OpenGL ES 模板操作

Posted

技术标签:

【中文标题】OpenGL ES 模板操作【英文标题】:OpenGL ES stencil operations 【发布时间】:2011-11-26 01:55:04 【问题描述】:

关于文章 OpenGL clipping 中讨论的问题,出现了一个新问题。

我正在为基于节点的 2D 场景图实现裁剪。每当剪切框轴对齐时,我都会使用OpenGL clipping 中建议的 glScissor。我已经成功实现了轴对齐框的节点裁剪。

事实证明,每个节点都必须将其剪切矩形与其使用剪切的祖先相交。 (如果兄弟姐妹与祖先的剪切框重叠,这是必要的)。

必须使用模板缓冲区来实现相交非轴对齐矩形的机制。我开始在OpenGL clipping 中实施建议的解决方案,但在儿童的剪辑矩形与他们的祖先重叠的问题上遇到了问题。

现在,模板剪裁只需一个剪裁框即可完美运行。 但是,如果孩子或孙子与祖先相交,算法会失败,因为此处需要 2 个相关矩形的交集(如在轴对齐版本中)作为掩码,而不是孩子的完整矩形。

我想出了以下算法:

最上面的节点写入从计数器值 1 开始,并将其填充为 1 的剪切矩形绘制到模板缓冲区中,并呈现它的子节点以 1 进行模板测试。每个也打开了剪切的兄弟节点都将其边界矩形绘制为 将 1 添加到模板缓冲区,然后针对 2 进行测试,依此类推。现在当一个兄弟剪切矩形与一个祖先重叠时,它们重叠的区域将被2s填充,在对2进行测试时提供完美的剪切。该算法可以扩展到最多255个嵌套剪切节点。

我的问题来了:

如何执行对模板缓冲区的渲染,而不是写入 1,而是在执行渲染时将 1 添加到当前模板缓冲区值。

这是我用来准备渲染到模板缓冲区的代码:

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, ref, mask);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

我正在寻找一种设置,它将模板缓冲区的当前值增加 ref 的值,而不是将 ref 写入缓冲区。

谁能帮帮我?

【问题讨论】:

【参考方案1】:

glStencilFunc(GL_ALWAYS, ref, mask); 说:

第一个参数表示模板比较测试总是成功 因此忽略第二个和第三个,但原则上会设置一个常数来比较来自模板缓冲区的值以及哪些位用于比较

glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 的作用是:

当模板测试失败时,新值替换旧值(根据第一个参数) 当深度测试失败但模板测试通过时,新值替换旧值(根据第二个参数) 当模板和深度测试都通过时,新值替换旧值(根据第三个参数)

所以你要进行设置,以便你尝试绘制的所有内容都将通过模板测试,并且在任何情况下,无论它是否通过测试,它的值都会被复制到模板缓冲区中。

您可能想要做的是将参数更改为glStencilOp,以便对通过的像素执行GL_INCR。因此,在您的模板缓冲区中,您最终会在被单个多边形触及的任何地方得到一个“1”,在你绘制两个连续多边形的任何地方都有一个“2”,在你绘制 3 的任何地方都有一个“3”,等等。

在绘制用户可见的内容时,您可以使用 glStencilFunc 设置为 GL_GEQUAL 并将传入的值与“1”、“2”、“3”或其他值进行比较。

如果您不想跟踪您的深度有多少层,假设您在模板中绘制了一个剪辑区域,您可以通过以下方式将其修改为下一个剪辑区域:

    GL_INCR绘制所有新几何;这将产生一个模板缓冲区,其中两个区域中的所有像素的值都为“2”,而仅一个区域中的所有像素的值都为“1” 绘制一个全屏多边形,只通过模板资金GL_GREATER和参考值为0,GL_DECR。结果是从未绘制或仅绘制一次的所有位置为“0”,绘制两次的所有位置为“1”。

【讨论】:

感谢您的解释。我终于实现了嵌套的、非轴对齐的剪辑 嗨,Tommy,不如始终使用 GL_INCR 最高 255 进行绘制,然后渲染一个全屏多边形并将值 != 255 设置为 0 并将值 == 255 设置为 1,然后继续使用 GL_INCR? @elect:这听起来像是一个推迟进行全屏清除的明智计划——假设跟踪你的计数没有问题(实际上,几乎可以肯定不是),而你所有的重新担心的是溢出,因此可能会产生歧义。

以上是关于OpenGL ES 模板操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在模板中使用深度纹理,OpenGL ES 3.0

OpenGL ES之“深度测试”与“模板测试”的使用流程

哪些 OpenGL ES 2.0 纹理格式可进行颜色、深度或模板渲染?

OpenGL ES 应用程序模板项目在 iOS 模拟器中崩溃

在 OpenGL ES 中为帧缓冲区使用深度和模板渲染缓冲区附件

OpenGL ES 学习教程(十三) Stencil_TEST(模板缓冲测试)