深度测试
深度测试和颜色缓冲一样,在每个片段中存储了信息,并且通常和颜色缓冲有着一样的宽度和高度,深度缓冲是由窗口系统自动创建的,他会以16,24,32位float 的形式存储他的深度值。在大部分的系统中,深度缓冲的精度都是24位的。
当深度测试(Depth Testing) 被启动的时候,OpenGl会将一个片段的深度值与深度缓冲的内容进行对比。OpenGl会执行一个深度测试,如果这个深度测试通过的话,深度缓冲将会更新为新的深度值,如果深度测试未通过的话,片段将会被丢弃。 深度缓冲是运行在片段着色器之后(以及模板测试之后)在屏幕空间中运行的。屏幕空间坐标与通过OpenGl的glViewport所定义的视口密切相关,并且可以使用GLSL内建变量gl_FragCoord从片段着色器中直接访问。 gl_FragCoord的x和y分量分别代表了片段的屏幕坐标(其中(0,0)位于左下角)。gl_FragCoord中包含了一个z分量,它包含了片段真正的深度值。z值就是需要与深度缓冲内容所对比的那个值。
现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性。提前深度测试允许深度测试在片段着色器之前运行。只要我们清楚一个片段永远不会是可见的(它在其他物体之后),我们就能提前丢弃这个片段。 片段着色器通常开销都是很大的,所以我们应该尽可能避免运行它们。当使用提前深度测试时,片段着色器的一个限制是你不能写入片段的深度值。如果一个片段着色器对它的深度值进行了写入,提前深度测试是不可能的。OpenGL不能提前知道深度值。
深度测试默认是禁用的,所以如果要启动深度测试的话,我们需要用GL_DEPTH_TEST选项来启动它:
glEnable(GL_DEPTH_TEST);
当它启动的时候,如果一个片段通过了深度测试的话,OpenGL会在深度缓冲中存储该片段的z值;如果没有通过深度缓冲,则会丢弃该片段。如果你启动了深度缓冲,还需要在每个渲染迭代之前使用GL_DEPTH_BUFFER_BIT来清除深度缓冲。否则你仍会使用上一次渲染迭代中的写入的深度值。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
如果在某些情况下需要对所有片段都执行深度测试并丢弃相应的片段,但不希望更新深度缓冲。基本上来说,你在使用一个只读(Read-Only)深度缓冲。OpenGL允许我们禁用深度缓冲的写入,只需要设置它的深度掩码(Depth Mask)设置为GL_FALSE就可以了:
glDepthMask(GL_FALSE);
这个只有在深度测试被启动的时候才有效
深度测试函数
OpenGL允许我们修改深度测试中使用的比较运算符。这允许我们来控制OpenGL什么时候该通过或丢弃一个片段,什么时候去更新深度缓冲。我们可以调用glDepthFunc函数来设置比较运算符(或者说深度函数(Depth Function)):
函数 | 描述 |
---|---|
GL_ALWAYS | 永远通过深度测试 |
GL_NEVER | 永远不通过深度测试 |
GL_LESS | 在片段深度值小于缓冲的深度值时通过测试 |
GL_EQUAL | 在片段深度值等于缓冲区的深度值时通过测试 |
GL_LEQUAL | 在片段深度值小于等于缓冲区的深度值时通过测试 |
GL_GREATER | 在片段深度值大于缓冲区的深度值时通过测试 |
GL_NOTEQUAL | 在片段深度值不等于缓冲区的深度值时通过测试 |
GL_GEQUAL | 在片段深度值大于等于缓冲区的深度值时通过测试 |