深度缓冲是一个与你的渲染目标(render target)相同大小的缓冲,这个缓冲记录每个像素的深度。当一个像素第二次被绘制时– 例如当一个物体在另一个物体之后被绘制-深度缓冲要么保留前面的深度值,要么使用第二个像素的深度值替换当前深度值。那个深度保留哪个深度抛弃取决于你选择的深度函数。例如,如果当前深度函数是CompareFunction.LessEqual时,只有小于等于当前深度值的值才会被保留,而大于当前深度值的值会被抛弃。这叫做深度测试,每次绘制像素时都会进行深度测试。当对一个像素进行深度测试时,它的颜色会被写入渲染目标,而深度被写入深度缓冲。
像素的深度值是由视矩阵和投影矩阵决定的。在近裁平面上的像素深度值为0,在远裁平面上的像素的深度值为1。场景中的每个对象都需进行绘制,通常最靠近相机的像素会被保留,这些对象阻挡了在它们后面的对象的可见性。
深度缓冲通常还包含stencil bits – 所以深度缓冲又被叫做depth-stencil缓冲。深度格式(depth format)表示深度缓冲的构造。深度缓冲总是32 bits,但可以用不同的方式组合,类似于纹理格式。
【颜色缓冲区】颜色缓冲区(COLOR_BUFFER)就是帧缓冲区(FRAME_BUFFER),你需要渲染的场景最终每一个像素都要写入该缓冲区,然后由它在渲染到屏幕上显示.
【深度缓冲区】深度缓冲区(DEPTH_BUFFER)与帧缓冲区对应,用于记录上面每个像素的深度值,通过深度缓冲区,我们可以进行深度测试,从而确定像素的遮挡关系,保证渲染正确.
【模板缓冲区】模版缓冲(STENCIL_BUFFER)与深度缓冲大小相同,通过设置模版缓冲每个像素的值,我们可以指定在渲染的时候只渲染某些像素,从而可以达到一些特殊的效果.
1. 深度缓冲区
深度缓冲区原理就是把一个距离观察平面(近裁剪面)的深度值(或距离)与窗口中的每个像素相关联。
1> 首先使用glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)来打开DEPTH_BUFFER
void glutInitDisplayMode(unsigned int mode);
2> 每帧开始绘制时,须清空深度缓存 glClear(GL_DEPTH_BUFFER_BIT); 该函数把所有像素的深度值设置为最大值(一般是远裁剪面)
3> 必要时调用glDepthMask(GL_FALSE)来禁止对深度缓冲区的写入。绘制完后在调用glDepthMask(GL_TRUE)打开DEPTH_BUFFER的读写(否则物体有可能显示不出来)
注意:只要存在深度缓冲区,无论是否启用深度测试(GL_DEPTH_TEST),OpenGL在像素被绘制时都会尝试将深度数据写入到缓冲区内,除非调用了glDepthMask(GL_FALSE)来禁止写入。
2. 深度测试
OpenGL中的深度测试是采用深度缓存器算法,消除场景中的不可见面。在默认情况下,深度缓存中深度值的范围在0.0到1.0之间
1> 使用glEnable(GL_DEPTH_TEST)打开深度测试
2> 每次绘制场景之前,需要先清除深度缓冲区,即glClear(GL_DEPTH_BUFFER_BIT),然后以任意次序绘制场景中的物体
3> glDepthRange (nearNormDepth, farNormalDepth);指定深度值范围
这里nearNormDepth和farNormalDepth可以取0.0到1.0范围内的任意值,甚至可以让nearNormDepth > farNormalDepth。这样,通过glDepthRange函数可以在透视投影有限观察空间中的任意区域进行深度测试。
4> glClearDepth (maxDepth);
参数maxDepth可以是0.0到1.0范围内的任意值。glClearDepth用maxDepth对深度缓存进行初始化,而默认情况下,深度缓存用1.0进行初始化。由于在进行深度测试中,大于深度缓存初始值的多边形都不会被绘制,因此glClearDepth函数可以用来加速深度测试处理。这里需要注意的是指定了深度缓存的初始化值之后,应调用:glClear(GL_DEPTH_BUFFER_BIT); 完成深度缓存的初始化。
5> glDepthFunc(func);
该函数用于指定将需要绘制的新像素的z值与深度缓冲区中对应位置的z值进行比较的函数,如果比深度缓存中的值小,那么用新像素的颜色值更新帧缓存中对应像素的颜色值。
参数func的值可以为GL_NEVER(没有处理)、GL_ALWAYS(处理所有)、GL_LESS(小于)、GL_LEQUAL(小于等于)、GL_EQUAL(等于)、GL_GEQUAL(大于等于)、GL_GREATER(大于)或GL_NOTEQUAL(不等于),其中默认值是GL_LESS。这些测试可以在各种应用中减少深度缓存处理的的计算。
启动深度测试后,后面物体的绘制与前后关系就无关了,最后完成绘制后已经自动按照前后顺序显示了。
但是在绘制半透明物体时,深度测试就会出错,你会发现最后绘制结果和想象中的不一样。此时要用到glDepthMask和alpha blend。绘制前调用glDepthMask(GL_FALSE)(或者glDisable(GL_DEPTH_TEST)),打开alpha blend,绘制完后在glDepthMask(GL_TRUE)
3. alpha blend
1> glEnable(GL_BLEND)
2> glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);