首页 > 解决方案 > OpenGL ES:模板缓冲区和剔除

问题描述

我是 OpenGL 的新手,我正在尝试一些实验,尤其是模板缓冲区。在我的代码中,我分别使用 glStencilFuncSeparate 将前后模板缓冲区分别设置为 0x5 和 0xC(GL_ALWAYS 作为函数的参数)。glStencilOpSeparate 为前和后状态设置为 GL_REPLACE 用于 dppass。当我设置两个模板缓冲区时,我还确保禁用了深度和剔除。

接下来我尝试渲染一个启用了深度、正面剔除和模板测试的立方体。我现在使用 glStencilFuncSeparate() 通过与 0x12 进行比较来仅绘制背面模板设置区域。由于正面被剔除,我希望只显示值为 0x12 的背面模板缓冲区所覆盖的区域。

但令我沮丧的是,它显示空白屏幕。当它给出比较值作为 0x5(front stencil init val) 并且剔除面作为前面时,我能够看到立方体的部分。

所以这似乎表明,当剔除设置为 GL_FRONT 时,立方体的背面与正面模板进行比较。StencilClear(value 0x1) 等所有其他参数看起来都正确,但我不知何故无法理解这种行为。

设置模板

glStencilMaskSeparate(GL_FRONT_AND_BACK, 0xff)
glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x5, 0xff)
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0xc, 0xff)
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE)
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_REPLACE)
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
glDepthMask(GL_FALSE)
glDrawArrays(GL_TRIANGLES, 0, 6)

启用剔除

glCullFace(GL_FRONT)
glEnable(GL_CULL_FACE)

画一个立方体

glStencilOpSeparate(GL_FRONT,GL_KEEP,GL_KEEP,GL_REPLACE)
glStencilOpSeparate(GL_BACK,GL_KEEP,GL_KEEP,GL_REPLACE)
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
glDepthMask(GL_FALSE)
glDrawArrays(GL_TRIANGLES, 0, 36)

OpenGL 版本:OpenGL ES 3.1 Mesa 19.0.8,Mesa DRI Intel Haswell Desktop

有人可以帮我理解为什么前后模板缓冲区似乎与剔除模式交换了吗?

标签: opengl-espyopenglstencil-buffer

解决方案


听起来您认为有两种不同的模板缓冲区,一种用于正面,一种用于背面。这是不正确的;只有一个模板缓冲区,每个像素有一个模板值。

这些glSeparate...()函数只是为您提供了为正面和背面三角形指定单独的模板测试/更新规则的方法,但它们将写入帧缓冲区中的相同存储位置。

假设您有一个正面最靠近相机的立方体,那么在您第一次通过后“幸存”的模板值将始终是正面参考值。

更新:请注意,您可以在同一模板缓冲区中“混合”正面和背面模板值,方法是使用 glStencilMaskSeparate()来控制可以写入的位,并glStencilFuncSeparate()控制在模板测试时使用哪些位。


推荐阅读