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 2.0 纹理格式可进行颜色、深度或模板渲染?
OpenGL ES 应用程序模板项目在 iOS 模拟器中崩溃