使用逐像素排序链表的与顺序无关的透明度

此示例的源代码可在 Khronos Vulkan 示例 github 存储库中找到。
Sample

概述

此示例使用逐像素排序的链表实现与顺序无关的透明度 (OIT) 算法。它渲染 64 个具有随机颜色和不透明度(从 0.2 到 1.0)的球体。它产生像素完美的结果。

算法

OIT 算法由两个阶段组成:收集阶段和组合阶段。

在收集阶段,透明几何体被渲染到逐像素排序的链表中。每个片段的颜色和深度都被推送到与其目标像素关联的链表中。链表的头存储在大小与屏幕相同的存储图像中。片段数据(颜色和深度)存储在所有链表共享的存储缓冲区中。

组合阶段是一个屏幕空间操作。对于每个像素,它会对存储在该像素链表中的片段进行排序。然后,它将它们进行 alpha 混合(在着色器代码中)以产生最终的透明颜色和覆盖率。最后,它将透明颜色通过固定混合函数混合到后缓冲区中。

该算法可以产生像素完美的结果,即使在几何体相交的情况下也是如此。但是,有一个问题。为了保持高性能,每个像素排序的最大片段数限制为 16。对于超过 16 个片段,该算法会尽最大努力混合额外的片段,但结果可能不准确。对于示例来说,这已经足够好了,因为对象在场景中的放置方式。一般来说,性能和正确性之间需要权衡。为了保持较高的占用率,每个排序片段的最大数量(combine.frag 中的 SORTED_FRAGMENT_MAX_COUNT)应保持较低。为了在任何情况下都获得正确的结果,该数字应尽可能高。通过使用“每个像素排序的片段”选项,可以观察到每个像素排序的片段数量较少导致的伪影。

选项

选项 描述 注释

排序片段

在组合阶段启用片段排序

此选项禁用时,旨在演示非排序透明几何体发生的视觉问题。

相机自动旋转

启用相机的自动旋转

每个像素排序的片段

指定每个像素排序的最大片段数

此选项设置为较低的数字(例如 4)时,会突出显示该算法的主要弱点。

背景灰度

指定背景颜色乘以的灰度值(0.0 到 1.0)

测试

此示例在 Windows 上进行了测试。验证层已启用,并且所有报告的问题都已修复。该示例在开发过程中也在 Linux 上进行了测试。两个系统都配备了 AMD GPU。