2009-09-10

Z Buffer or Depth Buffer.

在投影空间中,z的范围是[-1,+1]。在OpenGL中,默认情况下,最接近眼睛的片断(在近截面上)被映射到0.0,离眼睛最远的片断(在远截面上)映射到1.0。这个映射调整应该是线性的(没有查到正式文献)。当然,还可用glDepthRange调节深度值范围。

在正交投影中距离和Z值的关系是线性的,但在透视投影中却不是的。在透视投影中,情况发生了变化,还是看看映射公式:

z'= f(z)/w' = (Zfar+Znear) / ( Zfar – Znear ) + [2* Zfar*Znear / ( Zfar – Znear )]/z
这个映射是个双曲线:

下面来理解(http://www.cppblog.com/zmj/archive/2008/03/14/14122.html)给出的这几句话:
1. 在透视投影中这种关系是非线性的,而且非线性的程度与Frustum函数中的far/near(或gluPerspective函数中的zFar/zNear)成比例——也不是严格成比例,因为有一个Zfar*Znear 在。
2. 这种非线性在靠近近截面时增加了Z值的精度,而且增加了深度缓存的效率;但是在视见体的其它部分则降低了精度,也就减少了深度缓存的精确性——在上图,将[-Zfar,-Znear]之间等分,呵呵,靠近-Znear得到的Z’的范围显然大得多。
3. 根据经验,far/near比值大于1000会有这种不好的效果。所以一般far/near比值应小于1000。要想解决这个问题,最简单的方法是通过将近截面远离眼睛来降低far/near比值,其唯一的副作用是离眼睛很近的物体可能会被裁减掉,但在特定的应用程序中这很少是个问题,近截面的位置对X、Y坐标的投影没有影响,因此这对图像的影响很小——这个要牢记,呵呵。

没有评论: