我最近意识到OpenGL不仅针对x
和y
执行透视划分,也针对z
执行透视划分。
在我的理解x /= w;
和y /= w;
就足够了。当然,那么我们需要不同的投影矩阵。
那么,为什么OpenGL会z /= w;
?为了使z-buffer在短距离上更精确,但在长距离上更不精确?
答案 0 :(得分:1)
在数学上,划分所有组件是正确的方法。这样,在屏幕空间线性地插入z
(对于位置数据不进行透视正确插值,因为它应该在屏幕空间中插值)。
在场景空间中的线性插值当然意味着在眼睛或物体空间中观察它,它看起来是非线性的。它只是意味着一个不平行于图像平面的物体,在屏幕上向左移动一个像素确实意味着沿着+或-z向可变量移动,这取决于距离 - 所以这个视角实际上也会扭曲z轴
副作用是Z缓冲精度在近平面处最高,这对大多数场景来说实际上是一件好事。
使用"未分割的"深度测试的Z称为W buffer。但这意味着不能再使用线性插值。但是,对于现代GPU,这不是一个太大的问题。
答案 1 :(得分:0)
投影变换的作用是将对象从世界空间移动到投影空间(实际上它将是投影空间之前的相机空间,但它不在范围内)。
视觉上每隔一个空间是一个从-1到1的立方体,而投影空间是金字塔部分,近平面位于Z0,FarPlane位于Z1(或Z-1取决于右手或左手系统) )。所以z也变形(除非你有正交投影)。 Z从0变为1,因为对于近平面后面的对象进入渲染管道并没有任何意义。
你自己和评论中提到了Z Buffer的精度。它的精度不会改变,但是,在投影变换之后,物体Z增量在远处平面附近的物体之间会更小,而在靠近近平面附近的物体附近会更少(在较不发达的词中:物体之间Z轴上的距离)接近NearPlane将增加,而在FarPlane附近的物体之间的Z轴距离将减少。)
这就是为什么减少近平面和远平面距离有时会修复Z战斗:如果两个平面之间的距离较小,远距离物体之间的距离会减少。