如何在复杂的3D场景中正确实现Alpha混合?


11

我知道这个问题听起来似乎很容易回答,但这让我发疯。好的alpha混合机制应该处理的情况太多了,对于每种算法,我都能想到缺少一些东西。

这些是我到目前为止所使用的方法:

  • 首先,虽然关于按深度对对象进行排序,但由于对象不是简单的形状,它们可能具有曲线,并且可能在彼此内部循环,因此这只是失败了。所以我不能总是说出哪一个离相机更近。

  • 然后我考虑了对三角形进行排序,但是这个三角形也可能失败,以为我不确定如何实现它,在极少数情况下,可能会再次引起问题,即两个三角形相互穿过。同样,没有人能说出哪一个更近。

  • 接下来是使用深度缓冲区,至少我们拥有深度缓冲区的主要原因是因为我提到的排序问题,但现在又遇到了另一个问题。由于对象可能是透明的,因此在单个像素中可能会看到多个对象。那么我应该为哪个对象存储像素深度?

  • 然后,我想也许我只能存储最前面的对象深度,并以此确定我应该如何在该像素处混合下一个绘制调用。但是还是有一个问题,考虑两个半透明的平面,中间有一个实心平面。我打算在最后渲染实体平面,可以看到最远的平面。请注意,我将每两个平面合并一次,直到该像素只剩下一种颜色为止。显然,由于上述原因,我也可以使用排序方法。

  • 最后,我认为能够工作的唯一一件事就是将所有对象渲染到不同的渲染目标中,然后对这些图层进行排序并显示最终输出。但是这次我不知道如何实现该算法。

Answers:


11

简短答案

研究深度剥落。从我的研究来看,它似乎是最好的选择,尽管计算量很大,因为它需要多次渲染。这是NVIDIA 的另一种更新更快的实现

长答案

这是一个棘手的问题。我读过的大多数书籍都忽略了该主题,并将其保留在:

首先渲染所有不透明对象,然后以从后到前的顺序混合透明对象。

说起来容易做起来难,因为按质心对对象进行排序的明显方法不能保证正确的排序顺序。

为什么画家的算法在一般情况下不起作用,并且需要深度缓冲区,这是完全相同的问题。

话虽如此,我在其中一本书中提到了一些解决方案:

  • 深度剥离 -一种多遍解决方案,它通过为我们提供第n个最接近的片段而不仅仅是最接近的片段,从而克服了深度缓冲区的限制。最大的优点是您可以按任何顺序渲染透明对象,而无需进行排序。由于多次传递,它可能会很昂贵,但是我在顶部给出的链接似乎可以提高性能。

  • 模版布线的K缓冲区 -使用模版布线来捕获每个几何遍次每个像素的多个片段层。主要缺点是片段需要在后处理过程中进行排序。

它还提到了该问题的硬件解决方案,但我认为它实际上不可用:

  • F缓冲区 -用于多遍渲染的栅格化顺序FIFO缓冲区。但是,请仔细阅读,并且引言还谈到了透明排序问题和当前解决方案。

其他无法提供完美结果但总比没有好的解决方法:

  • 渲染所有不透明对象后,请继续对透明对象使用Z缓冲区测试,但禁用Z缓冲区写入。您可能会从不正确的排序中得到一些人工痕迹,但是至少所有透明的对象都是可见的。

并引用上面的F缓冲区白皮书:

最简单的解决方案是完全独立地渲染每个部分透明的多边形(即在进行下一个多边形之前渲染其所有通道)。由于所引起的状态改变成本,该解决方案通常非常昂贵。或者,应用程序或着色库可以对多边形进行分组,以确保仅将不重叠的多边形渲染在一起。在大多数情况下,此解决方案也没有吸引力,因为它需要软件执行多边形的屏幕空间分析。


11

正确的答案是#1:按深度对所有内容进行排序并渲染它们(显然,请关闭深度书写,但不进行测试)。什么是“东西”?

每个“事物”必须是一个凸物体;它不能自我重叠。如果您的物体是凹形的,则必须将其分解成凸形的碎片。

这是渲染透明场景标准方法。它能解决互穿案例吗?否。是否可以解决您无法确定3个深度顺序的情况?否。是否可以解决您的长对象与中心深度较近的小对象重叠的情况?没有。

但是效果很好。游戏不使用深度剥离。他们不使用模具路由的k缓冲区。他们不使用F缓冲区。为什么?因为这些事情太慢了。

您可能会使用标准方法获得工件。但是至少您的游戏运行得相当快。

如果您愿意将自己限制在DX11或更好的硬件上,则可以采用适当的排序方法来实现混合。它们速度较慢,但​​不比以前的技术慢。而且与可能引起伪影的深度剥皮不同,该工具非常精确。另外,算法的性能通常是每个片段(在某种程度上每个片段内的每个重叠部分)。因此,如果您没有画很多透明的东西,那么性能将是最小的。

我不知道该技术的名称是否虚假,但可以在此处找到GL4.2之前的一种实现。一个D3D11的版本可以在这里找到(PowerPoint中,PPSX,自由报兼容)。


关于这个答案的好点。我个人也会感到足够满意(我在回答中确实将其描述为一种变通方法),因为我列出的大多数技术可能比它们值得的麻烦更多。另外,最后是有趣的技术,我认为它没有在我研究其答复的“ 实时渲染”中列出。对于DX11级功能,我是一个完全菜鸟。
David Gouveia '04

“可以在此处找到GL4.2之前的一种实现方式” 404
Jeroen van Langen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.