如何在OpenGL中将opaque与透明对象分开

时间:2015-12-29 04:50:37

标签: c++ opengl transparency assimp soil

我试图在OpenGL中实现透明度,并从我已经阅读过的内容中首先渲染所有不透明对象然后以正确顺序呈现透明对象。

我的问题是如何在场景图中分离不透明物体和透明物体,以便我可以先渲染不透明物体。我的场景图由一组节点组成,这些节点可以附加实体,每个实体可以由几个具有不同材质的网格组成,每个网格都有一个或多个纹理。

如果我将一个场景加载到我的图形中,我需要知道哪些材质部分或完全透明,这意味着我需要检查加载的纹理是否有任何小于1的alpha值。我目前正在使用Assimp来处理加载模型/场景和SOiL来读取纹理,我还没有找到任何简单的方法将透明材料与不透明材料分开。

这可能有一个非常简单的解决方案,因为我还没有找到其他人有同样的问题,但我仍然从OpenGL开始,过去几个小时我一直坚持这个问题。

透明度如何正常完成以及不透明物体如何与部分或完全透明的物体分开,以便它们可以先渲染?

1 个答案:

答案 0 :(得分:1)

对于大多数渲染方法,您不必严格必须将opaque与透明对象分开。如果你考虑一下,透明度(或不透明度)是一种持续的品质。在OpenGL中,alpha组件通常用于定义不透明度。不透明对象的alpha值为1.0,但这只是连续光谱中的一个值。能够正确处理所有alpha值的方法不会因为alpha值恰好为1.0而突然失败。

换句话说:alpha值为0.9的对象是不透明的吗?如果alpha值为0.99,你能否证明它与alpha值1.0不同?它实际上是连续的,而不是二元决定。

有了这个说法,有理由说不同地处理不透明物体是很常见的。我能想到的主要原因是:

  1. 由于必须为常见的简单透明度渲染方法对非不透明对象进行排序,因此可以通过对 非透明对象进行排序来节省工作量。排序并不便宜,您可以通过这种方式缩短处理时间。对于大多数这些方法,您可以通过对所有对象进行排序来获得完美的结果,但代价是效率较低。

  2. 通常,对象无法完美排序,或者这样做至少不容易。一个明显的问题是当对象重叠时,但挑战超出了这种情况(请参阅我的答案,以便更深入地说明有问题的案例:Some questions about OpenGL transparency)。在这些情况下,您会从错误的排序中获取工件。通过在启用深度测试的情况下绘制不透明对象,可以避免这些对象产生伪影的可能性,并减少明显伪影的总体发生。

  3. 您不知道哪些对象包含透明度的情况似乎有点不寻常。在大多数情况下,您知道哪些对象是不透明的,因为您可以控制渲染和内容。因此,拥有一个指定对象是否不透明的属性通常是免费的。

    如果你真的无法定义哪些对象是不透明的,那么可以想到几个选项。第一个是您对所有对象进行排序,并按顺序渲染它们。基于上面的解释,您可能会遇到性能或质量下降,但值得尝试。

    有些方法可以使用透明度进行渲染,而无需排序或分离不透明和透明对象。想到的一个简单的问题是alpha-to-coverage。特别是如果你使用MSAA进行渲染,它不会产生任何开销。缺点是质量可能会平庸,具体取决于场景的性质。但同样,值得尝试。

    在我对这个问题的回答中,你可以找到alpha-to-coverage的基本解释,以及一些其他简单的透明度渲染方法:OpenGL ES2 Alpha test problems

    还有更高级的透明度渲染方法,部分依赖于最近的硬件功能。覆盖它们超出了这里的帖子范围(并且在很大程度上超出了我的知识......),但是你应该能够通过搜索“与订单无关的透明度”找到材料。