c++ - 为什么我在 OpenGL 的透视投影中将 Z 除以 W?

标签 c++ opengl math matrix

我想这与其说是一个 OpenGL 问题,不如说是一个数学问题,但我离题了。无论如何,如果透视除法的全部目的是获得可用的 x 和 y 坐标,为什么还要用 w 除以 z?另外,我如何首先获得 w?

最佳答案

实际上,解释更多的是与深度缓冲区的限制有关,而不是数学。

简单来说,“深度缓冲区是一种纹理,其中每个屏幕上的像素都根据其与相机的距离分配一个灰度值。这使得视觉效果可以随距离轻松改变。” Source

更准确地说,深度缓冲区是包含每个 fragmentz/w 值的纹理。 ,其中:

  • Z 是近裁剪平面到片段的距离。
  • W 是相机到片段的距离。

在下图中说明了 zwz/w 之间的关系,n 等于传递给 gluPerspectivezNear 参数,或等效函数,f 等于传递给同一函数的 zFar 参数。

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

乍一看,这个系统看起来不直观。但结果是,z/w 始终是介于 0 和 1 之间的浮点值(0/nf/f),因此可以表示为纹理的单个 channel 。

第二个重要注意事项:深度缓冲区是非线性的,这意味着恰好位于近距和远距裁剪平面之间的对象在深度缓冲区中远不接近 0.5 的值。如上所示,它与深度缓冲区中的值 0.999 相关。根据您的看法,这可能是好事也可能是坏事;您可能希望深度缓冲区是更详细的特写镜头(它确实如此),或者甚至在整个过程中提供细节(它没有)。

长话短说:

  • 您将 z 除以 w,因此它始终在 [0, 1] 范围内。
  • W 是相机到片段的距离。

关于c++ - 为什么我在 OpenGL 的透视投影中将 Z 除以 W?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25584667/

相关文章:

c++ - 设置来自系统 ("command"的变量) (C++)

c++ - 在另一个类中使用一个类的静态对象

c++ - 具有最短路径的四元数 slerp 不起作用

opengl - glsl算术运算符

c# - 这段 C# 代码如何得出答案?

c - 基本C程序,巴比伦算法

c++ - 使用评估为 None 类型的弱指针

c++ - 如何复制directshow的SampleCB中的示例数据?

c++ - 渲染到帧缓冲区/纹理显示为空

algorithm - 对数大 O 与平方根