自适应屏幕空间环境光遮蔽

下载文档下载代码示例

本文将介绍自适应屏幕空间环境光遮蔽 (ASSAO) 效果的最新实施方法,该技术经过精心设计,只需实施外观、设置和质量统一、符合行业标准的方法,就可从低能耗设备和场景扩展至高分辨率的高端台式机。

在实时渲染过程中,屏幕空间环境光遮蔽 (SSAO) 常用于打造小范围环境光效果和接触阴影效果。 许多现代游戏引擎都会用到这项技术,通常使用 5-10% 的帧 GPU 时间。 尽管市场上提供大量实施方法,但其中有许多不具备开源特性,不免费提供,也无法为低能耗移动设备和台式机提供充足的扩展性能。 ASSAO 的出现有效地填补了这一空白。

下面先用一个简短的视频来展示一下ASSAO的使用效果。

本文将重点介绍如何理解和集成或移植示例代码。 另外还将介绍相关的实施细节、可用选项、设置,以及使用过程中需进行的权衡。 即将出版的书籍《GPU Zen (GPU Pro* 8)》刊登了一篇专门介绍这种实施方法的文章。


图 1.  Unity 4* 测试场景中所使用的自适应 SSAO 示例。

完整 DirectX* 11 实施方法根据易于集成的软件包中的 MIT 许可证提供。

算法概述

ASSAO 是面向可扩展性和灵活性调整后的 SSAO 实施。 环境光遮蔽 (AO) 实施以立体遮蔽模式为基础,类似“水平环境光遮蔽”[Bavoil 等, 2008 年]和创新型渐进取样核心磁盘。 与此相关的性能框架基于 2 x 2 版高速缓存友好型解交织渲染技术,“面向高效缓存交替取样的解交织纹理”[Bavoil,2014 年],以及可选深度 MIP 映射“可扩展环境遮蔽”[McGuire 等, 2012 年]。

通过改变 AO 轻击(渐进取样核心支持)数量和在不同预设级中进行特性切换,可实现与性能相关的扩展质量。

随机取样可用于共享邻近像素间的 AO 值(基于旋转并不断扩展的取样磁盘)以及最后使用的去噪模糊。 去噪模糊能够感知边缘,防止效果渗透到不相关的背景或前景对象中,从而避免产生光晕。 边缘可仅基于深度,也可基于深度和法线。 (后者可以提高质量,但会延长处理时间)。 智能模糊在 2 x 2 解交织域中执行,以实现最高缓存效率,仅最终通道以全高清在交织(重构)通道中完成。

从实际应用角度来说,它是一种基于多通道像素着色器的技术。 在“高”预设情况下,主要步骤包括:

  1. 准备深度
    1. 4 个四分之一深度缓冲区中的 2 x 2 解交织输入屏幕深度,并将数值转化成视图空间。 另外,如果不提供输入屏幕法线,则需要通过深度重构。
    2. 为每个小型深度缓冲区创建 MIP(不在“低”或“中”预设中进行)。
  2. 计算每个 2 x 2 解交织部分(共 4 个)的 AO 选项和边缘感知模糊
    1. 计算AO 选项和边缘,并将其保存在 R8G8 纹理中。
    2. 使用边缘感知智能模糊(1-6 个通道,根据用户设置)。
  3. 将 4 个部分合并成最终的全分辨率缓冲区,并使用最终边缘感知模糊通道。

“最高/自适应”质量预设中包含辅助基底 AO 通道,可用于提供重要性启发法,为主 AO 通道的每像素变量示例数提供指导。

表 1 对性能数据进行了总结概括。 这些数据仅供参考,可能因驱动程序和硬件规格的不同而有所差异。 更改效果设置不会改变性能,但边缘感知模糊除外;增加模糊通道数会导致成本上升。

 

Skull Canyon (Iris Pro 580)

GTX 1080

RX 480

 

1920 x 1080

1920 x 1080

3840 x 2160

1920 x 1080

3840 x 2160

2.4

0.28

1.21

0.64

2.58

4.1

0.49

2.25

1.01

4.09

6.9

0.77

3.15

1.34

4.74

最高

10.4

1.12

4.65

2.07

7.44

表 1.  不同预设、分辨率和硬件情况下的 ASSAO 效果成本(毫秒)。

根据提供的屏幕法线进行分析,双通道模糊和“最高”自适应目标设为 0.45,通过更改 AO 轻击数,以及切换各特定的启/闭状态,可以在“低”/“中”/“高”/“最高”预设之间扩展效果(质量与性能)。 表 2 显示了这些预设的详细设置。

 

示例数

2 x 2 解交织

深度 MIP

边缘感知模糊

6

10

(仅深度)

24

有+

(深度 + 法线)

最高(自适应)

10–64

有+

(深度 + 法线)

表 2.  ASSAO 预设详情。

示例概述

该示例使用 DirectX 11,并兼容 Windows* 7 64 位或更高版本,也可兼容 Microsoft Visual Studio* 2015。


图 2.  自适应 SSAO 示例布局。

本示例中包含的 Crytek Sponza* 场景可在默认情况下使用,右上角表格列出了基本的效果分析指标。 表格下方是用于更改效果设置、质量或调试效果的衡量指标。 主要设置包括:

  1. 启用效果

    关闭/打开效果。 见屏幕图像 0(关)1(开)。

  2. 效果半径

    视野空间单元中的环境光遮蔽半径。 见屏幕图像 456

  3. 效果强度

    线性效果倍增器,用于设置效果强度,增加效果威力,以及效果渐显/渐弱。 见屏幕图像 78910

  4. 效果威力

    指数级效果倍增器: occlusion = pow(occlusion, effectPower). 调整效果曲线的最佳方法。 见屏幕图像 11121314

  5. 详细效果强度

    额外的 2 像素宽核心用于添加高频率效果。 高数值会导致混淆和暂时的不稳定。 见屏幕图像 1516171819

  6. 模糊量

    模糊通道较多时,能够以较少的高频率变化提高效果的流畅度,这样可带来优势(减少混淆现象),但会导致成本上升。 见屏幕图像 2021222324

  7. 模糊锐度

    确定基于距离(和可选法线)的边缘上的模糊量,防止前景和背景对象之间的渗透,从而避免产生光晕和其他问题。 数值 1 表示完整锐度(不模糊边缘),数值变小表示逐渐放开限制。 数值接近 1 可用于控制混淆现象。 见屏幕图像 2526

  8. 递延路径

    在递延路径中,相关的效果输入包括屏幕深度和法线贴图纹理。 相反,如果使用前向路径,输入仅包含深度纹理,法线贴图通过深度重构,这样会增加成本并导致结果稍有不同。 见屏幕图像 2728

  9. 扩展分辨率

    在屏幕边缘附近,效果核心负责的部分位于屏幕之外。 尽管可使用不同的取样模式(比如夹紧/镜像)得到不同的结果(见 m_samplerStateViewspaceDepthTap),但最好的方法以一定的比例扩展渲染区域和分辨率,同时创建深度缓冲区,以便提供边缘附近 AO 效果所需的数据。 该选项可完成这一操作,而且 ASSAO 使用可选 scissor 矩形,可避免计算有关扩展(不可见)区域的 AO。 见屏幕图像 2930

  10. 启用纹理

    切换纹理,以提高 AO 效果的可见性(依然应用光照)。 见屏幕图像 3132

  11. 质量预设

    切换四种质量预设,如表 1 和表 2 所示。 见屏幕图像 33343536

    就“最高”/“自适应”预设而言,自适应目标用于控制可在运行时更改的渐进质量目标,以快速权衡质量和性能。 见屏幕图像 373839

  12. 切换至高级 UI

    为了更详细地调试效果,该示例可切换至高级 UI,支持访问更多场景(见屏幕图像404142)和效果开发版本,有助于提供更深入的分析和各种调试视图,从而显示法线(屏幕图像 43)、检测边缘(屏幕图像 44)、有关已选像素的 AO 示例(屏幕图像 45)以及自适应效果热点图(屏幕图像 46)。

集成详情

只需使用本示例项目的三个文件,就可快速集成至 DirectX 11 代码库:

Projects\ASSAO\ASSAO\ASSAO.h
Projects\ASSAO\ASSAO\ASSAODX11.cpp
Projects\ASSAO\ASSAO\ASSAO.hlsl

它们包含不涉及其他相关性(DirectX 11 API 除外)的整个 ASSAO 实施过程。

基本 ASSAO 集成步骤包括:

  1. ASSAO.hASSAODX11.cpp 添加至项目。
  2. 添加支持加载过程的 ASSAO.hlsl 文件,或参阅 ASSAOWrapperDX11.cpp (和项目自定义构建步骤)中的“USE_EMBEDDED_SHADER”,以详细了解如何轻松将 .hlsl 文件嵌入至二进制文件。
  3. DirectX 11 设备创建完成后,通过向静态 ASSAO_Effect::CreateInstance(…) 提供 ID3D11Device 指示器和着色器源缓冲区,创建 ASSAO_Effect 对象实例。 毁坏 DirectX 设备之前,不要忘记调用 ASSAO_Effect::DestroyInstance() 毁坏该对象。
  4. 在渲染后期处理管道中查找合适的位置: SSAO 通常直接应用于聚光或后期色调图色彩缓冲区,实现其他屏幕空间效果之前通常使用多重混合模式。 有时使用物理校正方法将 AO 选项渲染至单个缓冲区,以便后期在光照通道中使用。 不管在何种情况下,如果所需的输入为场景深度(和屏幕空间法线(如有)),将意味着只要可用就可绘制 ASSAO。
  5. 通过填写 ASSAO_InputsDX11,设置每帧输入结构:
    1. 如果效果输出只需限制在较小的矩形中,比如如果采用扩展分辨率方法,则只需 ScissorLeft/Right/Top/Bottom。 否则,默认为 0,表示输出将前往整个视口。
    2. ViewportX/Y 必须设为 0,以及 ViewportWidth/Height 设为输出渲染目标和输入深度和屏幕空间法线纹理分辨率。 尚不支持自定义视口。
    3. ProjectionMatrix 必须设为用于绘制深度缓冲区的投影。 支持 LH 和 RH 两种投影矩阵,以及相反的 Z (http://outerra.blogspot.de/2012/11/maximizing-depth-buffer-range-and.html)。
    4. 如果输入屏幕空间法线不在视野空间中,则需要 NormalsWorldToViewspaceMatrix(可选),该矩阵可用于转换。
    5. MatricesRowMajorOrder 可定义输入 ProjectionMatrixNormalsWorldToViewspaceMatrix 的内存布局。
    6. NormalsUnpackMulNormalsUnpackAdd 分别默认为 2 和 -1,通过经常保存它们的 UNORM [0, 1] 纹理将法线解包成 [-1, 1] 范围。如果浮点纹理提供法线,这两个值必须设为1 (mul) 和 0 (add)。
    7. DrawOpaque 用于确定混合模式:如果为真值,将覆写所选渲染目标的内容;如果为假值,则使用乘法混合模式。
    8. DeviceContext(特定于 DirectX 11)应设为用于渲染效果的 ID3D11DeviceContext 指示器。
    9. DepthSRV(特定于 DirectX 11)应设为输入深度数据。
    10. NormalSRV (特定于 DirectX 11)应设为输入屏幕空间法线或 nullptr(如果不可用,在这种情况下法线将通过深度数据重构)。
    11. OverrideOutputRTV(特定于 DirectX 11)应设为 nullptr 或输出渲染目标。 如果设为 nullptr,则使用当前所选的 RTV。
  6. 设置 ASSAO_Settings 中规定的效果设置结构。 示例概述部分将对此进行了详细介绍。
  7. 调用 ASSAO_Effect::Draw 函数。 所有当前 DirectX 11 状态都完成了备份,调用后可进行恢复以确保无缝集成。

示例项目中的以下文件可提供集成示例:

Projects\ASSAO\ ASSAOWrapper.h
Projects\ASSAO\ ASSAOWrapper.cpp
Projects\ASSAO\ ASSAOWrapperDX11.cpp

可访问 https://github.com/GameTechDev/ASSAO,下载最新源代码。

参考书目

[Bavoil 等, 2008 年] Bavoil, L.、Sainz, M. 和 Dimitrov, R,2008 年。 “图像空间水平环境光遮蔽”。 ACM SIGGRAPH 2008 talks, ACM, New York, NY, USA, SIGGRAPH ’08, 22:1–22:1。

[McGuire 等, 2012 年] Morgan McGuire、Michael Mara、David Luebke。 “可扩展环境光遮蔽”。 HPG 2012。

[Bavoil,2014 年] Louis Bavoil,“面向高效缓存交替取样的解交织纹理”。 NVIDIA 2014。

声明

该示例源代码根据 MIT 许可证发布。

有关编译器优化的更完整信息,请参阅优化通知