如何使用stencil buffer实现分层剪裁

Posted

技术标签:

【中文标题】如何使用stencil buffer实现分层剪裁【英文标题】:How to use stencil buffer to achieve hierarchical clipping 【发布时间】:2019-10-31 08:15:27 【问题描述】:

我想要达到的效果如下图所示:

假设我们的模板缓冲区处于某种状态,因此此时只有红色部分被填充。当我使用标记为黄色的部分更新模板缓冲区时,我需要执行哪些操作,因此最终只有绿色部分是模板缓冲区的最终状态?

我需要这个来实现嵌套元素内容的裁剪,以防止元素的内容被渲染超出它们两者结合的边界。

到目前为止,我尝试了各种涉及模板测试的布尔运算都无济于事,这比任何进展都带来了更多的困惑。

请注意,此任务并不实际进行剪刀测试,因为元素可能具有任意形状和旋转。

【问题讨论】:

Stencil 有 8 个独立的位平面。您可以将红色与一个平面关联,将黄色与另一个关联,然后检查两个平面的位是否都已设置;那是他们相交的地方。有关详细信息,请参阅 glStencilFunc 和 glStencilOp 的 opengl 规范,如果您在阅读后没有得到它,请告诉它。 另一种解决方案是,如果小于 2,则通过模板测试,然后增加值。 0 = 无元素,1 = 一个元素,2 = 重叠元素 @Andreas 问题是可能有多个元素共享一个父元素,并且层次结构可能会一直深入下去。 “所以最后只有绿色部分是模板缓冲区的最终状态” - 这不清楚 - 状态是什么意思?最后的评论使它完全混乱。你能制定一个规则,明确定义应该在模板缓冲区中识别的片段吗?您是指不止一次绘制的所有片段。或者您是指在第一遍和第二遍中绘制的片段? @Rabbid76,我正在尝试解决有关内容剪辑的问题。想象一下,红色矩形是父级,黄色是子级。子项应该包含在父项中,由于偏移(或“滚动”,如果你愿意的话)被部分隐藏在里面。绿色矩形是应该在子元素内呈现的。状态表示当前写入模板缓冲区的内容。 【参考方案1】:

如果你有一个层次结构,那么你就有层次。每个孩子只能在其父母定义的区域内绘图。所以每一层都必须计算模板缓冲区(GL_INCR)并且只允许绘制,如果模板缓冲区的当前值等于层“深度”:

int layer = 0;
glStencilFunc(GL_ALWAYS, 1, 0xff);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

// draw initial layer
// ...

layer ++;
glStencilFunc(GL_EQUAL, layer, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

// draw layer 1
// ...

layer ++;
glStencilFunc(GL_EQUAL, layer, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

// draw layer 2
// ...

注意,通常模板缓冲区有 8 位,这将层数限制为 256。

【讨论】:

以上是关于如何使用stencil buffer实现分层剪裁的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL Stencil Buffer,它们的支持程度如何?

OpenGL ES 中的模板测试

使用 Stencil-buffer 勾勒出 3D 模型

glClear [ GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT 和 GL_STENCIL_BUFFER_BIT ]

无法让 Stencil Buffer 在 iOS 4+ 中工作(5.0 工作正常)。 [OpenGL ES 2.0]

OpenGLOpenGL中的Buffer的巧妙使用