为什么在OpenGL的透视投影中要将Z除以W?

13

我想这更像是一个数学问题,而不是OpenGL问题,但我偏离了主题。无论如何,如果透视除法的整个目的是获取可用的x和y坐标,为什么要将z除以w?另外,我该如何获得w呢?


http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection - Oliver Charlesworth
这与齐次坐标有关。它们映射 R^3 -> R^4 显然不是一对一的。w因子可以“规范化”为1。但是应用4x4矩阵运算符后,结果的 'w'可能会发生变化。如果我没记错的话,齐次坐标的一个优点是将平移作为线性运算符。 - Yotam
在我看来,最简短的答案是 - 因为将 z 除以 w 最终会影响到 x 和 y 的值。在 gpu 管道的下一步中,您将通过将 x 和 y 除以 z 来获得 2D NDC 空间,该空间可以转换为屏幕坐标。 - mtx
1个回答

24
实际上,这个解释更多地与深度缓冲区的限制有关,而不是数学方面。
简单来说,“深度缓冲区是一种纹理,其中每个屏幕像素根据其距离相机的灰度值进行分配。这使得视觉效果可以轻松随着距离而改变。”来源 更准确地说,深度缓冲区是一个包含每个片段z/w值的纹理,其中:
  • Z是从近裁剪平面到片段的距离。
  • W是从相机到片段的距离。
在下面的图示中,展示了zwz/w之间的关系,其中n等于传递给gluPerspective或等效函数的zNear参数,而f等于传递给同一函数的zFar参数。

Diagram illustrating the relationship between *z*, *w*, and *z*/*w*

这个系统一眼看上去不直观。但是结果是,z/w 总是一个介于0和1(0/nf/f)之间的浮点数值,因此可以表示为纹理的单通道。
第二个重要的注意事项:深度缓冲是非线性的,这意味着在近剪切平面和远剪切平面之间的物体在深度缓冲中的值并不接近0.5。如上所示,它将对应于深度缓冲中的0.999。根据您的视图,这可能是好事还是坏事;您可能希望深度缓冲在近距离时更详细(它确实如此),或者始终提供相同的细节(它没有做到)。
简而言之:
- 您将z除以w,使其始终在[0,1]范围内。 - W是从相机到片段的距离。

5
我并不完全同意这个回答,该问题与纯粹的数学问题有关,而这里所解释的是OpenGL和Z缓冲算法的实现细节(深度缓冲区)。 - Harald Scheirich
NDC中的z值范围为[-1, 1],而不是DirectX约定的[0, 1]。 - t0rakka
为什么在最远的片段中,w和z都是f?w和z起始点之间有“n”距离。谢谢。 - willSapgreen
Z是近裁剪平面到片段的距离。W是相机到片段的距离。我认为这些句子同样适用于DirectX。 - KeyC0de

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