这是我正在使用的顶点着色器:
attribute vec3 v_pos;
attribute vec4 v_color;
attribute vec2 v_uv;
attribute vec3 v_rotation; // [angle, x, y]
uniform mat4 modelview_mat;
uniform mat4 projection_mat;
varying vec4 frag_color;
varying vec2 uv_vec;
varying mat4 v_rotationMatrix;
void main (void) {
float cos = cos(v_rotation[0]);
float sin = sin(v_rotation[0]);
mat2 trans_rotate = mat2(
cos, -sin,
sin, cos
);
vec2 rotated = trans_rotate * vec2(v_pos[0] - v_rotation[1], v_pos[1] - v_rotation[2]);
gl_Position = projection_mat * modelview_mat * vec4(rotated[0] + v_rotation[1], rotated[1] + v_rotation[2], 1.0, 1.0);
gl_Position[2] = 1.0 - v_pos[2] / 100.0; // Arbitrary maximum depth for this shader.
frag_color = vec4(gl_Position[2], 0.0, 1.0, 1.0); // <----------- !!
uv_vec = v_uv;
}
和片段:
varying vec4 frag_color;
varying vec2 uv_vec;
uniform sampler2D tex;
void main (void){
vec4 color = texture2D(tex, uv_vec) * frag_color;
gl_FragColor = color;
}
注意我是如何手动将gl_Position变量的Z索引设置为0.0 - &gt;范围内的绑定值。 1.0(上限在代码中完成;可以说,不是顶点具有z值&lt; 0或&gt; 100)。
它主要起作用。问题在于,当我渲染它时,我得到了这个:
这些元素的深度排序不正确,这些元素的z值分别为15,50和80,正如您可以从每个精灵的红色值中看到的那样。
呈现的正确顺序是蓝色 - &gt;顶部,紫色中间,粉红色底部;但是这些精灵正在以渲染顺序呈现。
即。它们是通过以下方式绘制的:
glDrawArrays() <--- Pink, first geometry batch
glDrawArrays() <--- Blue, second geometry batch
glDrawArrays() <--- Purple, thirds geometry batch
发生了什么事?
在冲洗之前我多少次调用gl绘制函数无关紧要;深度测试应该排除这一切吗?
您是否必须以某种方式在片段着色器内手动调用深度测试?
答案 0 :(得分:1)
您说您正在将输出Z值标准化为以下范围: 0.0 - 1.0 ?
它应该是范围: -W - + W 。给定正交投影,这意味着剪辑空间Z的范围应为: -1.0 - +1.0 。您只使用了深度范围的一半,这显着降低了深度缓冲区的分辨能力。
更糟糕的是(而且我很确定这是你实际问题的来源)看起来你通过给最远的点提供 0.0 的值来反转你的深度缓冲区,并且最接近分 1.0 。实际上, -1.0 对应于近平面, 1.0 对应于OpenGL中的远平面。
gl_Position[2] = 1.0 - v_pos[2] / 100.0;
~~~~~~~~~~~~~~
// This needs to be changed, your depth is completely backwards.
gl_Position.z = 2.0 * (v_pos.z / 100.0) - 1.0;
~~~~~~~~~~~~~
// This should fix both the direction, and use the full depth range.
但是,值得一提的是,现在gl_Position[2]
或gl_Position.z
的值范围从 -1.0 到 1.0 ,这意味着它不能是用作可见颜色而没有一些缩放和偏差:
frag_color = vec4 (gl_Position.z * 0.5 + 0.5, 0.0, 1.0, 1.0); // <----------- !!
最后,我一直在讨论规范化设备坐标,而不是窗口坐标。在窗口坐标系中,默认深度范围为0.0 =近,1.0 =远;这可能是一些混乱的根源。了解窗口坐标(gl_FragCoord
)与顶点着色器中的计算无关。
vec4 color = texture2D(tex, uv_vec) * vec4 (gl_FragCoord.z, frag_color.yzw);
它应该产生与以下相同的结果:
vec4 color = texture2D(tex, uv_vec) * frag_color;