在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所示,framebuffer中一个像素,有相对应的depth buffer和stencil buffer值:

depth/stencil buffer的作用 ----------理解模板缓存  opengl-LMLPHP

D3D11中,depth buffer和stencil buffer一起定义,比如DXGI_FORMAT_D24_UNORM_S8_UINT,是指用一个无符号24位的值做为像素的深度缓冲值,并把它映射到[0,1],用一个8位的值表示像素stencil值,并把它映射到[0,255]。注意:在hardware中,detph buffer和stencil buffer实际上是两个独立的buffer。

下面我们看看depth buffer和stencil buffer的作用:

在光栅化阶段,光栅化硬件在光栅化primitive(比如一个三角形)的时候,会访问stencil buffer和depth buffer,并进行相应的比较,这种比较我们通常称为stencil test和depth test,只有通过stencil test和depth test的pixel(或者称为sample 或者fragment更合适),才能最终被写入framebuffer。

下图是stencil test和depth test的框图:

depth/stencil buffer的作用 ----------理解模板缓存  opengl-LMLPHP

首先会进行stecil test,就是当前pixel的stencil值和stencil buffer中对应的stencil值进行某种比较,只有通过比较测试的pixel才会进行depth test,否则就会被光栅化硬件丢弃掉。接着会进行depth test,depth test能够保证物体在场景中前后位置关系。如果两个test都pass,就会更新depth buffer值(当然stencil pass的时候,就可以根据stencil function更新或者保持stencil buffer值了)。

通过使用stencil test,我们可以实现蒙版的效果,从而实现一些渲染效果,比如镜子,体积阴影等。

举个例子:

在一个frame中,我们首先渲染一个四边形,做为镜子,渲染前,清除depth/stencil buffer值(depth设置为1.0, stencil 设置为0),这时场景中stencil buffer为

depth/stencil buffer的作用 ----------理解模板缓存  opengl-LMLPHP

接着,我们设置stencil 总是pass,并设置stencil buffer值为1,渲染一个镜子(四边形)。这是stencil buffer的值为

depth/stencil buffer的作用 ----------理解模板缓存  opengl-LMLPHP

接下来,我们渲染其它的primitive,比如一个三角形,先设置stencil 值为1,并设置stencil比较函数为等于,这样渲染三角形时候,会比较stencil值,对于三角形光栅化后的pixel,如果它在镜子的范围内,1=1,所以stencil pass,会保留这个像素,如果在镜子的外面,因为stencil buffer的值为0,所以stencil test fail,从而放弃这个pixel。如下图三角形,最后实际保留的像素只为蓝色的pass stencil test的部分。

depth/stencil buffer的作用 ----------理解模板缓存  opengl-LMLPHP

下面一章,我们将在D3D11中,通过使用stencil,实现一个镜子的效果。

05-17 13:04