Stencil缓冲区如何在OpenGL中运行

时间:2014-03-17 09:53:33

标签: c++ opengl stencil-buffer

我正在尝试在给定链接http://commons.wikimedia.org/wiki/File:OpenGL_Tutorial_Stencil.png中描述的OpenGL中实现以下效果,代码片段也在下面,这是官方的openGL维基百科教程。

虽然它有代码并注释掉解释但我仍然觉得很难理解openGL中模板缓冲区操作的逻辑。我提醒一下,在开始模板印刷之前,我阅读了红皮书中的大部分说明,所以我知道并且我很熟悉,glStencilFunc,glStencilOp和glStencilMask等工作原理,但是仍有一些模糊不清的东西在我的想法与模板有关。

以下是我如何解释代码的演练:

  1. 使用glStencilFunc(GL_NEVER, 1, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);我认为模板测试将始终通过,模板测试失败将导致模板缓冲区中的1s填充,因为glStencilOp

    中设置的指令
  2. 如果前面的代码块(#1)设置了模板缓冲区中的所有像素,那么我们使用glStencilMask(0xFF);过程调用实现了这一点。我们是否保证所有1都成功写入模板缓冲区或实际上是什么?

  3. 我们绘制圆圈然后打开蒙版,但这次glStencilMask(0x00),这是一个混乱,我认为这涉及防止模板缓冲区值被新值覆盖,但代码注释说这只是用0来填充模板缓冲区。

  4. 最后,如果我们不在模板缓冲区中更改任何值(由于glStencilMask(0x00)),那么有什么意义

    // fill 0s glStencilFunc(GL_EQUAL, 0, 0xFF); /* (nothing to draw) */ // fill 1s glStencilFunc(GL_EQUAL, 1, 0xFF);

  5. 主要计划机构:

     void onDisplay() {       
      glClearColor(0.1, 0.1, 0.1, 1.0);
      glClear(GL_COLOR_BUFFER_BIT); 
    
      glClear(GL_DEPTH_BUFFER_BIT);
      glEnable(GL_STENCIL_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glDepthMask(GL_FALSE);
      glStencilFunc(GL_NEVER, 1, 0xFF);
      glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)
    
      // draw stencil pattern
      glStencilMask(0xFF);
      glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF
      draw_circle();
    
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glDepthMask(GL_TRUE);
      glStencilMask(0x00);
      // fill 0s
      glStencilFunc(GL_EQUAL, 0, 0xFF);
      /* (nothing to draw) */
      // fill 1s
      glStencilFunc(GL_EQUAL, 1, 0xFF);
    
      draw_scene();
    
      glDisable(GL_STENCIL_TEST);
    
      glutSwapBuffers();
    }
    

1 个答案:

答案 0 :(得分:1)

glStencilMask(0xFF)类似于glColorMask(true, true, true, true)glDepthMask(true)函数 - 0xFF是一个掩码,在将其写入模板缓冲区之前,它与任何模板数据进行逐位AND运算。因此,通过glStencilMask(0xFF),我们确保成功写入OpenGL尝试写入模板缓冲区的任何值。

glStencilMask(0x00):当0x00与任何字节按位进行AND运算时,输出将始终为0.因此,任何时候尝试将字节写入模板缓冲区,写入的字节将为0.实际上,此时,它只是确保模板缓冲区没有写入任何新数据。

根据我的解释,带有/* (nothing to draw) */注释的部分是您在模板测试圆圈外绘制的材料的地方。 0是模板缓冲区中的默认值。因此,由于圆圈中的区域标记为1,因此圆圈外的像素将通过,并且内部的像素将被丢弃。它只是一个占位符。

我相信当评论说// fill 0s时,他们的意思是“这里绘制的任何内容都将填充设置为0的模板缓冲区的部分。考虑到调用glStencilFuncGL_EQUAL0作为参数,这就是将要发生的事情。我也相信,当评论说// fill 1s时,它们的意思相同,但部分是模板缓冲区设置为1(即圆圈已被绘制到模板缓冲区的区域。)