在GLSL中获得真正的碎片深度

我正在尝试编写一个简单的GLSL着色器,将一个片段的真实(未标准化)深度呈现为浮点值。

到目前为止,我已经想出了如何获得顶点的深度,并且只是插入片段,但是我开始意识到这不会给我每个片段的正确深度,是吗?

以下是我到目前为止:

顶点着色器:

uniform mat4 world; uniform mat4 view; uniform mat4 projection; attribute vec3 position; attribute vec3 color; varying float distToCamera; void main() { vec4 cs_position = view * world * vec4(position, 1.0); distToCamera = -cs_position.z; gl_Position = projection * cs_position; } 

片段着色器:

 varying float distToCamera; void main() { gl_FragColor = vec4(distToCamera, distToCamera, distToCamera, 1.0); } 

是的,您的Z值distToCamera在每个三角形的顶点都是正确的,但由于线性插值的原因,将不会在其他任何地方(Z值匹配的顶点之间除外)。

编辑:在当前的GLSL中,默认插值是“透视”,其中gl_Position / gl_FragCoord被考虑用于插值。 这可以被覆盖(你不会想要为你的情况)作为types限定符,如:

 noperspective out float distToCamera; // vertex shader noperspective in float distToCamera; // fragment shader 

或者,你可以得到它从gl_FragCoord恢复…

在片段着色器中, gl_FragCoord在窗口坐标中包含(x, y, z, 1/w) 。 x,y和z已经被w除。

所以,你可以恢复你的顶点着色器输出, gl_Position.z ,在3D中正确插值,如

 float originalZ = gl_FragCoord.z / gl_FragCoord.w; 

(取决于你如何完成顶点着色器投影matrix,当然这可能不是你的世界Z.)