OpenGL 裁剪

Posted

技术标签:

【中文标题】OpenGL 裁剪【英文标题】:OpenGL clipping 【发布时间】:2011-11-24 04:39:45 【问题描述】:

我已经阅读有关剪辑的文章几个小时了,但我似乎没有找到解决问题的方法。

这是我的场景:

在 OpenGL ES 环境(iosandroid)中,我有一个由可绘制对象组成的 2D 场景图,形成一棵树。

每个树节点都有自己的空间空间和自己的变换矩阵,每个节点都将其坐标空间继承给其子节点。每个节点都有一个矩形边界框,但这些边界框不是轴对齐的。

此设置非常适合渲染 2D 场景图,遍历树,渲染每个对象,然后是子对象。

现在我的问题来了:我正在寻找一种在节点上启用剪辑的方法。启用裁剪后,节点的子节点在离开父边界框区域时应被裁剪。

例如,我想要一个包含一组文本节点作为子节点的节点,它可以随着它的父边界框上下滚动,并且在离开父边界框区域时应该被剪裁。

由于边界框不是轴对齐的,我不能使用 glScissor,这将是最简单的方法。

我正在考虑使用模板缓冲区并将填充的边界矩形绘制到其中,当启用剪辑时,然后启用模板缓冲区。这可能会奏效,但会导致另一个问题:如果剪辑节点内的子节点再次剪辑会发生什么? - 必须为孩子设置模板蒙版,擦除父母的模板蒙版。

我正在考虑的另一个解决方案是在软件中进行剪辑。这是可能的,因为在每个节点内,剪裁可以在它自己的局部坐标空间中相对容易地完成。这个解决方案的缺点是必须为每个实现的新节点类型实现裁剪。

这里有人能指出我正确的方向吗? 我正在寻找的是类似于 glscissor 的功能,用于剪切非轴对齐的矩形区域。

【问题讨论】:

【参考方案1】:

剪刀箱是满足简单需求的简单工具。如果您的需求不那么简单,那么您将不得不使用不那么简单的 OpenGL 机制进行裁剪:模板缓冲区。

假设您目前没有将模板缓冲区用于其他任何事情,您可以访问 8 个模板位。通过为场景图中的每个级别赋予比上一个更高的编号,您可以为每个级别分配其自己的模板蒙版。当然,如果同一深度级别的两个兄弟姐妹重叠,或者只是靠得太近,那么你就有问题了。

另一种选择是为每个节点分配一个从 1 到 255 的数字。使用 GL_EQUAL 的模板测试,您将能够防止上述重叠问题。但是,这意味着整个场景图中的节点不能超过 255 个。根据您的特定需求,这可能是一个太大的限制。

当您通过任一方法用完位时,您当然可以清除模板(和深度。不要试图只清除其中一个)。但这可能有点昂贵,并且需要您清除深度,而您可能不想这样做。

另一种方法是对非轴对齐的节点使用递增数量和 GL_EQUAL 测试。您对大多数节点使用剪刀框,但如果有一些旋转(无论是在该节点上还是继承),那么您将使用模板掩码,在处理图形时碰撞掩码计数器。同样,您仅限于 256 个节点,但至少这些仅适用于旋转节点。根据您的需要和有多少旋转节点,这可能就足够了。

【讨论】:

随着数字的增加,我仍然不明白。想象一下,第一个启用了裁剪的节点在模板缓冲区中绘制了一个 1 的矩形,他的兄弟姐妹将被完美裁剪。现在出现了另一个启用了剪辑的兄弟姐妹。它在模板缓冲区中绘制了一个填充了 2 的矩形,替换了 2 个矩形重叠的 1。 兄弟姐妹也将被完美剪裁,因为他们再次测试 2。现在我们转到第一个节点,必须针对 1 进行模板测试。这里测试将失败,因为我们针对 1 和第一个矩形的某些部分已被 2s 覆盖。如果我的想法有误,请纠正我! @NULL 每个节点都应该在绘制子节点之前绘制自己的内容。因此,仅当同一父级下的两个兄弟姐妹重叠时,此问题才有意义。如果他们这样做了,那么正确的事情就会发生:重叠的一方获胜,另一方失败。兄弟姐妹应该互相夹击,因此,其中一个必须获胜。与 GUI 层次结构一样,节点下的兄弟姐妹具有 Z 顺序。您只需要保持此顺序并适当地绘制它们。 @NULL 此外,您可以在模板测试中使用 GL_LEQUAL 以确保剪切发生在某个点之上,但低于其他点。只要为所有父母分配一个小于其孩子的模板值,就可以正常工作。 @NICOLAS BOLAS 感谢您的意见。我已经成功实现了节点和祖先轴对齐的情况。我需要更多关于模板版本的帮助。我几乎让它工作了,但我需要一个不同的算法。我已经编辑了原始帖子并描述了我的算法以及我在那里遇到的问题。

以上是关于OpenGL 裁剪的主要内容,如果未能解决你的问题,请参考以下文章

opengl中剪裁的原理

OpenGL - 在 3D 空间中裁剪

OpenGL投影裁剪

裁剪平面附近的 OpenGL

裁剪坐标系和标准化设备坐标系(OpenGL)中的裁剪

OpenGL 裁剪