深度
- 深度,就是像素点在3D世界中距离摄像机的距离,即Z值。
深度缓冲区
- 深度缓存区,就是⼀块内存区域,专门存储每个像素点的深度值。深度值(Z值)越⼤,则离摄像机就越远。
- 为什么需要深度缓冲区?
- 在不使⽤深度测试的时候,如果先绘制⼀个⽐较近的物体,再绘制较远的物体。较远的图像就会像油画一样覆盖掉之前的图像。有了深度缓冲区后,绘制物体的顺序就不那么重要了。只要通过开启了深度缓冲区,并允许深度值的写入,OpenGL都会把像素的深度值写入到缓冲区中。
例如上图中两个图形混合 混合部分会进行重新渲染
深度测试
深度缓冲区和颜⾊缓存区是对应的。颜⾊缓存区存储像素的颜⾊信息,而深度缓冲区存储像素的深度信息。
在决定是否绘制⼀个物体表⾯时,首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏⽐较。如果大于深度缓冲区中的值,则丢弃这部分;否则利⽤这个像素对应的深度值和颜⾊值,分别更新深度缓冲区和颜色缓存区。这个过程称为深度测试。
深度值的计算
深度值一般由16位,24位或者32位值表示,通常是24位。位数越高的话,深度的精确度越好。深度值的范围在[0,1]之间,值越小表示越靠近观察者,值越大表示远离观察者。
深度缓冲主要是通过计算深度值来比较⼤小,在深度缓冲区中包含深度值介于0.0和1.0之间, 从观察者看到其内容与场景中的所有对象的 z 值进行了⽐较。这些视图空间中的 z 值可以在投影平头截体的近平面和远平面之间的任何值。我们因此需要一些方法来转换这些视图空间 z 值 到 [0,1] 的范围内。
fa和near是提供到投影矩阵设置可见视图截锥的远近值。
非线性深度缓存
在实践中可以减少使用这样的线性深度缓冲区。正确的投影特性的非线性深度方程是和1/z成正比,由于非线性方程和1/z成正比,例如1.0和2.0之间的z值,将变为1.0到0.5之间,将z非常小的时候给了我们很高的精度。方程式如下图
在深度缓冲区的值不是线性的屏幕空间(它们在视图空间投影应用之间是线性)。值为0.5的深度缓冲区并不意味着该对象的z值投影上边的平头解体的中间;顶点的z值是实际上徐娘当接近平面!可以看到z值和产生深度缓冲区的值在下列图标中的线性关系
屏幕空间的深度值是非线性如他们在z很小的时候有很高的精度,较大的z值有较低的精度。该片段的深度值会迅速增加,几乎所有顶点的深度值接近1.0。如果我们⼩小⼼心的靠近物体,你最终可能会看到的色彩越来越暗,意味着它们的值越来越小,这清楚地表明深度值的非线性特性。近的物体相对远的物体对的深度值比对象较大的影响。只移动几英寸就能让暗色完全变亮。但是我们可以让深度值变换回线性。要实现这一⽬标我们需要让点应⽤用投影变换逆的逆变换,成为单独的深度值的过程。这意味着我 们必须⾸首先新变换范围 [0,1] 中的深度值为单位化的设备坐标(normalized device coordinates)范围内 [-1,1] (裁剪空间(clip space))。然后,我们想要反转⾮非线性⽅方程 。
深度值的使用
开启深度测试
glEnable(GL_DEPTH_TEST);
在绘制场景前,清除颜⾊缓存区,深度缓冲。清除深度缓冲区默认值为1.0。
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
指定深度测试判断模式
void glDepthFunc(GLEnum mode);
深度缓冲区写入开关
//value: GL_TURE,开启深度缓冲区写入; GL_FALSE,关闭深度缓冲区写⼊
void glDepthMask(GLBool value);