OpenGL学习笔记(十九)

深度值精度

深度缓冲包含了一个介于0.0和1.0之间的深度值,它将会与观察者视角所看见的场景中所有物体的z值进行比较。观察空间的z值可能是投影平截头体的近平面(Near)和远平面(Far)之间的任何值。我们需要一种方式来将这些观察空间的z值变换到[0, 1]范围之间,其中的一种方式就是将它们线性变换到[0, 1]范围之间。下面这个(线性)方程将z值变换到了0.0到1.0之间的深度值:
depth=(z−near)/(far−near)

这里的near和far值就是提供给投影矩阵设置可视平截头体的那个 near 和 far 值。这个方程需要平截头体中的一个z值,并将它变换到了[0, 1]的范围中。

然而,在实践中是几乎永远不会使用这样的线性深度缓冲(Linear Depth Buffer)的。想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。它做的就是在z值很小的时候提供非常高的精度,而在z值很远的时候提供更少的精度。可以想象一下:我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?线性方程并不会考虑这一点。

由于非线性方程与 1/z 成正比,在1.0和2.0之间的z值将会变换至1.0到0.5之间的深度值,这就是一个float提供给我们的一半精度了,这在z值很小的情况下提供了非常大的精度。在50.0和100.0之间的z值将会只占2%的float精度,这正是我们所需要的。这样的一个考虑了远近距离的方程是这样的:
depth=(1/z−1/near)/(1/far−1/near)

如果不知道这个方程是怎么回事也没关系,重要的是要记住深度缓冲中的值在屏幕空间中不是线性的(在透视矩阵应用之前在观察空间中是线性的)。深度缓冲中0.5的值并不代表着物体的z值是位于平截头体的中间了,这个顶点的z值实际上非常接近近平面。

深度值很大一部分是由很小的z值所决定的,这给了近处的物体很大的深度精度。这个(从观察者的视角)变换z值的方程是嵌入在投影矩阵中的,所以当我们想将一个顶点坐标从观察空间至裁剪空间的时候这个非线性方程就被应用了。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页