Stencil Buffer(模板缓冲区)

作者:Nin+.Lee

邮箱:[email protected]

(红色部分为自己修改)


与颜色缓冲区和深度缓冲区类似,模板缓冲区可以为屏幕上的每个像素点保存一个无符号整数值。这个值的具体意义视程序的具体应用而定。在渲染的过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值。这个比较的过程被称为模板测试。模板测试发生在透明度测试(alpha test)之后,深度测试(depth test)之前。如果模板测试通过,则相应的像素点更新,否则不更新。图形渲染管线中,基于单个像素的测试操作的顺序如下图。

 

Stencil Buffer(模板缓冲区)_第1张图片

 

在模板测试的过程中,可以先使用一个比较用掩码(comparison mask)与模板缓冲区中的值进行位与运算,再与参考值进行比较,从而实现对模板缓冲区中的值的某一位上的置位状态的判断。这样,模板缓冲区中的值不仅可以作为一个独立的整体使用,还可以作为一个比特集合使用。

 

在OpenGL中,可以通过调用glStencilFunc()函数来设定,比较条件(comparison function)、参考值(reference value)以及比较用掩码(comparison mask)。例如,

glStencilFunc(GL_EQUAL, // 比较条件

0x1, // 参考值

0xff); // 比较用掩码

 

比较条件的种类如下:

方法

参考值与模板值之间的比较结果

GL_NEVER

总是失败

GL_ALWAYS

总是通过测试

GL_LESS

当参考值小于模板值时,通过测试

GL_LEQUAL

当参考值小于等于模板值时,通过测试

GL_EQUAL

当参考值等于模板值时,通过测试

GL_GEQUAL

当参考值大于等于模板值时,通过测试

GL_GREATER

当参考值大于模板值时,通过测试

GL_NOTEQUAL

当参考值不等于模板值时,通过测试

 

具体情况是:

  GL_NEVER        Always fails. 

  GL_LESS         Passes if ( ref & mask ) < ( stencil & mask). 

  GL_LEQUAL       Passes if ( ref & mask ) <= ( stencil & mask). 

  GL_GREATER      Passes if ( ref & mask ) > ( stencil & mask). 

  GL_GEQUAL       Passes if ( ref & mask ) >= ( stencil & mask). 

  GL_EQUAL        Passes if ( ref & mask ) = ( stencil & mask). 

  GL_NOTEQUAL     Passes if ( ref & mask ) != ( stencil & mask). 

  GL_ALWAYS       Always passes.

 

 

除了比较参考值与模板值之外,我们还需要使用一些操作来更新模板缓冲区中的值,这些操作被称为模板操作(stencil operation)。模板缓冲区的更新与模板测试的结果以及深度测试的结果有着密切的联系。模板操作可以为下述三种情况,分别指定相应的更新方法。

1. 模板测试失败。

2. 模板测试通过,但深度测试失败。

3. 模板测试通过,且深度测试通过。

当上述情况中的一个发生时,就会执行预先设定的更新操作。在OpenGL中,可以使用glStencilOp()函数来为上述三种情况分别设置更新方法。例如,

glStencilOp(GL_KEEP, // 第一种情况更新方法

GL_DECR, // 第二种情况的更新方法

GL_INCR); // 第三种情况的更新方法

 

可是设置的更新方法如下:

更新方法

描述

GL_KEEP

保持当前的模板值不变

GL_ZERO

将当前的模板值设为0

GL_REPLAC

用glStencilFunc函数所指定的参考值替换蒙板参数值

GL_INCR

在当前的模板值上加1

GL_DECR

在当前的模板值上减1

GL_INVERT

对当前的模板值进行按位取反操作

 

我们可以通过写入掩码(write mask)来更新模板值指定比特位上的置位状态。OpenGL中,提供了glStencilMask()函数来设置写入掩码。例如,

glStencilMask(0xff);

默认情况下,模板测试功能是禁用的。在OpenGL中可以通过

glEnable(GL_STENCIL_TEST);

glDisable(GL_STENCIL_TEST);

来启用和禁用模板测试。

 

通常,在渲染开始之前,需要对模板缓冲区执行清理操作,将模板缓冲区的值初始化为某个指定的值。在OpenGL中,可以通过

glClearStencil()函数来设置这个指定的初始值。例如,

glClearStencil(0); // 初始为0

然后,用

glClear(GL_STENCIL_BUFFER_BIT);

执行实际的清理操作。注意,在使用OpenGL清理模板缓冲区的时候,OpenGL会清理的过程中应用写入掩码。如果你想保留模板值某些位上的置位状态,这个功能显然是非常有用的。但是,如果你希望将所有的模板值都初始化为某个指定的初始值时,这同样也可能会造成一些迷惑。

 

为了功能的完整性,OpenGL还提供了读写、复制模板值的操作。把glReadPixels()、glDrawPixels()、glCopyPixels()的格式参数设置为GL_STENCIL之后,就可以对模板缓冲区进行读写、复制操作了。

 

参考文献

1. David Blythe, The Stencil Buffer,

http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html

2. Mark J. Kilgard, Improving Shadows and Reflections via the Stencil Buffer

你可能感兴趣的:(OpenGL)