OpenGL深度测试

1. 深度缓冲(Depth Buffer)

深度缓冲是由窗口系统自动创建的,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位的。
当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。如果深度测试失败了,片段将会被丢弃。
深度缓冲是在片段着色器运行之后在屏幕空间中运行的。屏幕空间坐标与通过OpenGL的glViewport所定义的视口密切相关,并且可以直接使用GLSL内建变量gl_FragCoord从片段着色器中直接访问。gl_FragCoord的x和y分量代表了片段的屏幕空间坐标(其中(0, 0)位于左下角)。gl_FragCoord中也包含了一个z分量,它包含了片段真正的深度值。z值就是需要与深度缓冲内容所对比的那个值。

2. 深度缓冲实现

1.启用深度缓冲

深度测试默认是禁用的,所以如果要启用深度测试的话,需要用GL_DEPTH_TEST选项来启用它,当它启用的时候,如果一个片段通过了深度测试的话,OpenGL会在深度缓冲中储存该片段的z值;如果没有通过深度缓冲,则会丢弃该片段。

glEnable(GL_DEPTH_TEST);

2.深度测试函数

可以调用glDepthFunc函数来设置深度函数,默认为glDepthFunc(GL_LESS);

函数 描述
GL_ALWAYS 永远通过深度测试
GL_NEVER 永远不通过深度测试
GL_LESS 在片段深度值小于缓冲的深度值时通过测试
GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试
GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试
GL_GREATER 在片段深度值大于缓冲区的深度值时通过测试
GL_NOTEQUAL 在片段深度值不等于缓冲区的深度值时通过测试
GL_GEQUAL 在片段深度值大于等于缓冲区的深度值时通过测试

3.渲染循环中清除深度缓冲

启用了深度缓冲,你还应该在每个渲染迭代之前使用GL_DEPTH_BUFFER_BIT来清除深度缓冲,否则你会仍在使用上一次渲染迭代中的写入的深度值:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

使用一个只读的(Read-only)深度缓冲,OpenGL允许我们禁用深度缓冲的写入

glDepthMask(GL_FALSE);

3. 深度测试函数测试对比

情况1. 不开启深度测试
在这里插入图片描述
情况2. 深度测试函数为glDepthFunc(GL_ALWAYS);
在这里插入图片描述
情况3. 深度测试函数为glDepthFunc(GL_LESS); 或者默认不写
在这里插入图片描述

4. 深度冲突(Z-fighting)

深度缓冲没有足够的精度来决定两个形状哪个在前面。结果就是这两个形状不断地在切换前后顺序,这会导致很奇怪的花纹。这个现象叫做深度冲突(Z-fighting)
以箱子模型和地毯为例子,当我们把相机拉进到箱子的内部时会出现地板与模型出现干涉现象,即有时候出现地毯有时候出现箱子,两者之间出现锯齿花纹。如图所示:
在这里插入图片描述
深度冲突不能够被完全避免,但一些技巧有助于在场景中减轻或者完全避免深度冲突

防止深度冲突的方法
1.不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。通过在两个物体之间设置一个用户无法注意到的偏移值,你可以完全避免这两个物体之间的深度冲突。
2.尽可能将近平面设置远一些
3.牺牲一些性能,使用更高精度的深度缓冲。大部分深度缓冲的精度都是24位的,但现在大部分的显卡都支持32位的深度缓冲,这将会极大地提高精度。

猜你喜欢

转载自blog.csdn.net/weixin_44478077/article/details/124899412