深度测试
深度就是像素点在3d世界中距离相机的距离,深度缓存中存储着每个像素点的深度值,深度值越大,则离相机越远
深度缓存位数越高,精度越高 16、24、32位
事实上只要有深度缓冲区,无论是否开启深度测试,OpenGL都会尝试将深度数据写到缓冲区内,除非调用了glDepthMask(GL_FALSE)来禁止写入。
启用深度测试glEnable(GL_DEPTH_TEST)
默认情况是将需要绘制的新像素z值与深度缓冲区对应位置的z值进行比较,如果深度缓存中的值小,那么用新像素的颜色值更新帧缓存中对应像素的颜色值
但是可以使用glDepthFunc(func) 修改测试方式,有如下几种模式:
GL_NEVER(没有处理) GL_ALWARYS(处理所有) GL_LESS(小于) GL_LEQUAL(小于等于) GL_EQUAL(等于) GL_GEQUAL(大于等于) GL_GREATER(大于) 或 GL_NOTEQUAL(不等于) 默认GL_LESS
启用深度测试,不适用于同时绘制不透明物体
绘制半透明物体钱需要glDepthMask(GL_FALSE) 将缓冲区设置为只读形式,或关闭深度测试,绘制完半透明物体以后再开启深度测试,否则可能会出现绘制错误
因为半透明需要开启混合,而深度测试是发生在混合之前的,如果不关闭深度测试,在绘制完不透明物体后,在进行深度测试,有可能半透明物体直接被剔除掉了,
这样就无法绘制透明物体了
深度冲突(Z-Finghting or Depth Fighting)的解决
由于深度缓存都存在精度问题,所以会出现精度损失的问题, 所以当两个片面相近的时候,显示有可能混乱
这里有几个解决方案
1.使用Polygon offset 对绘制物体进行偏移
比如
A.Render()
glEnable(GL_POLYGON_OFFSET_FILL)
glPolygonOffset(0.0f,-1.0f);
B.Render()
glDisable(GL_POLYGON_OFFSET_FILL);
这个方法实际操作起来很麻烦,而且效率也不高,因为这两个物体必须独立出来渲染,增加了批次
我们可以调整远近裁面来解决这个问题
由于硬件只能支持一定的深度,也就是深度未D是固定的,dw(深度值)
dw/D = (far_clip - near_clip)/near_clip
想要dw更精细,那么必然要 far_clip 越小 near_clip 越大