为什么 Z 会受到透视分割的影响?

Why Z is affected by the perscpective division?

我最近意识到 OpenGL 不仅对 xy 执行透视分割,而且对 z 也执行透视分割。

以我的理解x /= w;y /= w;就足够了。当然,那我们就需要不同的投影矩阵了。

那么,为什么 OpenGL z /= w;?使 z-buffer 在短距离上更精确但在长距离上更不精确?

投影变换的作用是将物体从World Space移动到Projection Space(实际上是Camera Space before Projection space,但是它不在范围内)。

视觉上每隔一个 space 是一个从 -1 到 1 的立方体,而 The Projection space 是一个金字塔截面,近平面在 Z0 和 FarPlane 在 Z1(或 Z -1 取决于右手或左手系统)。所以 z 也会变形(除非你有正交投影)。 Z 从 0 变为 1,因为近平面后面的对象进入渲染管线没有任何意义。

您在评论中也提到了 Z 缓冲区精度。它的精度不会改变,但是,在投影变换之后,对象 Z 增量将在靠近远平面的对象之间变小,而在靠近近平面的对象之间变大(换句话说:对象之间 Z 轴上的距离靠近NearPlane的物体会增加,而靠近FarPlane的物体在Z轴上的距离会减小。

这就是为什么减少近平面和远平面距离有时会修复 Z 战斗的原因:如果两个平面之间的距离较小,则远处物体之间的距离将减少得更少。

从数学上讲,划分所有组件是正确的方法。这样,在屏幕 space 中线性插值 z (没有对位置数据进行透视正确插值,因为它应该在屏幕 [=21] 中插值=]). sceen space 中的线性插值当然意味着在眼睛或物体space 中看这个,它看起来是非线性的。它只是意味着对于一个不平行于图像平面的物体,在屏幕上向左移动一个像素意味着沿着 + 或 -z 移动一个变量,具体取决于距离 - 所以透视实际上也扭曲了 z 轴.

副作用是近平面的 Z 缓冲区精度最高,这对大多数场景来说实际上是一件好事。

使用"undivided" Z 进行深度测试称为W buffer。但这意味着不能再使用线性插值了。然而,对于现代 GPU,这不是什么大问题。