一、概念
-
深度:深度其实就是该像素点在3D世界中距离摄像机的距离,Z值。
-
深度缓冲区:深度缓存区,就是一块内存区域,专⻔存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越大, 则离摄像机就越远.
-
深度缓冲区的作用:在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么重要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写入到缓冲区中. 除非调⽤glDepthMask(GL_FALSE).来禁止写入.
-
深度测试:深度缓冲区(DepthBuffer)和颜色缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜⾊信息,⽽深度缓冲区存储像素的深度信息. 在决定是否绘制一个物体表面时, 首先要将表面对应的像 素的深度值与当前深度缓冲区中的值进⾏行比较. 如果⼤于深度缓冲区中的值,则丢弃这部分.否则 利用这个像素对应的深度值和颜色值.分别更新深度缓冲区和颜色缓存区. 这个过程称为”深度测试”。
-
深度值计算
深度值⼀般由16位,24位或者32位值表示,通常是24位。位数越⾼高的话,深度的精确度越好。深度缓冲主要是通过计算深度值来比较⼤小,在深度缓冲区中包含深度值介于 0.0 和 1.0 之间, 从观察者看到其内容与场景中的所有对象的 z 值进⾏了⽐较。这些视图空间中的 z 值可以在投影平头截体的近平面和远平面之间的任何值。我们因此需要一些方法来转换这些视图空间 z 值到 [0,1] 的范围内,下面的 (线性) 方程把 z 值转换为 0.0 和 1.0 之间的值 :

二、使用深度测试
深度测试主要函数
开启深度测试
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);
函数说明
GL_ALWAYS 总是通过测试
GL_NEVER 总是不通过测试
GL_LESS 在当前深度值 < 存储的深度值时通过
GL_GREATER 在当前深度值 > 存储的深度值时通过
GL_EQUAL 在当前深度值 == 存储的深度值时通过
GL_LEQUAL 在当前深度值 <= 存储的深度值时通过
GL_GEQUAL 在当前深度值 >= 存储的深度值时通过
GL_NOTEQUAL 在当前深度值 != 存储的深度值时通过
深度缓冲区写入开关
//value: GL_TURE,开启深度缓冲区写入; GL_FALSE,关闭深度缓冲区写⼊
void glDepthMask(GLBool value);
三、正背面剔除问题解决
到这里上图中正背面剔除弊端的问题就迎刃而解了,开启深度测试将新旧深度值的对比,决定像素点是绘制还是丢弃,就不会出现分不清正背面的问题了。
设置深度测试开关
开启和关闭的逻辑,主要取决于右键菜单的点击次数,第一次打开,第二次关闭,以此类推
//根据设置iDepth标记来判断是否开启深度测试
if(iDepth)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
四、深度测试ZFighting闪烁问题
开启深度缓冲区后,由于深度值精度的限制,对于相差非常小的深度值(比如在同一个深度进行2次渲染),就可能出现不能正确区分两个深度值的问题,导致测试的结果随机出现。所以,显示时2个画⾯交错出现,就会出现闪烁问题。如下图所示:

1. 解决方案 — 多边形偏移(Polygon Offset)
其问题产生的主要原因是由于图形靠的太近,导致无法区分出图层先后次序,针对该问题,OpenGL提供了一种多边形偏移(Polygon Offset)
方案
- 启用
多边形偏移(Polygon Offset)
glEnable(GL_POLYGON_OFFSET_FILL)
多边形偏移枚举值 | 对应的光栅化模式 |
---|---|
GL_POLYGON_OFFSET_FILL | GL_FILL |
GL_POLYGON_OFFSET_LINE | GL_LINE |
GL_POLYGON_OFFSET_POINT | GL_POINT |
- 指定偏移量 (参数一般填 -1 和 -1)
void glPolygonOffset(Glfloat factor, Glfloat units);
- 关闭
多边形偏移(Polygon Offset)
// 参数和开启的参数相同
glDisable(GL_POLYGON_OFFSET_FILL);
2. 问题预防
-
不要将两个物体靠的太近。
避免渲染时三⻆形叠在一起。 -
尽可能将近裁剪面设置得离观察者远一些。
如果观察者离近裁剪平⾯很近,那么深度测试对精确度要求很⾼。因此,可以适当推远近裁剪平⾯的位置来避免这个问题,但是可能导致离观察者较近的物体被裁减掉,使用时需要小心。 -
使用更高位数的深度缓冲区。
默认的深度缓冲区精度是24位的,如果硬件支持32位的缓冲区,就可以提供更高的精度。
网友评论