OpenGL 学习之 深度测试的理解

2,195 阅读4分钟

什么是深度?

深度其实就是该像素点在3D世界中距离摄像机的距离,Z值

什么是深度缓冲区?

深度缓存区,就是一块内存区域,专门存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越大, 则离摄像机就越远.

为什么需要深度缓冲区?

在不使用深度测试的时候,如果我们先绘制一个距离比较近的物理,再绘制距离较远的物理,则距离远的位图因为后绘制,会把距离近的物体覆盖掉.有了深度缓冲区后,绘制物体的顺序就不那么􏰁要的.实际上,只要存在深度缓冲区,OpenGL都会写入到缓冲区中. 除非调⽤ glDepthMask(GL_FALSE).来禁⽌止写⼊.

两个图形混合 混合部分会进行重新渲染

深度测试

深度缓冲区(DepthBuffer)和颜⾊色缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜色信息,而深度缓冲区存储像素的深度信息.在决定是否绘制一个物体表⾯面时, 首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏比较.如果大于深度缓冲区中的值,则丢弃这部分.否则利用这个像素对应的深度值和颜色值.分别更新深度缓冲区和颜色缓存区. 这个过程称为”深度测试”

深度值计算

  • 深度值一般由16位 ,24位 或者32位值来表示 ,通常是24位。位数越高的话。深度值就越精确。深度值范围在[0,1]之间,值越小表示越靠近观察者,值越大表示远离观察者。
  • 深度缓冲主要是通过计算深度值来比较大小,在深度缓冲区中包含深度值介于0.0和1.0之间,从观察者看到其内容与场景中的所有对象的z值进行来比较。这些视图空间中的z值可以在投影到平头截体的近平面远平面之间的任何值。我们因此需要一些方法来转换这些视图空间z值到[0,1]的范围内。下面的(线性)方程把z值转换为0.0和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))。然后,我们想要反转⾮非线性⽅方程 。

使用深度测试

深度缓冲区,一般由窗口管理系统,GLFW创建.深度值一般由16位,24位,32位值表示. 通常是24位.位数越⾼高,深度精确度更更好. 开启深度测试

glEnable(GL_DEPTH_TEST)

在绘制场景前,清除颜色缓冲区, 深度缓冲

glear(0.f,0.f,0.f,1.0f)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

清除深度缓冲区默认值为1.0,深度值范围为(0,1)之间. 值越小表示越靠近观察者,值越⼤大表示 越远离观察者

指定深度测试判断模式

void glDepthFunc(GLEnum mode)

打开/关闭深度hu缓冲区写入

void glDepthMask(GLBool Value)
value :GL_TURE 开启深度缓冲区写入,GL_False 关闭深度缓冲区写入