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

18

我希望获得实际的世界空间距离,我的实验感觉是:

(gl_FragCoord.z / gl_FragCoord.w)

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

编辑 我刚刚在找到了我最初找到这段代码的地方。显然这是从相机到某个物体的实际深度?


我不确定你的问题具体是什么。你是在问 gl_FragCoord.z 的值是多少吗?还是在问 gl_FragDepth 的值应该是多少?或者只是想知道如何获取世界空间深度?后者需要解释一下你所说的世界空间深度是什么,因为“深度”通常被定义为到相机的平面距离。 - Nicol Bolas
1
如问题所述,我想要相机(或其近裁剪面,如果更合适)在世界空间单位中的实际距离。 - Engineer
3个回答

34
这是同一个人提出的问题,并且在其他地方得到了回答。我在这里进行了改述和补充:
OpenGL 4.3核心规范书(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 近/远值 转换为窗口坐标。 win.z = ((dfar-dnear)/2) * ndc.z + (dfar+dnear)/2

现在,使用默认的深度范围 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 已经给出了近/远范围) 并从中计算出 AB 值,或者你需要使用投影矩阵的逆矩阵。另外,你也可以直接使用投影矩阵本身,因为片元着色器可以使用顶点着色器可用的相同 uniform 变量。你可以直接从该矩阵中选择 AB 项。 A = projectionMatrix [2] [2]B = projectionMatrix [3] [2]


3
根据文档,以下是相关的IT技术内容:
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


1
不是这样的。这就是我最初想的。我只是用gl_FragDepth替换了我的方程中的gl_FragCoord.z(用于生成线性雾)来检查你的答案,结果整个场景无论距离远近都变成了黑色。而当我保留原始的gl_FragCoord.z时,我可以在一定距离后看到雾。 - Engineer
@NickWiggill:你不能质疑OpenGL规范。如果你的代码产生了那个结果,那么要么是你的代码有bug,要么是实现中存在bug。这就是规范中写的,因此OpenGL的行为就是如此。 - Nicol Bolas
1
@NickWiggill: 我不理解它背后的数学原理? 不理解它背后的数学原理 我不需要去反驳无意义的东西;规范就是规范,那个页面是错误的。 - Nicol Bolas
7
@NickWiggill说:“是的,那些宣传虚假信息,并对真实事实进行贬低的人会让我感到恼火。” - Nicol Bolas
3
您正在混淆输入变量和输出值。'gl_FragCoord.z'对您来说是可用的输入。但对于'gl_FragDepth'并非如此,它是一个输出值,必须由您填写。如果您不填写它,则规范说明它将自动填充为'gl_FragCoord.z'。您不应将'gl_FragDepth'用作输入。 - João Monteiro
显示剩余3条评论

1

作为

gl_FragCoord.w = 1.0 / gl_Position.w

根据你的说法(可能),你的投影矩阵从-z中获取w(如果最后一列是0,0,-1,0);
float distanceToCamera = 1.0 / gl_FragCoord.w;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接