1

我正在尝试在给定链接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);,模板测试失败将导致模板缓冲区填充 1 秒,因为设置的指令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);

主程序体:

 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();
}
4

1 回答 1

1

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

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

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

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

于 2014-03-21T05:40:12.017 回答