为什么此glsl着色器不考虑深度索引?

为什么此glsl着色器不考虑深度索引?,glsl,shader,Glsl,Shader,这是我目前正在使用的顶点着色器: 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_ro

这是我目前正在使用的顶点着色器:

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;
}
请注意,我是如何手动将gl_Position变量的Z索引设置为0.0->1.0范围内的一个界限值(上限是在代码中完成的;可以安全地说,不是顶点的Z值小于0或大于100)

它是有效的。。。大部分。问题是,当我渲染它时,我得到以下结果:

这不是这些元素的正确深度排序,它们的z值分别为15、50和80,从每个精灵的红色值可以看出

渲染的正确顺序为蓝色->顶部、紫色中间和粉色底部;但是,这些精灵将按渲染顺序进行渲染

也就是说,它们是通过以下方式绘制的:

glDrawArrays() <--- Pink, first geometry batch
glDrawArrays() <--- Blue, second geometry batch
glDrawArrays() <--- Purple, thirds geometry batch

glDrawArrays()您说要将输出Z值规格化到以下范围:0.0-1.0

它应该是范围:-W-+W。给定正交投影,这意味着剪辑空间Z的范围应为:-1.0-+1.0。您只使用了深度范围的一半,这大大降低了深度缓冲区的分辨率

更糟糕的是(我很确定这就是您实际问题的根源),看起来您正在通过将最远点的值设置为0.0和最近点的值设置为1.0来反转深度缓冲区。实际上,-1.0对应于OpenGL中的近平面,1.0对应于远平面

gl_位置[2]=1.0-v_位置[2]/100.0;
~~~~~~~~~~~~~~
//这需要改变,你的深度是完全向后的。
gl_位置z=2.0*(v_位置z/100.0)-1.0;
~~~~~~~~~~~~~
//这将固定两个方向,并使用整个深度范围。
然而,值得一提的是,现在
gl_Position[2]
gl_Position.z
的值范围为-1.01.0,这意味着如果没有一些缩放和偏置,它不能用作可见颜色:


frag_color=vec4(gl_Position.z*0.5+0.5,0.0,1.0,1.0);//Z指数?对我来说,这意味着很多不同的东西(整数向量)。但我想,既然您使用的是数组下标表示法而不是更常见的swizzle表示法(例如,
[2]
而不是
.z
),您就会这样想。为了清晰起见,我会把它称为<代码> z <代码>组件或<代码>第三>代码>组件(而不是索引)。在任何情况下,您是否使用透视投影?如果是,则应将红色分量除以
W
,使其与后期透视深度匹配。正确,这是z坐标,而不是z索引;我之所以使用这个名字,仅仅是因为这是一个正交投影,z值取离散的整数值;但是,它们在交错数组(vec3 v_pos)的z分量中作为浮点值传递。如图所示,红色部分被正确地呈现为图上的深度。奇怪的是,这实际上是正确的。使用:gl_位置[2]=-1.0+v_位置[2]/50.0;使它们以正确的深度顺序渲染。在我看来,这完全是一种怪诞;使用一半深度范围和整个深度范围之间的差异会产生差异吗?我真的不明白。。。但是成功了,谢谢@道格:其实这是两件事的结合,你在正确的方向上使用深度缓冲区,同时也在使用深度缓冲区的全部范围。几乎可以肯定的是,将深度存储在正确的方向上是解决问题的方法。
glDrawArrays() <--- Pink, first geometry batch
glDrawArrays() <--- Blue, second geometry batch
glDrawArrays() <--- Purple, thirds geometry batch