【问题标题】:How Stencil Buffer Operates in OpenGLStencil Buffer 在 OpenGL 中是如何工作的
【发布时间】:2014-04-22 11:18:07
【问题描述】:

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

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

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

  1. 对于glStencilFunc(GL_NEVER, 1, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);,我相信模板测试将始终通过,并且由于glStencilOp中设置的指令,模板测试失败将导致模板缓冲区填充1s

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

  3. 我们画了一个圆圈然后打开遮罩,但这次glStencilMask(0x00),这是一个混乱,我认为这涉及防止模板缓冲区值被新值覆盖,但代码 cmets 说这个只需用 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();
}

【问题讨论】:

    标签: c++ opengl stencil-buffer


    【解决方案1】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-31
      • 2015-12-24
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多