(gl_FragCoord.z / gl_FragCoord.w)代表什么?

时间:2012-12-04 20:24:25

标签: opengl glsl

我想要实际的世界空间距离,我从实验中得到感觉

(gl_FragCoord.z / gl_FragCoord.w)

是世界空间的深度吗?但我不太确定。

编辑我刚刚found where I had originally located this snippet of code。显然它是相机的实际深度?

3 个答案:

答案 0 :(得分:21)

这是(由同一个人)和answered elsewhere提出的。我在这里解释和修饰答案:

OpenGL 4.3 core profile specification (PDF)第15.2.2节所述,gl_FragCoord.w1 / clip.w,其中clip.w是剪辑空间位置的W分量(即:什么你写信给gl_Position)。

假设通常的变换,

gl_FragCoord.z由以下过程生成:

  1. 相机空间到剪辑空间变换,通过顶点着色器中的投影矩阵乘法。 clip.z = (projectionMatrix * cameraPosition).z
  2. 转换为规范化设备坐标。 ndc.z = clip.z / clip.w
  3. 使用glDepthRange near/far values转换为窗口坐标。 win.z = ((dfar-dnear)/2) * ndc.z + (dfar+dnear)/2
  4. 现在,使用near = 0,far = 1的默认深度范围,我们可以根据剪辑空间定义win.z(clip.z/clip.w)/2 + 0.5。如果我们将其除以gl_FragCoord.w,则相当于乘以clip.w,从而为我们提供:

    (gl_FragCoord.z / gl_FragCoord.w) = clip.z/2 + clip.w/2 = (clip.z + clip.w) / 2
    

    使用标准投影矩阵,clip.z表示相机空间Z分量的比例和偏移。比例和偏移由相机的近/远深度值定义。 clip.w再次在标准投影矩阵中,只是对相机空间Z的否定。因此,我们可以用这些术语重新定义我们的等式:

    (gl_FragCoord.z / gl_FragCoord.w) = (A * cam.z + B -cam.z)/2 = (C * cam.z + D)
    

    其中AB代表基于近/远的偏移和比例,以及C = (A - 1)/2D = B / 2

    因此,gl_FragCoord.z / gl_FragCoord.w 与相机的相机空间(或世界空间)距离。也不是摄像机空间与摄像机的平面距离。但它相机空间深度的线性变换。您可以将它用作将两个深度值进行比较的方法,如果它们来自相同的投影矩阵,等等。

    要实际计算相机空间Z,您需要将相机从矩阵附近/远处传递(OpenGL already gives you the range near/far)并从中计算这些AB值,或者你需要使用投影矩阵的逆。或者,您可以直接使用投影矩阵,因为片段着色器可以使用顶点着色器可用的相同制服。您可以直接从该矩阵中选择AB字词。 A = projectionMatrix[2][2]B = projectionMatrix[3][2]

答案 1 :(得分:1)

根据the docs

Available only in the fragment language, gl_FragDepth is an output variable that
is used to establish the depth value for the current fragment. If depth buffering
is enabled and no shader writes to gl_FragDepth, then the fixed function value
for depth will be used (this value is contained in the z component of
gl_FragCoord) otherwise, the value written to gl_FragDepth is used.

因此,看起来gl_FragDepth应该只是gl_FragCoord.z,除非您已将其设置在着色器中的其他位置。

答案 2 :(得分:0)

作为

gl_FragCoord.w = 1.0 / gl_Position.w

并且(可能)你的投影矩阵从-z得到w(如果最后一列是0,0,-1,0)那么;

float distanceToCamera = 1.0 / gl_FragCoord.w;