java - 如何在 opengl es 2.0 中设置 2D 游戏的深度范围?

标签 java android opengl-es

所以我目前正在开发一个 Android 2D 游戏项目,我正在使用 Opengl ES 2.0。我猜我有一个默认范围从 0.0 到 1.0 的深度缓冲区,但我想将其扩展到 0.0 - 100.0。我尝试使用 GLES20.glDepthRangef,但它似乎对我不起作用。 Z 值超出范围:0.0 - 1.0 的图像不会显示在屏幕上。我错过了什么吗?我将不胜感激您的帮助!

private final float[] mtrxProjection = new float[16];
private final float[] mtrxView = new float[16];
private final float[] mtrxProjectionAndView = new float[16];

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

        //current width and height.
        swp = width;
        shp = height;

        // Redo the Viewport, making it fullscreen.
        GLES20.glViewport(0, 0, (int)swp, (int)shp);

        // Clear our matrices
        for(int i=0;i<16;i++)
        {
            mtrxProjection[i] = 0.0f;
            mtrxView[i] = 0.0f;
            mtrxProjectionAndView[i] = 0.0f;
        }

        // Setup our screen width and height for normal sprite translation.
        Matrix.orthoM(mtrxProjection, 0, 0f, swp, 0.0f, shp, 0, 100);

        // Depth testing
        GLES20.glEnable( GLES20.GL_DEPTH_TEST );
        GLES20.glDepthFunc( GLES20.GL_LEQUAL );
        GLES20.glDepthMask( true ); 
        GLES20.glDepthRangef(0,  100);

        // Set the camera position (View matrix)
        Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        // Calculate the projection and view transformation
        Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);
}

这是我的顶点着色器:

public static final String vs_Image =
        "uniform mat4 u_MVPMatrix;" + // u_MVPMatrix is the mtrxProjectionAndView calculated above
        "attribute vec4 a_position;" +
        "attribute vec2 a_texCoord;" +
        "varying vec2 v_texCoord;" +
        "void main() {" +
        "  gl_Position = u_MVPMatrix * a_position;" +
        "  v_texCoord = a_texCoord;" +
        "}";

最佳答案

glDepthRange() 的参数需要在 0.0 到 1.0 范围内。其工作原理是 0.0 到 1.0 代表深度缓冲区的整个可用范围。 glDepthRange() 可用于将深度值仅映射到完整可用范围的子范围,但它无法扩展可用范围。

控制映射到深度缓冲区范围的坐标范围的方法是在顶点着色器中应用变换。 gl_Position 中生成的顶点着色器的输出坐标为剪辑坐标,通过将位置的 x、y 和 z 除以 w 坐标,将其转换为标准化设备坐标 (NDC),其中通常称为透视划分。然后映射到深度缓冲区范围的 NDC 中的 z 值范围为 [-1.0, 1.0]。

在您的特定顶点着色器中,您可以通过将输入位置乘以 u_MVPMatrix 来获得 gl_Position。要解决您的问题,您需要确保正确设置该矩阵。使用 glDepthRange() 不是您正在寻找的解决方案。

通过投影矩阵,您已经在 z 方向设置了 100 个单位的范围,这看起来与您的目标一致:

Matrix.orthoM(mtrxProjection, 0, 0f, swp, 0.0f, shp, 0, 100);

问题似乎出在您的 View 矩阵上:

Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

第三个到第五个参数是视点,即您的调用中的 (0.0, 0.0, 1.0)。第 6 个到第 8 个参数是您正在查看的点,即调用中的 (0.0, 0.0, 0.0)。因此,您从 z 轴上距离原点一个单位的点向原点看。由于投影矩阵给出的总 z 范围为 100 个单位,因此 View 体积中 z 值的范围为 [-99.0, 1.0]。

如果您希望可见 z 范围为 [0.0, 100.0],则需要将 View 矩阵中的视点调整为距原点 100 个单位。调用将如下所示:

Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 100f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

现在您从点 (0.0, 0.0, 100.0) 向原点看,范围由投影矩阵给出 100 个单位。这将为您提供 z 坐标的 [0.0, 100.0] 可见范围。

关于java - 如何在 opengl es 2.0 中设置 2D 游戏的深度范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25095005/

相关文章:

c++ - 在 Windows 上开始使用 OpenGL ES 2.0

java - 在调试 Java 代码时,@ 在 {Instance@789} 或 "SomeThread"@321 : RUNNING? 等语句中的含义是什么

java - Java 类文件的创建是确定性的吗?

Java 8 日期时间解析,可选 2-4 年组件

java - 如何在scanner.nextDouble()中使用两个分隔符? java

android - 有没有可能用安卓来控制继电器?

iOS Metal : Jaggies Anit-aliasing

javascript - 通过电子邮件中的链接打开 Nativescript Android 应用程序

java - 如何使状态 View 突出显示和超链接

java - Android流畅的游戏循环