实践项目:https://github.com/JackieLong/OpenGL/tree/main/project_stencil_test
发生在逐片段操作阶段中的剪切测试之后(Scissor Test)。
点击查看【processon】

工作原理

有一个和颜色缓冲(Color Buffer)一样的模板缓冲(Stencil Buffer),每个模板值一般都是8bit,表示每个片段/像素都有OpenGL_模板测试(Stencil Test) - 图1个模板值,我们可以写入模板值,当某个片段有某个模板值时,可以决定是否要保留还是丢弃该片段。OpenGL_模板测试(Stencil Test) - 图2

开启模板测试

  1. glEnable(GL_STENCIL_TEST); // 开启深度测试,根据库的不同,可能默认不开启。
  2. // glStencilMask(bitMask),将要写入的模板值与bitMask(位掩码)进行and运算。
  3. glStencilMask(0xFF); // 开启写入:每个bit都原样输出到模板缓冲,默认值。
  4. glStencilMask(0x00); // 禁用写入:每个bit写入到模板缓冲时,都为0。
  5. while(!glfwWindowShouldClose(window))
  6. {
  7. glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  8. // 每次渲染迭代之前别忘了清除
  9. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_TEST);
  10. ......
  11. }

模板函数

有两个相关函数:

  • glStencilFunc
    • 描述了OpenGL对模板缓冲做什么操作。
  • glStencilOp
    • 描述了如何更新模板缓冲。 ```cpp

glStencilFunc(GLenum func, GLint ref, GLuint mask); // 描述了OpenGL对模板缓冲做什么操作。 //func: 模板测试函数,设stencilFrag:片段模板值,stencilBuffer:缓冲区对应片段模板值 // GL_ALWAYS 永远通过模板测试,后绘制的一律覆盖之前绘制的。 // GL_NEVER 永远不通过模板测试,一律保留最先绘制的。 // GL_LESS stencilFrag < stencilBuffer,通过测试,即丢弃 >= stencilBuffer的片段,默认值 // GL_EQUAL stencilFrag == stencilBuffer,通过测试 // GL_LEQUAL stencilFrag <= stencilBuffer,通过测试 // GL_GREATER stencilFrag > stencilBuffer,通过测试 // GL_NOTEQUAL stencilFrag != stencilBuffer,通过测试 // GL_GEQUAL stencilFrag >= stencilBuffer,通过测试 //ref: 模板测试参考值,模板缓冲内容与这个值进行比较。 //mask: 位掩码,compare(mask & ref, mask & stencilFrag),默认都为1,一般是0xFF,8bit。

glStencilFunc(GL_EQUAL, 1, 0xFF); // 如果stencilFrag==1,则通过模板测试并被绘制,否则会被丢弃。

  1. ```cpp
  2. glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); // 描述了如何更新模板缓冲。
  3. // sfail: 模板测试失败时采取的行为。
  4. // dpfail: 模板测试通过,但深度测试失败时采取的行为。
  5. // dppass: 模板测试和深度测试都通过时采取的行为。
  6. // 三者的可能取值如下;
  7. // GL_KEEP: 保持当前储存的模板值
  8. // GL_ZERO: 将模板值设置为0
  9. // GL_REPLACE: 将模板值设置为glStencilFunc函数设置的ref值
  10. // GL_INCR: 如果模板值小于最大值则将模板值加1
  11. // GL_INCR_WRAP: 与GL_INCR一样,但如果模板值超过了最大值则归零
  12. // GL_DECR: 如果模板值大于最小值则将模板值减1
  13. // GL_DECR_WRAP: 与GL_DECR一样,但如果模板值小于0则将其设置为最大值
  14. // GL_INVERT: 按位翻转当前的模板缓冲值
  15. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // 默认情况,不会更新模板缓冲。