Android 深度测试在平移时起作用,但在指定z坐标(2D渲染)时不起作用 问题

Android 深度测试在平移时起作用,但在指定z坐标(2D渲染)时不起作用 问题,android,opengl-es,depth-buffer,opengl-es-3.0,Android,Opengl Es,Depth Buffer,Opengl Es 3.0,似乎我在Android OpenGL ES 3.0中发现了深度测试的问题。 要么是这样,要么我有一个实现缺陷。我注意到,当我通过修改模型矩阵转换几何体时,深度测试工作正常;但是,当我尝试通过在几何体中指定位置数据来执行相同操作时,深度测试失败。最后渲染的几何体显示在先前渲染的几何体后面。 我的目标是执行2D渲染,使每个像素对应于世界空间中的1个单位。为此,我对glViewport和Matrix.orthoM进行了以下调用,以设置投影矩阵: GLES30.glViewport(0, 0, wid

似乎我在Android OpenGL ES 3.0中发现了深度测试的问题。 要么是这样,要么我有一个实现缺陷。我注意到,当我通过修改模型矩阵转换几何体时,深度测试工作正常;但是,当我尝试通过在几何体中指定位置数据来执行相同操作时,深度测试失败。最后渲染的几何体显示在先前渲染的几何体后面。
我的目标是执行2D渲染,使每个像素对应于世界空间中的1个单位。为此,我对
glViewport
Matrix.orthoM
进行了以下调用,以设置投影矩阵:

GLES30.glViewport(0, 0, width, height);
Matrix.orthoM(projectionMatrix, 0, 0, width, 0, height, 0, 10.0f);
这将导致投影使用
TextureView的全宽和全高,并提供10个单位深度的剪辑空间(z轴)

在曲面创建期间,我确保启用深度测试(使用默认深度功能):

最后但并非最不重要的一点是,我还确保清除每个绘图帧的深度缓冲区:

GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
上述调用应设置深度缓冲。剩下的就是定义一个视图矩阵,在渲染任何几何体之前,在每个绘图帧中执行以下操作:

Matrix.setLookAtM(viewMatrix, 0, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
这些参数指定
eyePosition={0.0f,0.0f,1.0f}
,它远离屏幕(朝向观看者),眼睛注视着
centerPosition={0.0f,0.0f,0.0f}
,这是世界的起源。该视图矩阵应仅将摄影机移离场景而不旋转(因为我是在2D中渲染的)。

使用模型矩阵转换几何图形: 通过使用模型矩阵转换几何体,我可以有效地使深度测试正常工作。几何体根据指定的z索引按顺序渲染

在draw函数中,以下代码对我希望绘制的每个矩形(钢琴键)执行:

Matrix.setIdentityM(modelMatrix, 0);
if (keys[index].keyType == WHITE_KEY) {
    Matrix.translateM(modelMatrix, 0, 0.0f, 0.0f, keys[index].zIndex);
} else {
    Matrix.translateM(modelMatrix, 0, 0.0f, 0.0f, keys[index].zIndex);
}
Matrix.translateM(modelMatrix, 0, translateX, 0.0f, 0.0f);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "model"), 1, false, modelMatrix, 0);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "view"), 1, false, viewMatrix, 0);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "projection"), 1, false, projectionMatrix, 0);

keys[index].draw();
这会给出正确的结果。请注意,所有黑色关键点都显示在顶部,即使所有关键点都是按从左到右的顺序渲染的

使用位置数据转换几何图形: 我希望在矩形的实际顶点数据中指定z索引。因此,我不使用上述渲染代码,而是使用以下代码:

Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix, 0, translateX, 0.0f, 0.0f);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "model"), 1, false, modelMatrix, 0);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "view"), 1, false, viewMatrix, 0);
GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(shaderProgram, "projection"), 1, false, projectionMatrix, 0);

keys[index].draw();
请注意,唯一的区别是我不再根据z索引值平移几何体。相反,我在实际顶点数据中指定z索引:

float[] vertexData = new float[] {
        x, y, zIndex, //Specify z-index in vertex data.
        0, 0, //Texture coordinates.
        x + width, y, zIndex, //Specify z-index in vertex data.
        1, 0, //Texture coordinates.
        x, y + height, zIndex, //Specify z-index in vertex data.
        0, 1, //Texture coordinates.
        x + width, y + height, zIndex, //Specify z-index in vertex data.
        1, 1  //Texture coordinates.
};

int[] indexData = new int[] {
        0, 1, 3,
        0, 3, 2
};

//Set up VAO, VBO, and EBO with the data above (works properly, but is
//provided for the sake of completion).
FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
        .order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexData).position(0);

IntBuffer indexBuffer = ByteBuffer.allocateDirect(indexData.length * 4)
        .order(ByteOrder.nativeOrder()).asIntBuffer();
indexBuffer.put(indexData).position(0);

GLES30.glGenVertexArrays(1, vao, 0);
GLES30.glGenBuffers(1, vbo, 0);
GLES30.glGenBuffers(1, ebo, 0);

GLES30.glBindVertexArray(vao[0]);

GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexData.length * 4, vertexBuffer, GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indexData.length * 4, indexBuffer, GLES30.GL_STATIC_DRAW);

//Point to vertex positions (stride = size of vertex in bytes = 5 components *4 bytes per float = 20)
GLES30.glEnableVertexAttribArray(0);
GLES30.glVertexAttribPointer(0, 2, GLES30.GL_FLOAT, false, VERTEX_STRIDE, 0);

GLES30.glEnableVertexAttribArray(1);
GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, VERTEX_STRIDE, VERTEX_POSITION_COMPONENTS * 4);

GLES30.glBindVertexArray(0);
删除翻译后,我收到以下结果。请注意,最后一个关键点渲染在前一个关键点之后,尽管我们从左到右渲染它们。还请注意,对于白键,
zIndex=-1.0f
,而对于黑键,
zIndex=0.0f
。这将导致白键比黑键更深入屏幕。在提供给
Matrix.orthoM
的剪裁空间内,两个键都应可见(由于视图矩阵从屏幕上平移了1个单位,因此有效zNear和zFar值分别为
1.0f
-9.0f


问题: 我需要做什么才能在顶点数据中指定
zIndex
,同时获得正确的深度测试结果?

代码 顶点着色器

#version 300 es

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);

    //Pass texture coordinate to fragment shader.
    TexCoord = texCoord;
}
#version 300 es

in vec2 TexCoord;

out vec4 color;

uniform sampler2D texture;

void main()
{
    vec2 flippedTexCoord = vec2(TexCoord.x, 1.0 - TexCoord.y);
    color = texture(texture, flippedTexCoord);
}
片段着色器

#version 300 es

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);

    //Pass texture coordinate to fragment shader.
    TexCoord = texCoord;
}
#version 300 es

in vec2 TexCoord;

out vec4 color;

uniform sampler2D texture;

void main()
{
    vec2 flippedTexCoord = vec2(TexCoord.x, 1.0 - TexCoord.y);
    color = texture(texture, flippedTexCoord);
}

您正在将“位置”属性设置为只有两个组件:

GLES30.glVertexAttribPointer(0, 2, GLES30.GL_FLOAT, false, VERTEX_STRIDE, 0);
第二个参数指定组件的数量。所以这应该是:

GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, VERTEX_STRIDE, 0);
或者,由于您似乎为此目的定义了一个常量,您不妨在此处使用它:

GLES30.glVertexAttribPointer(0, VERTEX_POSITION_COMPONENTS, GLES30.GL_FLOAT, false, VERTEX_STRIDE, 0);

您是否尝试过在顶点数据中输入“-1.0”表示黑色关键点,输入0.0表示白色关键点!但这并不能解决问题。虽然这是有意义的,如果出于某种原因,相机是向后的…而且,我想知道你如何有5个组件在vertexdata数组中的每个顶点。x、 y、z、0、1每个顶点由3个位置组件和2个纹理坐标组件组成(请注意,步长用于顶点属性指针)。为了简单起见,我尽量避免发布所有代码。已编辑,包含更多注释;)事实的确如此。我敢说那个部分工作正常,所以我很高兴你不信任我!对此过于本地化表示歉意,希望它能帮助其他人。