OpenGL ES 模板操作
参考OpenGL裁剪一文中讨论的问题,出现了一个新问题。
我正在实现基于节点的 2D 场景图的裁剪。每当剪切框轴对齐时,我都会使用 glScissor,就像 OpenGL 剪切 中建议的那样。我已经成功实现了轴对齐框的节点裁剪。
事实证明,每个节点都必须将其剪裁矩形与其使用剪裁的祖先的矩形相交。 (如果兄弟姐妹与祖先的剪切框重叠,这是必要的)。
必须使用模板缓冲区来实现非轴对齐矩形相交的机制。我开始在 OpenGL 裁剪 中实现建议的解决方案,但我遇到了剪辑矩形与祖先重叠的孩子的问题。
现在,只需一个剪贴盒即可完美地进行模板剪贴。 但是,如果子代或孙代与祖先相交,则算法会失败,因为这里需要两个相关矩形的交集(就像在轴对齐版本中一样)作为掩码,而不是子代的完整矩形。
我想出了以下算法:
最顶层的节点以计数器值 1 开始写入,并将其填充有 1 的剪切矩形绘制到模板缓冲区中,并根据 1 渲染其子模板测试。每个也打开剪切的同级节点都会进行绘制它的边界矩形是通过将 1 添加到模板缓冲区,然后针对 2 进行测试,依此类推。现在,当兄弟剪裁矩形与祖先剪裁矩形重叠时,它们重叠的区域将被 2 填充,在针对 2 进行测试时给出完美的剪裁。该算法可以扩展到最多 255 个嵌套剪裁节点。
我的问题是:
如何以一种方式执行对模板缓冲区的渲染,无论何时执行渲染,都将 1 添加到当前模板缓冲区值,而不是写入 1。
这是我用来准备渲染到模板缓冲区的代码:
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, ref, mask);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
我正在寻找一种设置,可以将模板缓冲区当前值增加 ref 的值,而不是将 ref 写入缓冲区。
有人可以帮我吗?
In reference to the problem diskussed in article OpenGL clipping a new question arises.
I am implementing the clipping for a node based 2D scene graph. Whenever the clipping boxes are axis aligned I am using the glScissor like proposed in OpenGL clipping. I have sucessfully implemented node clipping of boxes that are axis aligned.
It turns out that each node has to intersect it's clipping rectangle with the ones of it's ancestors that use clipping. (That is necessary in case of siblings that are overlapping with the clipping box of an ancestor).
The mechanism of intersecting non axis aligned rectangles has to be implemented using the stencil buffer. I started implementing the proposed solution in OpenGL clipping but am having problems with chidrens having clip rects overlaping with theyr ancestors ones.
Right now stencil clipping works perfect with only one clipping box.
But in case of a child or grand child that intersects with an ancestor the algorith fails, because the intersection of the 2 involved rectangles would be needed here (like in the axis aligned version) as mask and not the full rectangle of the child.
I have thought out the following algorithm:
The topmost node writes starts with a counter value of 1 and draws it's clipping rectangle filled with 1s into the stencil buffer and renders it's children stencil-testing against 1. Each sibling that also has clipping turned on draws it's bounding rectangle by adding 1 to the stencil buffer and then testing against 2 and so on. Now when a siblings clipping rect overlaps with an ancestors one,the region where they overlap will be filled with 2s, giving perfect clipping when testing against 2. This algorithm can be extended to a maximum of 255 nested clipping nodes.
Here comes my questions:
How do I perform rendering to the stencil buffer in a way that instead of 1s being writing,1s are added to the current stencil buffer value, whenever rendering is performed.
This is my code I use to prepare for rendering to the stencil buffer:
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, ref, mask);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
I am looking for a setup that will increase the stencil buffers current value by the value of ref instead of writing ref into the buffer.
Can someone help me out?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(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_GREATER
和参考值 0,以及GL_DECR
。结果是“0”,凡是从未绘制过或只绘制了一次的地方,“1”,凡是绘制了两次的地方。glStencilFunc(GL_ALWAYS, ref, mask);
says that:glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
has the effect that:So you're setting things up so that everything you try to draw will pass the stencil test, and in any case its value will be copied into the stencil buffer whether it passes the test or not.
Probably what you want to do is to change your arguments to
glStencilOp
so that you perform aGL_INCR
on pixels that pass. So in your stencil buffer you'll end up with a '1' anywhere touched by a single polygon, a '2' anywhere that you drew two successive polygons, a '3' anywhere you drew 3, etc.When drawing the user-visible stuff you can then use something like
glStencilFunc
set toGL_GEQUAL
and to compare incoming values to '1', '2', '3' or whatever.If you prefer not to keep track of how many levels deep you are, supposing you have one clip area drawn into the stencil, you can modify it to the next clip area by:
GL_INCR
; this'll result in a stencil buffer where all pixels that were in both areas have a value of '2' and all pixels that were in only one area have a value of '1'GL_GREATER
and reference value 0, withGL_DECR
. Result is '0' everywhere that was never painted or was painted only once, '1' everywhere that was painted twice.