寒霜引擎中基于物理的天空、大气和云渲染

257 阅读1小时+

目录

1 引言 4

1.3 贡献者 6

2 参与介质 8

3 天空与大气 17

3.5 我们的方法 21

3.5.1 性能 22

3.5.2 结果 22

4 太阳、月亮和星星 23

4.1 太阳 25

4.1.3 临边昏暗 28

4.3 星星 28

5 云 30

5.1 背景与前期工作 30

5.2 云参与介质材料 32

5.3 云创作 32

5.4 云噪声 34

5.5 云渲染 35

5.3.1 云分布与密度 33

5.4.1 云材料 35

5.5.1 环境光照 35

5.6 改进的散射 36

5.6.2 更好的数值积分 38

5.7 云相位函数 39

5.8 多重散射 41

5.9 其他相互作用 42

5.6.3 能量守恒解析积分 38

5.9.1 影响云的空中透视 43

5.9.2 云对空中透视的影响 43

6 结论 45

6.1 未来工作 50

A 天空查找表参数化 57

B 太阳临边昏暗天体物理模型 60

C 能量守恒解析散射积分 61

D 可平铺体积噪声库 62

1 引言

视频游戏对视觉质量和动态性的要求越来越高。例如,开放世界游戏可能需要大量动态元素,如一天中不同时间的光照和实时变化的天气。这些元素的动态性及其通常的全局性,使得实时模拟和渲染它们变得困难。天空、大气和云是我们需要模拟的三个主要组件,以实现动态的时间变化和天气条件。由于它们具有非常细致且特殊的体积特性,因此很难渲染。这些元素之间也存在相互作用,例如云会影响大气光照,反之亦然。

在本文档中,我们介绍了为寒霜引擎研究和开发的实用基于物理的解决方案,用于模拟和组合所有这些元素,以及渲染它们之间的复杂相互作用。我们还将描述这如何融入寒霜引擎的基于物理的着色框架,以及艺术家如何创作这些元素(包括已发布和正在制作的作品),并介绍它们的性能特点。

1.1 背景

2014 年,寒霜引擎 1 经过重大改进,成为基于物理的渲染引擎 [LR14]。除其他方面外,这导致了灯光和材料定义的解耦,改变了艺术家指定它们的方式以及它们相互作用的方式。这些变化一直影响到相机接收器以及光照信息在屏幕上的转换和呈现方式。这带来了视觉质量的巨大提升,如图 1 所示。很难分辨哪张图片是真实的,哪张是计算机生成的:左边还是右边?

image.png

图 1:《极品飞车》[Gho17] 对比:现实与寒霜引擎。你能分辨出哪个是哪个吗?

采用基于物理的方法,将光照和材料信息解耦,意味着一旦创建了一种材料,它在任何光照条件下都应看起来保持一致。

1 寒霜引擎是一个游戏开发平台,为电子艺界(EA)的大多数游戏提供支持。详见 www.frostbite.com

这一点现在尤为重要,因为许多 EA 游戏本质上更偏向开放世界,具有时间变化和动态天气。然而,当时寒霜引擎的天空、雾、云和参与介质系统仍然是非常静态的元素,只能进行线性混合。这些元素包括全景天空纹理、天空颜色渐变、雾颜色、雾曲线等。艺术家需要确保一天中每个时间的所有这些颜色和曲线都保持一致,这非常耗时,特别是因为每个状态都可以线性插值并包含高动态范围内容。而且,在收到艺术指导反馈后需要重新创作时,也需要投入大量时间。这些技术本身并没有什么问题,因为它们确实让《战地 4》和《星球大战:前线》等游戏看起来非常出色(图 2)。话虽如此,我们需要更先进的解决方案,使游戏能够支持更多动态场景。

image.png

图 2:上图和下图:《战地 4》[DIC13] 和《星球大战:前线》[DIC15]。

1.2 范围和目标

图 3 展示了我们希望游戏艺术家能够在寒霜引擎中实现的效果:

image.png

图 3:包含天空和大气散射、太阳和云的空中透视照片。

  • 支持动态时间变化的真实天空

  • 根据太阳位置的动态光照

  • 大气散射

  • 随天气变化的云

我们希望这些技术具有可扩展性,以便同时用于 30 FPS 和 60 FPS 的游戏。我们还希望这些新技术能够融入寒霜引擎的基于物理的框架。这意味着将光照参数与材料表示解耦,并使用基于物理的参数化来表示参与介质材料的真实物理特性。

此外,许多 EA 游戏需要在高视觉质量下达到稳定的 60 帧 / 秒。这本身就具有挑战性,而在具有动态时间变化和天气的情况下,在满足这一约束的同时发布游戏则更为复杂。特别是当你希望所有不同的系统保持同步时。

而且,我们希望所有这些视觉特征能够连贯地相互作用,并在参与介质、不透明和透明材料之间默认保持尽可能真实和统一。例如,云变得更大更厚时,应该会影响通过大气散射的光线以及太阳阴影,这反过来又会影响全局光照,从而影响透明表面的全局反射等。

1.3 贡献者

本文档中介绍的工作是寒霜引擎团队、硕士研究生以及游戏团队工程师和艺术家之间大量合作的成果。

关于天空和大气系统,我们要感谢 Gustav Bodare(Ghost 工作室)和 Edvard Sandberg(Ghost 工作室),他们是 2014 年的硕士研究生,以及 Bioware(《质量效应:仙女座》)、DICE(《镜之边缘:催化剂》)、Ghost(《极品飞车》)。

关于体积云系统,我们要感谢 Rurik Högfeldt(2015 年寒霜引擎硕士研究生)以及 Bioware 的 Marc-Andre Loyer(程序员)、Soren Hesse(技术环境艺术师)和 Don Arceta(首席环境艺术师)。

感谢 Per Einarsson、Charles de Rousiers 和 Tomasz Stachowiak 以及寒霜引擎渲染团队就这些渲染技术进行的所有讨论和提供的帮助。

感谢渲染研究社区分享如此令人难以置信的知识、有用的研究和实用的成果,有时还包括源代码!请继续这样做。感谢 Fabrice Neyret、Eric Bruneton 和 Antoine Bouthors 关于天空和云渲染的讨论。

最后,感谢 Stephen Hill 和 Stephen McAuley 在 SIGGRAPH 2016《基于物理的着色:理论与实践》课程 [MH16] 的准备、演示和本文档的审阅过程中提供的帮助。

2 参与介质

参与介质是用于描述充满粒子的体积的术语。这些粒子可以是大的杂质,例如灰尘、污染物、水滴,或者仅仅是分子等粒子。根据其成分,介质与穿过其中并在粒子上反射的光线会有不同的相互作用,通常称为光散射。单位体积内的粒子密度也可能在空间上变化,并在不同尺度上呈现不同的形式。例如,对于水滴,分布范围广且密度低的体积可以代表均匀的雾(即均匀介质),而局部密度高的体积可以代表云(即非均匀介质)。

在本文档中,我们将重点关注由不同半径的球形粒子表示的参与介质。我们不会讨论微薄片的表示和理论。这意味着我们假设参与介质是各向同性的,即散射概率不依赖于入射光方向,但仍然允许非对称散射,即散射量依赖于入射光方向,并由相位函数驱动(见第 2.3 节)。我们还将忽略发光的参与介质,例如黑体模拟。本文档中使用的符号如表 1 所示。

符号描述单位
σₐ吸收系数m⁻¹
σₛ散射系数m⁻¹
σₜ消光系数m⁻¹
ρ反照率无单位
p相位函数sr⁻¹
L亮度cd·m⁻²
L(x, ω)点 x 处沿方向 ω 的亮度cd·m⁻²
E照度cd·sr⁻¹·m²

表 1:本文档中使用的符号。

在本节中,我们介绍参与介质体积光照和阴影的理论。我们还将介绍不同的参数以及它们如何相互作用并影响最终结果。目的是帮助你理解每个不同参数的行为。

为了进一步学习,你还可以访问 ShaderToy 网站,获取体积散射和阴影的示例代码(见图 4)。寒霜引擎使用此类代码来模拟体积光相互作用。

image.png

图 4:展示体积散射和阴影的 ShaderToy 示例[Hilb][Hilc]。

2.1 单次散射

我们将重点关注参与介质中单次散射的模拟和渲染。如果你在阅读本章后仍有兴趣了解更多,可以阅读以下写得非常好的资料:[PH10]、[dEo16] 或 [Wre11]。关于散射事件的最佳解释之一可以在 [Jar08] 的第 4 章中找到。

考虑光线直线穿过介质时,出射亮度可能与入射亮度不同,原因如下:

  • 吸收:光子被介质物质吸收。

  • 外散射:光子被介质中的粒子散射出去。这将根据描述反射方向分布的相位函数 p 进行(见第 2.3 节)。

  • 内散射:光子在经过粒子反射后可以散射到当前光路上,并对最终亮度产生贡献。这也将根据相位函数 p 进行。

  • 发射:当介质达到高温时会发光,例如火焰。本文档中我们忽略这一成分。

总而言之,增加光路上的光子是 σₛ 的函数,而减少光子是消光 σₜ 的函数,消光同时代表吸收和外散射。

这些事件中的每一个都与波长有关。这意味着不同频率的光被吸收或散射的概率不同。为了实时效率,我们将简化处理,只考虑红(680nm)、绿(550nm)和蓝(440nm)光光谱。可以使用方程 1 考虑点光源,对每个光谱的亮度进行积分。图 5 展示了不同组件的示意图。

Li(xi,ωi)=Tr(x,xs)L(xs,ωi)+t=0STr(x,xt)Lscat(xt,ωi)σsdtL_{i}\left(x_{i}, \omega_{i}\right)=Tr\left(x, x_{s}\right) L\left(x_{s}, \omega_{i}\right)+\int_{t=0}^{S} Tr\left(x, x_{t}\right) Lscat\left(x_{t}, \omega_{i}\right) \sigma_{s} d t

image.png

图 5:使用本节介绍的参数和方程,说明在具有单个点光源的虚拟世界中散射光积分的示意图。

方程 2 中的透射率 Tr (x, xₜ) 是消光的函数。消光越高或距离越远,光学厚度 τ=σₜ(xₜ) dt 就越大,反过来,穿过介质部分的光就越少。图 6 展示了透射率函数的行为。透射率需要应用于(1)来自不透明表面的亮度 L (xₛ, ωᵢ),(2)内散射事件产生的亮度 Lscat (xₜ, ωᵢ),以及(3)从散射事件到光源的每条路径。(1)会导致表面出现类似雾的遮挡效果,(2)会导致参与介质的自遮挡,(3)会导致参与介质内的体积阴影。由于 σₜ=σₐ+σₛ,因此透射率预计会受到散射(即外散射)和吸收成分的影响。

Tr(xa,xb)=exp(x=xaxbσt(x)dt)Tr\left(x_{a}, x_{b}\right)=exp \left(-\int_{x=x_{a}}^{x_{b}} \sigma_{t}(x) d t\right)

image.png

图 6:透射率函数作为深度和消光系数 σₜ=0.5、σₜ=1.0 和 σₜ=2.0 的函数。

方程 3 中的 Lscat (x, ωᵢ) 表示单次内散射事件,描述了根据场景中所有点光源、可见性函数 Vis (x, L) 以及第 2.3 节中描述的相位函数 P,散射回某个方向的亮度量。

Lscat(x,ωi)=i=0lightsp(ωi,L)Vis(x,L)Li(x,L)(3)Lscat\left(x, \omega_{i}\right)=\sum_{i=0}^{lights } p\left(\omega_{i}, L\right) Vis(x, L) L_{i}(x, L) \quad (3)

方程 4 中的可见性函数 Vis (x, L) 表示到达光源的光量。例如,如果一个不透明物体位于光源和采样点之间,从而遮挡了采样点,那么 shadowMap (x, L) 将简单地返回 0 而不是 1(在无限小点光源的情况下,忽略软阴影)。这通常是通过依赖光照视图深度纹理的硬件阴影映射来实现的。

体积阴影 volumetricShadow (x, L) 表示从采样点到光源位置的透射率,每个波长的值在 [0,1] 范围内,从而允许参与介质自阴影。这通常是通过向每个光源进行二次光线步进实现的。作为质量和性能的权衡,可以使用特定的体积阴影采样 / 存储技术 [Hil15][JB10][Sal+10] 来存储从光源发出的方向的透射率。

Vis(x,L)=shadowMap(x,L)volumetricShadow(x,L)volumetricShadow(x,L)=Tr(x,xL)\begin{aligned} Vis(x, L) & =shadowMap(x, L) * volumetricShadow(x, L) \\ volumetricShadow(x, L) & =Tr\left(x, x_{L}\right) \end{aligned}

2.2 反照率

方程 5 中的反照率是一个值,表示在介质中每个考虑的光谱带中散射相对于吸收的相对重要性。该值在 [0,1] 范围内:

  • 反照率接近 0 表明大部分光被吸收,导致介质非常暗(例如,深色的废气烟雾)

  • 反照率接近 1 表明大部分光被散射而不是被吸收,导致介质更亮(例如,空气、云或地球大气)

ρ=σs/(σs+σa)ρ=σs/σt \begin{aligned} \rho&=\sigma_{s} /\left(\sigma_{s}+\sigma_{a}\right) \\ \rho&=\sigma_{s} / \sigma_{t} \end{aligned}

2.3 相位函数

如前所述,参与介质由不同半径的粒子组成。这些粒子半径的分布将影响介质内任何点的光散射方向分布。描述这种概率分布是通过使用相位函数来实现的,如方程 3 中所示,在评估内散射时使用。

x=2πrλ(6)x=\frac{2 \pi r}{\lambda} \quad (6)

相位函数会根据到达该点的定向亮度信息改变点处的内散射。根据方程 6 中定义的粒子相对大小(其中 r 是粒子半径,λ 是所考虑的波长),可以识别不同类型的散射 [Hul57][Wikg]:

  • x<<1:例如瑞利散射(如空气)

  • x≈1:米氏散射

  • x>>1:几何散射

更多因素会影响散射结果,例如折射率或参与介质的内容等。在本文档的这个版本中,我们将忽略它们。

2.3.1 各向同性散射相位

在这种情况下,光将均匀地散射到所有方向。这当然不是一个非常现实的场景,但由于其简单性而被广泛使用。相位函数如方程 7 所示,其中 θ 是入射光方向和外散射方向之间的角度。

p(θ)=14π(7)p(\theta)=\frac{1}{4 \pi} \quad (7)

2.3.2 瑞利散射相位

p(θ)=316π(1+cos2θ)p(\theta)=\frac{3}{16 \pi}\left(1+\cos ^{2} \theta\right)

瑞利推导出了光在空气中分子上的散射表达式 [Ray71]。例如,瑞利散射用于描述地球大气中发生的光散射,并且据报道其吸收非常低或没有吸收。这种相位是一个双瓣函数,如图 7 所示,可以使用方程 8 进行评估。

image.png

图 7:瑞利相位函数的极坐标图

瑞利散射也高度依赖于光的波长。这由 [Jar08] 中提出的波长相关散射系数 σₛ 方程表示。常用的近似方法是为评估 / 渲染此类散射事件时常用的简化红、绿、蓝光光谱带中的每一个设置恒定的 σₛ。

2.3.3 米氏散射相位

米氏散射 [Mie08] 是当粒子大小与光波长相似时可以使用的模型。然而,米氏散射模拟复杂,需要许多幂函数。

另一种选择是使用 g 在 ] 0,1 [ 范围内的 Henyey-Greenstein 相位函数。它被提出用于表示星际尘埃的散射。它也可以用于表示任何烟雾、雾或灰尘等参与介质。这种介质可以表现出非常强烈的后向或前向散射,导致光源周围出现大的视觉光晕,例如雾中的聚光灯,或云边缘沿太阳方向的强烈亮边效果。

phg(θ,g)=1g24π(1+g22gcosθ)1.5(9)p_{h g}(\theta, g)=\frac{1-g^{2}}{4 \pi\left(1+g^{2}-2 g \cos \theta\right)^{1.5}} \quad (9)

这种 Henyey-Greenstein 相位函数可以具有比瑞利散射更复杂的形状,并使用方程 9 进行评估。如图 8 所示,它可以产生各种形状。前向或后向散射的强度由 g 参数控制。

image.png

图 8:Henyey-Greenstein 和 Schlick 近似相位函数的极坐标图。

一种快速近似 Henyey-Greenstein 相位函数的方法是使用 Schlick 提出的近似。方程 10 不包含任何复杂的幂函数,而只包含一个平方,计算速度快得多。为了能够将该函数映射到原始的 Henyey-Greenstein 相位函数,需要使用 g 通过方程 9 计算 k 参数。对于具有恒定 g 值的参与介质,这只需进行一次。值得注意的是,对于非常大的正负 g 值,误差会变得相当大(见图 9),并导致亮边效果减弱。

k1.55g0.55g3p(θ,k)=1k24π(1+kcosθ)2 \begin{aligned} k & \approx 1.55 g-0.55 g^{3} \\ p(\theta, k) & =\frac{1-k^{2}}{4 \pi(1+k \cos \theta)^{2}} \end{aligned}

image.png

图 9:Henyey-Greenstein 和 Schlick 近似相位函数的极坐标图,显示在大 g 值时误差较大。

2.3.4 几何散射相位

几何散射发生在非常大的粒子上。在这种情况下,光可以在每个粒子内折射和反射。这会导致复杂的散射相位函数,该函数也依赖于光的偏振。例如,现实生活中的一个例子是视觉上的彩虹效果。它是由空气中水滴内的光的内反射引起的,将太阳光分散到可见光谱中,在较小的视角(约 3 度)内产生后向散射。

可以使用 MiePlot 软件 [Lav15] 评估这种复杂的相位函数。该软件使用米氏散射理论、德拜级数和光线追踪来评估相位函数。生成的相位函数可以可视化并输出到文件中,供你的应用程序使用,如图 10 所示。

2.4 示例

本节介绍体积渲染的不同组件,以及它们如何影响体积的最终视觉外观。如果你刚开始尝试这类算法,本节有望让你对不同参数的作用和影响有一个很好的直观理解。如果你认为有任何遗漏,请务必联系我们 2,我们将更新本节。

image.png

图10 米氏散射相位函数极坐标图 image.png

图 11:启用不同的体积渲染组件:(a)σₛ=1 散射,无体积阴影;(b)σₛ={0.5,1.0,2.0} RGB 散射,带有使用 σₜ=mean(σₛ) 实现的灰色体积阴影;(c)带有使用 σₜ=σₛ={0.5,1.0,2.0} 实现的彩色体积阴影。在每个示例中,吸收都设置为 σₐ=0。(a)和(b)在物理上不正确,但在这里用于展示组件的贡献

图 11 分别展示了启用不同组件的效果。图像(a)显示在白光和白色散射 σₛ=1 下的斯坦福兔子形状的参与介质。图像(b)显示相同的介质,但 σₛ={0.5,1.0,2.0}。由于蓝色光散射更多,兔子整体呈蓝色。体积阴影是使用方程 4 评估的灰色阴影。灰度阴影是使用 σₜ=2.0 实现的。这只是为了展示体积阴影的添加,尽管这在物理上是不正确的。为了物理正确,体积阴影应该使用 σₜ=σₛ+σₐ={0.5,1.0,2.0} 进行评估(考虑到在这种情况下 σₐ=0)。结果如图 11(c)所示。 image.png

图 12:(a)图表表示光在均匀介质中传播后散射的光量,考虑了透射率,并假设相位函数均匀,x 轴表示距离。(b)图表的相应颜色渐变可视化。

在空气和介质的界面处,当光传播路径不长时,蓝光散射更多,导致呈蓝色。对于从入口点深入的长光路,蓝光已被更多地散射。结果,只剩下其他成分:这就是为什么在这种材料配置中红光更明显。这种行为实际上类似于光在大气中的传播。它只在更大的尺度上发生,因为大气中空气分子的浓度低得多(见第 3 节)。为了使用相同的系数来说明这个想法,我们在图 12 中以图表形式给出了红、绿、蓝波长的一维散射分布和颜色渐变。

image.png

图 13:斯坦福兔子和龙,密度不断增加(从左到右:0.1、1.0 和 10.0),其中 σₛ={0.5,1.0,2.0}

图 13 展示了斯坦福兔子和龙,使用相同的参与介质材料(σₛ=0.5,1.0,2.0)但密度不同。对于低密度介质,散射系数将决定参与介质的主要颜色。当密度增加时,由于吸收和外散射,产生的行为将更加复杂,如前所述。在最右边图片的高密度情况下,物体开始看起来几乎像 flesh/skin。这是因为我们的皮肤也具有类似的整体特征:红光在我们的 flesh 中传播得更远。皮肤也是一种更复杂的体积材料,具有许多层,因此使用光线步进评估可能成本很高。相反,它通常使用更便宜的扩散分布来近似,忽略任何形式的单次散射相位函数或各向异性 [Jen+01b][DL07]。

image.png

图 14:斯坦福兔子使用 Henyey-Greenstein 相位函数 9,g 从各向同性到强前向散射(从左到右 g=0.0,0.5,0.9,0.99,0.999),密度为 1.0(上)和 10.0(下)。

相位函数也会极大地影响参与介质的最终外观。例如,要实现云的特征外观,获得它们特有的亮边视觉效果至关重要。对于许多类型的烟雾也是如此。这种现象在图 14 中可见,特别是对于 dense 材料阻挡光线穿过的情况( bottom 行)。你还会注意到,对于强前向散射(g>0),当朝向光源观察时,介质看起来更亮。实际上,强前向散射介质会将越来越多的光散射到其传播方向,而使其他区域更暗。这会在光源周围产生光晕,产生众所周知的辉光效果,例如在雾天看路灯时。介质越厚,光线穿透的能力就越弱。然而,在体积边缘附近的小光学厚度处,强前向散射光仍然能够通过,从而产生亮边视觉效果。

2.5 相关章节

本节中描述的参与介质材料和光相互作用是本文档中介绍的所有技术和结果的基础。这里介绍的概念将在以下部分中讨论:

  • 瑞利和米氏散射以及大气介质:第 3.2 节

  • 云相位函数:第 5.7 节

  • 积分改进:第 5.6 节

  • 多重散射近似:第 5.8 节

3 天空与大气

本节描述如何模拟和渲染天空和大气散射。在这一领域已经有很多非常详细的资源。因此,本节将比较简短,我们将尽可能引用外部文章和开源代码。

本节介绍的研究和开发是与以下团队共同努力的结果:

  • Ghost 工作室:Gustav Bodare 和 Edvard Sandberg(2015 年寒霜引擎 / DICE / 查尔姆斯理工大学硕士研究生 [BS])

  • Ghost 工作室(《极品飞车》)

  • DICE(《镜之边缘:催化剂》)

  • Bioware(《质量效应:仙女座》)

3.1 前期工作

渲染一个世界本质上需要渲染行星的天空和大气效果。在地球上,我们所说的蓝天是太阳光在大气参与介质中散射的结果。大气也是一个关键的视觉线索:它的颜色与一天中的时间(即太阳方向)有关,其雾状的视觉外观有助于感知距离和相对大小。因此,对于越来越多需要动态时间变化和大型开放世界可供探索、驾驶甚至飞行的游戏来说,能够准确渲染这些组件非常重要。Nishita 等人 [Nis+93] 提出的第一个基于物理的大气渲染模型专门用于从太空渲染地球。从那时起,人们提出了许多天空渲染方法来渲染从地面到太空的大气和天空。它们可以分为两类:

  • 解析模型 [PSS99][HW12][CIE95]

  • 迭代模型 [Ril+04][Wen07][ONe07][BN08][Ele09][HW12][Yus13a]

解析模型建立一组用于评估天空外观的参数。例如,[PSS99] 依赖于混浊度(衡量由 haze 引起的散射相对于分子(米氏 / 瑞利散射)引起的散射的比例)、天顶亮度,当然还有视图和太阳方向。然而,这些模型仅限于地面视图,或者大气参数不能自由更改以模拟地外行星,或达到特定的艺术驱动视觉效果。

许多模型可以使用天空的光谱渲染来提高准确性,但对于当今平台上的实时游戏,我们确实负担不起。在这种情况下,我们将仅限于可见光范围内通常的 3 个波长:红(λ=680 nm)、绿(λ=550 nm)和蓝(λ=440 nm)。

从现在开始,我们将重点关注依赖查找表(LUT)进行大气模拟和渲染的迭代大气模型。如果你想更详细地了解这些天空模拟模型如何实现,我们强烈建议你详细阅读 [BN08]、[Ele09] 和 [Yus13a]。他们的实现描述得很好、很详细,开源代码也可以在以下地址获得 [Bru17] 和 [Yus13b]。

迭代模型主要依靠光线步进来积分散射光。结果通常存储在查找表(LUT)中,以避免光线步进的高昂成本。然后可以利用图形卡的硬件过滤功能,高效地对这些纹理进行采样。例如,Bruneton 等人 [BN08] 生成以下 LUT:

  • 2D 透射率 LUT:由于地球的球对称性,仅通过视图高度和方位角索引。

  • 4D 散射 LUT:由于它依赖于高度、视图和光方向,因此基于这些值的自定义重映射进行索引,以避免地平线处的某些视觉伪影。

然后,可以使用 4D 散射 LUT 迭代多次散射阶数,从而预积分已经包含多重散射的 LUT [BN08]。这是这些方法的一个非常重要的特性,因为当太阳在地平线时,多重散射尤为重要,以避免过于饱和或过暗。

Elek 等人 [Ele09] 提议通过忽略视图方向和太阳方向之间的水平 / 方位角的函数的散射变化来降低 4D 散射 LUT 的维度。这种简化基本上从大气多重散射解决方案中去除了地球阴影。这导致了一个更简单的 3D LUT,在 GPU 上实时评估速度更快。此外,Yusov [Yus13a] 提出了一种改进的参数化方法,有助于在地平线处获得更多细节,并减少地平线处可能出现的一些视觉伪影。

3.2 天空和大气参与介质定义

为了能够渲染天空和大气,我们需要考虑几个组件。我们必须首先将大气视为围绕地球的恒定高度层,其中空气分子呈指数分布。

与远小于光波长的空气粒子相互作用的光会产生高度依赖波长的瑞利散射。考虑到地球大气,蓝光散射更多,这就是为什么白天天空呈现蓝色。然而,当太阳在地平线时,光线必须在大气中传播更长的距离,大多数蓝光会被散射掉。蓝光在大气中的传播距离不如绿光和红光远。这就是为什么日落和日出呈现红色。

大气的另一个重要组成部分是集中在地面附近的大粒子。这些粒子的浓度在很大程度上取决于天气条件,例如污染。这些粒子会引起与波长无关的米氏散射。因此,描述光如何散射的相位函数通常不是均匀的,而是偏向光的传播方向,即前向散射。这种现象会导致我们通常在太阳周围看到的明亮光晕。

3.3 大气成分

在本小节中,我们描述应该使用哪些系数和分布。经过与 [BN08] 讨论,我们了解到这些系数并不代表所有波长的散射系数,并根据人类感知与 RGB 可见光谱进行积分。相反,红、绿、蓝的散射系数仅取自相应的波长 680、550 和 440 纳米。

我们遵循 [Ril+04] 和 [BN08] 对大气的通常描述。在此基础上,我们还添加了臭氧的贡献,这对于日落和日出时天空的外观很重要。表 2 总结了所有系数及其在大气中的分布。

我们选择使用与 [Ril+04] 和 [BN08] 相同的瑞利散射系数,尽管方程 11 的评估给了我们不同的数值(5.47e⁻⁶、1.28e⁻⁵、3.12e⁻⁵,对于空气折射率 n=1.0003,每立方米分子数 N=2.545×10²⁵,标准空气 depolarisation 因子 pₙ=0.035 [PSS99])。米氏系数实际上取决于大气状态:清晰度、污染、灰尘、沙尘暴等。

类型散射(m⁻¹)消光(m⁻¹)分布
瑞利(分子)σₛᵣₐᵧ = (5.8e⁻⁶, 1.35e⁻⁵, 3.31e⁻⁵)σₛᵣₐᵧe^(-h/8.0km)
米氏(灰尘)σₛᵐⁱᵉ = 2e⁻⁶1.11σₛᵐⁱᵉe^(-h/1.2km)
臭氧0σₐᴼ³e^(-h/8.0km)

表 2:默认地球大气特性。

I¨ƒsRay=8π2(n21)23Nλ2A~—6+3pn67pnσ_{s}^{Ray }=\frac{8 \pi^{2}\left(n^{2}-1\right)^{2}}{3 N \lambda^{2}} × \frac{6+3 p_{n}}{6-7 p_{n}}

使用这些系数的结果如图 15 所示。你会注意到,增加瑞利散射会增加天空的蓝色,直到由于外散射导致光消光变得更重要,如参与介质示例第 2.4 节所示。增加米氏散射

image.png

图 15:左:轻度、类地球和重度瑞利散射。右:具有无、默认和重度米氏散射的默认类地球天空。

只会使大气看起来更浑浊,就像有严重污染或沙尘暴一样。

3.4 臭氧吸收

正如 Adams [CK74] 所报道的,考虑臭氧粒子吸收对于再现天顶天空的蓝色至关重要。Kutz 在他的硕士论文博客中展示了考虑臭氧带来的视觉改进 [Kut13]。不幸的是,吸收系数没有共享:我们在这里介绍我们如何恢复它们。我们使用方程 12 和 13 恢复 σₐᴼ³。我们首先使用方程 12 恢复单位体积的空气分子数(分子 /m³),其中 airConcentration=41.58 mol/m³ [Wikk] 是海平面的空气密度,Nₐ=6.022140857×10²³ 是阿伏伽德罗常数 [Wiki]。然后使用方程 13 从臭氧截面和空气密度评估吸收系数。臭氧截面取自 [Ser13] 的测量数据:该值是每个红、绿、蓝波长范围内所有测量温度的平均值。根据大气中臭氧的总体百分比 [Kut13],恢复的臭氧吸收最终值为 σₐᴼ³=(3.426,8.298,0.356)×0.06×10⁻⁵。

臭氧应该集中在天空中 32 公里处。但这给我们带来了意想不到的结果(可能是由于使用 RGB 而不是更完整的光谱)。相反,我们选择让臭氧遵循与瑞利散射粒子分布相同的大气分布,因此吸收系数可以简单地添加到用于散射模拟的瑞利消光系数中。

Nair=airConcentrationA~—NA(12)N_{air }= airConcentration × N_{A} \quad (12)

crossSectionO3B=1.3682089967147A~—1021(cm2/molecule)crossSectionO3B=3.31405330400124A~—1021crossSectionO3B=1.4221462736509A~—1021crossSectionO3G=crossSectionO3R/10000.0(m2/molecule)crossSectionO3B=crossSectionO3B/10000.0I¨ƒaO3R=NaircrossSectionO3R(1/m)I¨ƒaO3G=NaircrossSectionO3G(1/m)I¨ƒaO3B=NaircrossSectionO3B(13) \begin{array}{rlrl} crossSection ^{O_{3} B} & =1.3682089967147 × 10^{-21} & \left(cm^{2} / molecule \right) \\ crossSection ^{O_{3} B} & =3.31405330400124 × 10^{-21} & \\ crossSection ^{O_{3} B} & =1.4221462736509 × 10^{-21} & \\ crossSection ^{O_{3} G} & = crossSection ^{O_{3} R} / 10000.0 & \left(m^{2} / molecule \right) \\ crossSection ^{O_{3} B} & = crossSection ^{O_{3} B} / 10000.0 & \\ σ_{a}^{O_{3} R} & =N_{air } * crossSection ^{O_{3} R} & (1 / m) \\ σ_{a}^{O_{3} G} & =N_{air } * crossSection ^{O_{3} G} & (1 / m) \\ σ_{a}^{O_{3} B} & =N_{air } * crossSection ^{O_{3} B} & \end{array} \quad (13)

使用臭氧的结果如图 16 所示。没有臭氧时,天空整体可能显得过于黄色。将臭氧考虑到消光系数中(见第 2.1 节)可以在日落和日出时恢复更一致的蓝天颜色。

作为补充说明,我们尝试使用 [PSS99] 中与波长相关的臭氧吸收系数和 [WSS13] 中的光谱到 XYZ 函数。我们尝试了不同的变换和 sRGB 色域空间裁剪,但无法根据模拟距离恢复一致的吸收系数。这种方法被证明是不稳定的,我们希望得到任何反馈以及我们可能出错的原因 / 地方。恢复这些系数的尝试可以在 ShaderToy [Hila] 上公开获得。图 17 显示了 ShaderToy 呈现的多个图形:波长到 RGB 权重、每个波长范围的灰色臭氧吸收曲线,以及每个波长带基于距离的吸收和转换回 RGB 空间后的恢复 RGB 颜色。你会注意到有时会恢复负吸收系数,这是完全无效的。因此,欢迎提供帮助和 / 或建议。

image.png

Figure 16: Left: default sky. Right: default sky with added ozone absorption

image.png

图 17:光谱到 RGB 臭氧吸收 ShaderToy [Hila]

3.5 我们的方法

寒霜引擎中可用的基于物理的天空系统借鉴了许多研究成果:Bruneton [BN08]、Elek [Ele09] 和 Yusiv [Yus13a]。以下是一些选择:

我们使用 [Ele09] 中的 3D 查找表,而不是原始的 4D 查找表 [BN08]。这只意味着我们忽略了视图 / 太阳方位角:例如,我们不能在散射查找表中表示地球的阴影。我们发现对于我们到目前为止遇到的大多数用例,这是一个合理的假设。[Ele09] 的第 4.1.1 节中提供了所有假设的综合列表。

  • 如 Bruneton 等人 [BN08] 所述,散射 LUT 在 horizon 处可能存在精度问题,当视图接近地面时,在仰角为 0 时会导致视觉伪影。我们依赖于 Yusov [Yus13c] 提出的参数化改进。我们在附录 A 中给出了我们使用的参数化的简单非优化参考 hlsl 代码。

  • 在不透明表面上渲染空中透视时,每像素多次使用 LUT 评估散射亮度可能会根据你的预算而变得昂贵。为了降低成本,我们每帧在适合相机视锥体的低分辨率 3D 纹理(默认分辨率:32x32 带 16 个深度切片)中评估当前视图的散射亮度。这使得雾评估更便宜,并且具有易于评估并应用于所有透明网格以确保一致性的优点。在寒霜引擎中,我们在透明顶点上采样这个体积纹理。空中透视渲染如图 18 所示。

我们为艺术家提供了一种向他们的场景添加高度雾的方法 [Wen07]。为了使最终图像在一天中的不同时间看起来一致,我们根据在地平线处从 LUT 中获取的亮度为高度雾着色。这得益于使用 3D 散射 LUT 而不是上面提到的 4D LUT(在这种情况下,需要在整个地平线上采样值)。当将高度雾应用于场景时,会结合每像素评估的相位函数来考虑这种亮度 [Hil15]。这导致从相机附近的高度雾、地平线处到天空的无缝过渡,如图 18 所示。

一旦计算出 LUT,太阳就可以自由移动。但是,更改某些大气参数(如高度、散射或消光系数)将触发 LUT 更新,这成本太高。我们通过在多个帧上临时分摊查找表更新成本来解决这个问题(见第 3.5.1 节)。

3.5.1 性能

为了实现连贯和统一的光照和阴影,必须在多个视图中渲染基于物理的天空,例如主视图、平面反射、环境贴图。在本节中,我们给出 Xbox One 上的最新性能结果。

通道性能
720p 主视图0.42 ms
AP 体积 32x32x16(第 3.5 节)0.05 ms
一帧内的 LUT 更新3.50 ms
19 帧内的 LUT 更新每帧 0.22 ms

表 3:Xbox One 上基于物理的天空渲染性能。

图 3 中给出的性能是全屏天空的性能。当大气属性改变时,我们必须更新透射率和散射查找表。这可能需要多达 3.5 毫秒,因为还集成了多重散射。为了避免这种成本,我们在多个帧上分布 LUT 的评估,同时在最后两个有效结果之间进行线性插值 [BS]。这是使该技术能够用于 60 帧 / 秒游戏的关键点。它确实会增加一点延迟,但对于我们所有的用例来说,这被认为是可以接受的。

3.5.2 结果

动态天空的结果在本文档的整个部分以及体积云第 5 节中都可以看到。首批采用该技术的游戏是《极品飞车 2016》[Gho15] 和《镜之边缘:催化剂》[DIC16][Chr16]。

由于天空模拟将散射和消光系数作为输入,因此可以渲染任何地外行星。例如,火星被称为红色星球,因为它由于其生锈的地面而看起来像一颗红色的恒星。火星大气似乎也会散射更多的光谱中的红色和绿色成分。这就是为什么火星大气在白天呈现黄色或橙色 [NAS16]。一个直接的结果是,火星上的日落不是红色的,而是蓝色的,如美国宇航局在其网站 [NAS05] 上所示,如图 19 所示。我们未能找到火星大气散射特性,但图 20 显示了一系列使用寒霜引擎渲染的火星日落延时图像,并使用了一组凭经验设置的大气属性。

image.png

[图 18:天空、大气散射和高度雾。从上到下;左:仅太阳光,添加天空渲染,添加空中透视;右:逐渐添加更厚的高度雾。

image.png

![图 19:左:白天的火星视图 [NAS16]。右:日落时的火星视图 [NAS05]。

image.png ![图 20:寒霜引擎中火星大气日落模拟的延时摄影。

4 太阳、月亮和星星

渲染天空涉及渲染许多其他遥远的元素:

  • 太阳

  • 月亮

  • 星星

  • 天体

渲染这些元素时需要注意许多小细节。还需要知道它们的属性,如亮度或角直径 [Wika],以忠实地表示它们。

4.1 太阳

太阳是地球绕其运行的恒星。从海平面看,其角直径在一年中的不同时间在 32.7 到 31.6 角分之间 [NAS16],即根据其轨道位置。这对应于 0.527 度到 0.545 度的角直径。

4.1.1 太阳照度

据报道,地面的太阳照度 Eₛ(图 21)在 100000 到 120000 勒克斯之间 [Wikf]。

image.png

图 21:展示本节讨论的不同元素和量的示意图:地球、大气、透射率、太阳亮度和天顶及当前太阳位置的照度。

在寒霜引擎中,艺术家通过指定天顶处的太阳照度 Eₛᶻᵉⁿⁱᵗʰ 来创作太阳的贡献。这对他们来说更方便,因为更容易且更直观地与现实世界的值进行比较(见 [LR14] 第 4.6 节)。它也是在应用大气透射率后,为天顶处的太阳指定的。这使得艺术家更容易抽象出由大气中粒子的非平凡分布以及散射 / 吸收系数导致的地球透射率。

4.1.2 太阳亮度

在寒霜引擎中,光缓冲区存储亮度 L,而不是照度 E。因此,我们需要将艺术家给出的太阳照度 Eₛᶻᵉⁿⁱᵗʰ 转换为将应用于太阳圆盘的亮度 Lₛ。为了实现这一点,应用以下过程:

  1. 考虑太阳为完美圆盘,评估其立体角 ωₛ(假设在地球上恒定)

  2. 根据 ωₛ 和 Eₛᶻᵉⁿⁱᵗʰ 评估地面的太阳亮度 Lₛᶻᵉⁿⁱᵗʰ

  3. 考虑地球透射率和天顶处的太阳,评估太阳外层空间亮度 Lₛᵒᵘᵗᵉʳˢᵖᵃᶜᵉ

  4. 使用 Lₛᵒᵘᵗᵉʳˢᵖᵃᶜᵉ 渲染太阳,并对其应用大气透射率

对于孔径为 θ 弧度的圆锥体,立体角可以使用方程 14 评估。因此,可以恢复太阳的立体角 ωₛ(对于上述物理角直径,在 0.0000664sr 到 0.0000711sr 之间)。

2π(1cos(0.5A~—θ))(14)2 \pi(1-\cos (0.5 × \theta)) \quad (14)

对于太阳,艺术家给出的地面照度是针对天顶处的太阳,并且与它所对的立体角无关。如果我们认为太阳具有相对较小的立体角和相对均匀的亮度,我们可以使用方程 15 将其照度 Eₛᶻᵉⁿⁱᵗʰ 近似为其立体角上的积分。然后我们可以使用方程 16 简单地恢复太阳亮度 Lₛᶻᵉⁿⁱᵗʰ

Eszenith=ωsLszenithLszenithωsLszenith \begin{aligned} E_{s}^{zenith } & =\int_{\omega_{s}} L_{s}^{zenith } \\ L_{s}^{zenith } & \approx \omega_{s} L_{s}^{zenith } \end{aligned}

LszenithEszenithωs(16)L_{s}^{z e n i t h} \approx \frac{E_{s}^{z e n i t h}}{\omega_{s}} \quad (16)

对于给定的地球 / 大气设置,可以通过沿向上向量从地面积分消光直到所考虑的大气上边界,轻松计算天顶处的透射率 Trₐₜₘₒₛₚₕₑᵣₑᶻᵉⁿⁱᵗʰ。现在可以计算外层空间亮度为 Lₛᵒᵘᵗᵉʳˢᵖᵃᶜᵉ = Lₛᶻᵉⁿⁱᵗʰ / Trₐₜₘₒₛₚₕₑᵣₑᶻᵉⁿⁱᵗʰ。

我们在这里做出的合理假设是,大气透射率对于每个波长成分都不会达到 0。

有了太阳外层空间亮度,我们可以将太阳精灵渲染为完美圆盘,匹配其角直径,并将其亮度 Lₛᵒᵘᵗᵉʳˢᵖᵃᶜᵉ 贡献添加到光缓冲区。然而,如果只做到这一点,太阳看起来就像一个非常明亮的圆盘,因为忽略了大气透射率 Trₐₜₘₒₛₚₕₑᵣₑˢᵘⁿ。这可以通过使用第 3 节中描述的大气透射率查找表来解决。每像素采样后,我们简单地评估太阳的正确最终亮度为 Lₛ = Trₐₜₘₒₛₚₕₑᵣₑˢᵘⁿ × Lₛᵒᵘᵗᵉʳˢᵖᵃᶜₑ。这种最终正确且匹配的结果如图 22 所示。

完成此过程后,太阳将具有与天顶角以及大气属性匹配的正确外观。当太阳移动以模拟一天中的时间变化时,这一点尤为重要。在低曝光场景(如黄昏或黎明设置)中,太阳在可见时不会使画面过曝也很重要。此外,由于太阳亮度是从其照度和立体角恢复的,增大太阳会自动使其亮度变暗。这个过程自动确保整个视觉场景的照明与太阳的外观保持一致。

地球上太阳的数值示例:

image.png

[图 22:屏幕截图显示地平线处的太阳圆盘(黄昏设置),左图未应用大气透射率,右图每像素应用了大气透射率。

地面照度 Eₛᶻᵉⁿⁱᵗʰ = 120000 勒克斯

  • 0.545 度的角直径对应 0.0000711sr 的立体角

  • 亮度 Lₛᶻᵉⁿⁱᵗʰ = 1.69×10⁹ cd・m⁻²

  • 外层空间亮度 Lₛᵒᵘᵗᵉʳˢᵖᵃᶜᵉ = Lₛᶻᵉⁿⁱᵗʰ / Trₐₜₘₒₛₚₕₑᵣₑᶻᵉⁿⁱᵗʰ

使用第 3 节中的寒霜引擎默认基于物理的天空模拟,天顶处的透射率值可以在 0.925、0.861、0.755 之间,当太阳在地平线时,透射率值为 0.0499、0.004、4.10e⁻⁵。图 23 展示了根据太阳仰角的透射率的不同特性。

image.png

图 23:上:每个 RGB 通道的透射率曲线,对应可感知光波长。中:仰角为 90、45、20、10、5、0 度时的透射率颜色。下:根据最高波长通道缩放的透射率,以可视化透射率色调,即色相。

4.1.3 临边昏暗

太阳在天空中看起来像一个圆盘。但由于太阳是一个球体,圆盘的亮度并不均匀 [Wikh]。这是因为,对于给定的视角,沿法线观察表面(圆盘中心)比沿切线观察(圆盘边缘)会看到更多的光。实际上,在切线区域,光必须穿过更多的太阳气体,因此也会被更多地吸收。这种现象导致太阳圆盘的中心在视觉上比边缘更亮。天体物理学研究人员测量了太阳圆盘上发射光的亮度变化,并提出了一些模型 [Nec96]。

本文档中给出了 [Nec96] 和 [HM98] 模型的实现。HLSL 源代码实现见附录 B。[Nec96] 提出的模型产生的梯度如图 25 所示。可以将模型初始化为太阳系太阳,同时仍让艺术家能够创作临边昏暗效果。在实时环境中,你甚至可能希望将这些模型简化和优化为简单的梯度纹理采样。

image.png

图 24:屏幕截图显示地平线处的太阳圆盘(黄昏设置),(a)无临边昏暗,(b)具有匹配太阳系太阳的临边昏暗 [HM98],(c)通过更改参数获得更强的临边昏暗效果

image.png

图 25:[Nec96] 产生的太阳临边昏暗梯度,太阳圆盘中心在左,外边缘在右。

4.2 月亮

月亮是一颗绕地球运行的卫星,平均距离为 384000 公里。其角直径在一年中的不同时间在 29.3 到 34.1 角分之间 [Wikj]。这对应于 0.488 度到 0.568 度的角直径。

地面照度 Eₘₒₒₙ = 0.26 勒克斯 [Wikf]

  • 0.568 度的角直径对应 0.0000711sr 的立体角

  • 亮度 Lₘₒₒₙ = 3658 cd・m⁻²

由于 Eₘₒₒₙ 是地面照度(经过大气透射率后),Lₘₒₒₙ 可用于在乘以呈现其反照率的纹理后渲染月亮亮度。

一个需要渲染的棘手效果是使月亮和其他轨道物体相对于单个和 / 或多个太阳具有照亮和阴影的侧面。寒霜引擎目前不处理这种情况:艺术家负责设置。此外,有趣的是,必须记住月亮明暗界线错觉 [VSc]。

4.3 星星

星星是散布在宇宙中的发光体。其中最著名的是太阳。我们没有找到星星的平均立体角、照度或亮度数据。我们只能收集到以下数据:

[Jen+01a] 中报道了星星对地球照明的典型值(Eₛₜₐᵣₜₛ = 3e⁻² W/m²)

  • 星座、太阳系、一些星星和太空中其他物体的角直径在 [Wika] 中报道

Neyret 的一个 shader toy [Ney] 中也介绍了一种渲染星星的方法。它根据星星的温度渲染彩色星星。颜色是使用普朗克定律恢复的,该定律描述了每个温度下电磁辐射的光谱密度 [Wikl][Wikb]。

4.4 结果

图 26 展示了在寒霜引擎中黎明和夜间渲染太阳、月亮和星星精灵的结果。环境贴图和局部反射体积立方体贴图可以捕捉月亮、星星和其他太空和天体元素。这使得月亮和星星在反射中可见,增加了场景的真实感和整体连贯性。当这些立方体贴图被卷积时,这些元素将成为卷积的一部分,也会导致更一致的照明。

image.png

图 26:屏幕截图显示(左)黎明时分、(右)夜间的太阳圆盘(已放大)、月亮和星星的渲染,以及它们在反射中的存在。

5 云

本节介绍的研究和开发是与以下团队共同努力的结果:

  • Rurik Högfeldt(2015 年寒霜引擎硕士研究生 [Hög])

  • Bioware:Marc-Andre Loyer(程序员)、Soren Hesse(技术环境艺术师)和 Don Arceta(首席环境艺术师)

5.1 背景与前期工作

云是天空中非常复杂且富有表现力的视觉特征。从艺术角度来看,可以让它们看起来具有威胁性,代表即将到来的风暴,或史诗般的、不显眼的、稀薄的或巨大的等等。云通常移动缓慢,但对于具有动态天气变化的大型开放世界游戏,云需要是动态的。根据游戏设置和预算的复杂程度,可以使用不同的技术来实现这些外观。

当考虑使用单个全景纹理渲染天空和云的经典方法时,Guerette 提议使用一种众所周知的视觉流技术,以给天空中的云一种运动的错觉 [Gue14]。然后,云似乎会沿着例如全局风向设定的方向移动。这是一种非常有效的方法,但不涉及云形状、天气或照明的任何变化。

在飞行模拟器的情况下,Harris 提出将云渲染为粒子体积 [Har02]。通过并非一直渲染所有粒子,而是在远处使用代表粒子群的广告牌,该方法变得非常高效。这使得可以根据相机距离和相对位移以较低的速率更新广告牌。另一种基于粒子的云渲染方法是 Yusov [Yus14] 提出的。通过考虑太阳和天空的动态照明,使用每个粒子的预积分照明,可以渲染层积云状的云。使用称为光栅化器有序视图的新硬件功能实现的深度感知混合避免了简单的类粒子外观,见图 27。这两种基于粒子的方法在渲染云方面非常高效,但主要限于积云状的形状。

image.png

图 27:Yusov 等人 [Yus14] 获得的结果

image.png

图 28:Bouthors 等人 [Bou+08] 获得的结果

一些基于体积的云渲染技术也得到了研究 [Ril+04][Bou+08][Sch15]。例如,Bouthors 使用网格和光线步进超纹理的混合来渲染云 [Bou+08]。使用位于云形状表面的盘状光收集器收集最终的散射光。光线步进时实时积分光传输,并使用离线预计算的传输表加速。最终结果具有非常高的视觉质量,如图 28 所示,但也具有不可忽略的 GPU 成本。此外,网格和超纹理数据的组合对于艺术家来说理解、创建和编辑并不简单。

image.png

图 29:Schneider 等人 [Sch15] 获得的结果。

在实时游戏的背景下,《Reset》是第一款展示先进云渲染以及大气相互作用的游戏 [Ltd]。然而,关于该算法的细节公开披露的不多。Schneider 提出了一种视觉上类似的光线步进方法 [Sch15],允许渲染动态照明的体积云。通过几个参数,该方法允许渲染具有许多细节的复杂云形状,如图 29 所示。使用包含 Perlin-Worley 噪声的体积纹理被认为非常适合更好地表现积云状云的花椰菜状形状。生成的云是完全动态的,可以根据时间和天气约束演变。由于使用了散射光解决方案的时间积分,允许暂时积分最终的散射结果,因此该技术非常适用于实时游戏。

对于寒霜引擎,我们决定遵循 [Ltd] 和 [Sch15] 的路径,因为它们具有我们需要的以下优势:

  • 逼真的云形状

  • 可能实现大规模云

  • 动态的,因此天气可以变化

  • 支持动态体积照明和阴影

我们希望我们的实现符合寒霜引擎基于物理的框架:将材料信息与照明解耦,并保持能量守恒。这确保云在任何照明环境中都能适应,这在处理动态时间变化和天气时是必不可少的。

5.2 云参与介质材料

云由非常厚的参与介质组成。Hess 等人 [HKS98] 测量了水云,并报告了单层积云的散射反照率 ρ=1,以及消光系数 σₜ 在 [0.04,0.06] 范围内(对于层云),[0.05,0.12] 范围内(对于积云)(对于对应于可感知绿色的 550um 波长)。鉴于 ρ 非常接近 1,可以假设 σₛ=σₜ。

云的单次散射及其非常特定的相位函数(见第 5.7 节)是它们定义外观的重要部分。仅靠单次散射,由于云的厚度,云看起来只会像表面有散射光的脏 / 烟雾状元素。为了避免这种情况,必须考虑云外观的另一个定义组件:云内部发生的许多散射事件。第 5.7 节详细介绍了如何近似这一特性。

5.3 云创作

艺术家在世界中创作云和云分布的方式与 [Sch15] [Sch15] 中的非常相似,但具有一些我们的游戏和用例所需的额外控制。这种用于生成云形状的体积方法称为程序性方法,它使用算法从几个参数生成内容。使用算法生成艺术数据可能难以控制,并且也不总是与艺术家的愿景兼容。因此,定义一组有意义的输入参数,让艺术家实现他们的愿景是很重要的。本节解释了在寒霜引擎中向创作体积云的艺术家公开的控制。

作为一种程序性方法,人们很容易想到成千上万种生成参数和控制的方法,这些参数和控制将使用公式混合在一起以生成体积云。我们在这里介绍的方法符合我们的游戏和艺术家的需求。你需要找到最适合你的需求和游戏的方法。

5.3.1 云分布与密度

假设云保持在地球周围的单个恒定高度层内。它们由单一的参与介质材料组成,仅密度不同。艺术家创建一个天气纹理,该纹理在世界空间中具有大小和范围。如有必要,该纹理可以缩放并在整个世界中重复。图 30 中可见一个示例,每个通道代表:

image.png

图 30:云天气纹理示例。艺术家可以绘制云的世界空间分布及其类型

  • 红色通道:2D 投影云密度。

  • 绿色通道:2D 投影云类型索引。

云类型用于沿纹理空间的 x 轴索引另一个云类型纹理。Y 纹理空间轴是云层内的标准化高度。图 31 中可见一个这样的纹理示例,每个通道代表:

  • 红色通道:层高度内的云密度。

  • 绿色通道:应用的侵蚀量(小尺度噪声侵蚀大尺度噪声)。这直接映射到云表面的湍流程度。0 映射到平滑,1 映射到根据与 [Sch15] 类似的参数被 3D 侵蚀纹理完全侵蚀。

云类型纹理允许艺术家指定沿大气高度的云剖面。使用这样的纹理也给了艺术家很大的自由度。例如,他们可以表示多层云或砧状云(见第 5.11 节)。我们只是要求艺术家尽可能缩小这些纹理,以帮助减少纹理缓存未命中。这两种纹理都可以静态分配给一个关卡,必要时也可以动态更新。

image.png 在对云层进行光线步进时,我们根据天气纹理、类型纹理以及两个不同的体积噪声纹理评估云密度,方式类似于 [Sch15]。首先使用低频噪声 L 为云提供基本形状,并打破天气纹理的重复性,也称为基本形状。然后使用高频噪声 H 侵蚀该基本形状并在边缘添加细节。我们在接下来的第 5.4 节中介绍一种生成这些体积噪声纹理的方法。

5.4 云噪声

[Sch16] 中描述的云渲染算法建议使用特定设置的可平铺体积噪声纹理,但未给出源代码或纹理。我们在本节中描述纹理生成,并链接到可以访问源代码的开源存储库。

噪声 L 体积纹理是 Perlin-Worley 噪声和多个八度的 Perlin 噪声的组合生成的。噪声 H 纹理是多个八度的 Worley 噪声生成的。Worley 噪声在云渲染中非常有趣,因为它有助于表现云有时呈现的花椰菜状形状。

这些纹理可以表示为 4 分量 RGBA 纹理,通过着色器数学组合 [Sch16]。在寒霜引擎中,我们简单地使用表示最终单通道噪声的单分量体积纹理。这大大加快了云的渲染速度,因为减少了所需的内存带宽,同时仍能提供相同的最终视觉结果。

image.png

图 32:这些图像显示 4 个可平铺体积噪声切片:顶部,包含花椰菜状 Perlin-Worley 噪声形状的形状噪声;底部:由多个八度的 Perlin 噪声组成的侵蚀噪声。

我们提供了一个使用开源库生成此类噪声的小程序。请参考附录 D 了解描述和如何访问代码的更多细节。

5.4.1 云材料

云参与介质材料被描述为单一的参与介质材料。它由以下参数组成:

  • 第 2 节中描述的吸收 σₐ

  • 第 2 节中描述的散射 σₛ

  • 第 5.7 节中描述的双瓣相位函数

只有材料的密度在空间上变化。这种密度是使用上一小节中描述的程序性方法构建的。然而,为了使云看起来令人信服,噪声的选择至关重要。

5.5 云渲染

使用第 2 节中描述的材料和方程,我们积分图 33 中呈现的不同照明组件。

image.png

图 33:对云层进行光线步进时考虑的不同照明组件(从左上角到右下角):(1)背景透射率,(2)环境散射,(3)未遮蔽的太阳光散射,无(4)和有(5)前向散射相位函数的云自遮蔽太阳光散射。生成这些图像使用了 21 个样本。

5.5.1 环境光照

云的环境光照使用表示为球谐函数的全局光探针采样 [LR14]。为了性能起见,在评估环境光照时不考虑环境光照遮挡。考虑到我们当前的游戏预算,这并不实用,并且由于体积云的高度程序性,涉及复杂的噪声形状和侵蚀过程,预积分遮挡也会很棘手。我们只考虑寒霜引擎全局探针的第一个非定向项。因此,环境光照贡献产生的亮度往往会过于明亮。为了 counter 这种效果,我们给艺术家一种按 [0,1] 范围内的比例缩小环境组件的方法。如果不使用多重散射解决方案,考虑天空(即大气散射)可能会导致云略带蓝色。为了解决这个问题,我们还让艺术家能够降低环境光照产生的亮度的饱和度。

我们还使用从云层底部到顶部的 [0,1] 线性梯度对环境光照进行加权。这种方法假设天空是环境光照的唯一贡献者,而忽略了来自地球的反射光。这可以用两种不同的方法近似:

  • 将梯度范围偏置到 [0.2,1],以考虑环境光照的 a% 是由于地球地面的反射。

  • 从全局探针采样来自半球顶部和底部的环境贡献。如果全局探针在积分来自下半球 / 地球的亮度时考虑了一些整体色调,这是上述方法的改进版本。

本小节中介绍的环境贡献控制不是基于物理的,但允许我们的游戏团队达到他们的视觉目标。

5.5.2 太阳阴影采样

为了生成体积阴影,我们沿着视图向量对每个采样点向太阳进行光线步进。根据当前采样点的抖动位置,沿直线向太阳进行光线步进(参见下一节关于时间散射积分)。根据基本阴影采样距离,对阴影采样四次,每个采样的距离乘以一个常数因子。这是为了逐步采样远离源采样点。这种渐进式阴影采样方案与时间抖动一起产生平滑 / 软阴影估计。

5.5.3 时间散射积分

我们在单个通道中渲染云。每帧,样本在其采样步长 / 深度范围内随机偏移。一旦估计出当前帧的解决方案,就会根据恒定的混合因子将其与前一帧的解决方案混合。这导致使用指数移动平均实现散射解决方案的时间积分。为了使相机快速移动 / 旋转时最终帧看起来不模糊,我们根据先前和当前的相机属性(即投影和变换)重新投影先前的结果。

这种技术允许我们每帧使用少得多的样本,同时保持视觉质量。差异和改进如图 34 所示。

image.png

图 34:左:14 个云样本,无时间积分。右:相同视图和样本数量,有时间散射积分。

5.6 改进的散射

在实时积分参与介质中的散射光时,必须使用尽可能少的样本来提高效率。在这种情况下出现的一个问题是,单个样本将代表更大距离上的积分。距离越大,该样本的代表性就越差,从而降低积分的准确性。我们在这里描述不同的积分方法,并提出一种新的方法,该方法提供更高的质量并且也是能量守恒的。

5.6.1 常用散射积分

沿光线积分散射和透射率的常用且简单的方法如清单 5.6.1 所示。散射光初始化为 (0,0,0),透射率初始化为 1。每一步都采集材料样本和光样本,用于根据方程 1 更新散射光和透射率。

// 包含沿光线积分的散射亮度(rgb)和透射率(a)。
float4 intScattTrans = float4(0.0, 0.0, 0.0, 1.0);
for (uint samplerIt = 0; samplerIt < sampleCount; ++samplerIt)
{
    float4 scatteringExtinction = takeMediaSample(coord);
    const float3 scattering = scatteringExtinction.rgb;
    const float transmittance = exp(-scatteringExtinction.a * ds);
    
    // 根据体积阴影和相位函数获取太阳亮度
    const float3 luminance = sunLuminance(coord, sunDir, viewDir);
    
    intScattTrans.rgb += scattering * luminance * intScattTrans.a * ds; // (S)步骤
    intScattTrans.a *= transmittance; // (T)步骤
}

清单 1:展示沿光线积分散射光和透射率的方法的简化代码。

这种公式有一个问题:inScattTrans.rgb 使用 inScattTrans.a(S)更新,然后 inScattTrans.a(T)更新。但这步骤的顺序正确吗?事实上,如图 35 所示,两种顺序都不正确。如果先执行(S)再执行(T),那么散射将在不考虑采样范围 ds 上的透射率的情况下添加,导致积分不守恒能量。如果先执行(T)再执行(S),那么由于散射光将使用整个 ds 范围过度遮挡,导致参与介质看起来过亮。

image.png

图 35:积分散射光时的问题,左:先执行(S)再执行(T)(不守恒能量),中:先执行(T)再执行(S)(能量吸收过多),右:多次采样的参考积分,显示预期结果。

总体而言,对于非密集材料,图 35 中呈现的误差将非常小。例如,像这里呈现的这种简单积分适用于轻雾。然而,当 σₛ 变高时,对于非常密集的材料,它将开始失效。

5.6.2 更好的数值积分

为了使用少量样本更好地近似曲线的定积分,可以使用不同的数值方法,如梯形法 [Wikn] 或辛普森法则 [Wikm]。在本节中,我们将以梯形法则为例。

梯形法则描述了如何使用少量样本和梯形表面积方程近似曲线积分。在图 36 的左图中,让我们将透射率视为绿色曲线,散射光亮度为 1。通过清单 5.6.1 中呈现的代码(先执行(T)再执行(S))评估的透射率(例如 ∑(tₓ/(dₓ₊₁-dₓ)))将导致过多的吸收:红色方块的 Y 轴顶部始终在我们要积分的绿色曲线下方。然而,先执行(S)再执行(T)(例如 ∑(tₓ₊₁/(dₓ₊₁-dₓ)))将导致非守恒能量的积分,因为红色方块的 Y 轴顶部始终在绿色曲线上方。

image.png

图 36:左:不同的积分解决方案,右:线性函数和 exp(-x) 函数之间的差异。

使用梯形曲线将允许使用分段线性顶部在每个区间 [dₓ, dₓ₊₁] 上积分 [Wikn]。梯形积分表示图 36 中橙色曲线的积分。你可以看到橙色曲线更接近我们要积分的绿色参考曲线。然而,我们仍然可以注意到积分不会守恒能量:如图 36 的右图所示,橙色曲线仍然始终在绿色参考曲线上方。因此,参与介质材料仍将散射比应有的更多的光,并且对于高 σₛ 值,差异会更大,即在本例中绿色曲线会更快地收敛到 0,而橙色曲线则不会。

5.6.3 守恒能量的解析积分

为了解决这个问题,我们建议根据消光 σₜ 和散射光样本 S=Lscat (xₜ, ωᵢ) 以及积分深度 d 解析地积分一定范围内的散射光。如果我们考虑为散射光样本采集单个样本,我们只需要根据到范围前端深度的透射率在曲线上的每个点积分它。这是使用方程 17 实现的 [Hil15]。

x=0dexpσtx×S dx=SSexpσtdσt \int_{x=0}^{d} \exp ^{-\sigma_{t} x} \times S \mathrm{~d} x=\frac{S-S \exp ^{-\sigma_{t} d}}{\sigma_{t}}

使用方程 17 很简单:每个平板只需要采集单个 σₜ 和 S。如清单 5.6.3 所示,可以使用上述方程评估积分的散射光,同时应用和更新先前积分的透射率。这将导致在考虑的深度范围 d 上守恒能量的散射。你可能已经注意到,当消光 σₜ=0 时,方程 17 的结果未定义。我们只需将消光钳位到一个小的 ε 即可解决这个问题。

// 包含沿光线积分的散射亮度(rgb)和透射率(a)。
float4 intScattTrans = float4(0.0, 0.0, 0.0, 1.0);
for (uint samplerIt = 0; samplerIt < sampleCount; ++samplerIt)
{
    float4 scatteringExtinction = takeMediaSample(coord);
    const float3 scattering = scatteringExtinction.rgb;
    const float extinction = scatteringExtinction.a;
    const float clampedExtinction = max(extinction, 0.0000001);
    const float transmittance = exp(-scatteringExtinction.a * ds);
    
    // 根据体积阴影和相位函数获取太阳亮度
    const float3 luminance = sunLuminance(coord, sunDir, viewDir);
    
    const float3 integScatt = (luminance - luminance * transmittance) / clampedExtinction;
    intScattTrans.rgb += intScattTrans.a * integScatt;
    intScattTrans.a *= transmittance;
}

清单 2:改进的解析散射积分伪代码。

使用这种积分改进,当增加材料密度时,可以使用不太多的样本使参与介质看起来正确。图 37 - 左显示,使用第 5.6.1 节中呈现的采样,需要采集 512 个样本才能使结果收敛到与材料匹配的正确结果(与图 35 中呈现的错误的 21 个样本图片相比)。然而,在右图中,当使用散射积分方程时,只需要 21 个样本即可达到预期结果。如你所料,使用 512 个样本的图像将更准确地表示云的形状,但至少现在光照结果在更大程度上与样本数量无关。

image.png

图 37:左:不使用方程 17 渲染云:需要 512 个样本才能收敛,右:使用方程 17 改进的积分,显示只需要 21 个样本即可收敛到正确/可接受的视觉结果。

在这种特定情况下,这种解析积分比梯形积分更正确。在基于物理的 HDR 光照和渲染中,当场景中的对比度和亮度差异可能非常大时,这一点尤为重要。有关这种改进的散射积分公式的更多详细信息,请参考附录 C。

5.7 云相位函数

在第 2.3 节中,我们将相位函数描述为一种数学工具,表示光散射时的反射方向分布。这是参与介质的一个重要属性,

因为它定义了一些非常重要的视觉特征:从云上前向散射产生的强烈亮边到导致彩色雾虹的细微的波长相关几何散射。

image.png

图 38:使用 MiePlot [Lav15] 生成的云相位函数示例(也在 [Bou+08] 中讨论)。这显示了单个光波长的散射,所有偏振光在对数尺度上平均。

如 [Bou+08] 中所呈现的,云相位函数可能非常复杂。云由相对较大的水滴组成,可以具有几何散射(见第 2.3 节)。这种云相位函数的示例如图 38 所示。你可以注意到右侧强烈的前向散射峰值,或者在 120 度左右的复杂雾虹视觉效果 [Wikc]。其他云视觉特征是伪镜面反射和光环 [Wikd]。

image.png

图 39:太阳在相机后面时的云渲染,左:单瓣 Phg,右:双瓣 Pdual 相位函数。顶部图像显示对应的 2D 相位函数形状,假设前向朝右。

在视频游戏等实时环境中,我们没有评估这种复杂相位函数形状的条件。因此,通常评估单个相位函数(例如 Henyey-Greenstein 相位函数)。但是,当表示具有强烈前向散射的材料(如云)时,从与太阳方向相反的方向观察云时,后向散射分量可能会缺失,并且看起来暗淡且缺乏细节,如图 39 左图所示。实际上,对于强烈的前向峰值,当太阳在相机后面时观察云,只有环境光照会保留。为了解决这个问题,我们使用由两个 Henyey-Greenstein 相位函数根据权重 w∈[0,1] 混合组成的双瓣相位函数 Pdual,如方程 18 所示。

pdual (θ,g0,g1,w)=lerp(phg(θ,g0),phg(θ,g1),w)p_{\text {dual }}\left(\theta, g_{0}, g_{1}, w\right)=\operatorname{lerp}\left(p_{h g}\left(\theta, g_{0}\right), p_{h g}\left(\theta, g_{1}\right), w\right)

使用双瓣相位函数给了艺术家更多控制光在云参与介质中反射方式的能力。现在可以更好地平衡前向和后向散射。图 39 右图显示,通过使用双瓣相位函数,在允许强烈前向散射峰值的同时,还保持一定量的后向散射以从云形状中呈现更多细节,可以获得更多细节。

5.8 多重散射

云散射光很多,它们明亮和白色外观的很大一部分是多重散射的结果。没有多重散射,云在边缘主要会被太阳和环境光照亮,而在其他任何地方都会非常暗。多重散射也是云看起来不像烟雾的关键因素。由于空气中悬浮着大量的水,蓬松的云看起来可以非常白和明亮,即使在被非常强烈的蓝色环境天光散射照明时也是如此。如本节开头所述,云的反照率非常接近 1。

可以使用不同的方法评估多重散射解决方案:

  • 路径追踪(递归):对于实时游戏用例,这在很大程度上超出了预算。

  • 预计算:这类似于 [Bou+08] 提出的基于收集器的方法。然而,对于程序性内容,预计算可能很困难。

  • 迭代:类似于 [Ele+14],可以在体积中传播多重散射光。尽管是自动的,但由于所需的内存量,我们很可能仍然会超出预算。

最后,我们决定使用 Wrenninge 等人 [WKL13] 提出的非常简单的多重散射近似。该方法基本上积分多个散射八度并将它们相加。

因此,基本上,最终积分的散射为:

Lmultiscat(x,ωi)=0(N1)Lscat(x,ωi)Lmultiscat\left(x, \omega_{i}\right)=\sum_{0}^{(N-1)} Lscat\left(x, \omega_{i}\right)

其中进行了以下替换:

σs=σsA~—anσe=σeA~—bnp(θ)=p(θA~—cn) \begin{aligned} \sigma_{s}^{\prime} & =\sigma_{s} × a^{n} \\ \sigma_{e}^{\prime} & =\sigma_{e} × b^{n} \\ p^{\prime}(\theta) & =p\left(\theta × c^{n}\right) \end{aligned}

为了确保在评估 Lmultiscat (x, ωᵢ) 时该技术守恒能量,必须确保 a<=b。否则,可能会散射比预期更多的光,因为方程 σₜ=σₐ+σₛ 将不再成立,因为 σₛ 可能最终大于 σₜ。

这种解决方案的优点是,可以在光线步进时一次积分不同八度的散射光。缺点是它不能很好地表示复杂的多重散射行为:例如侧面或后向散射、无锥展等。尽管有这些缺点,该技术在实践中效果很好,并为艺术家提供了对体积云外观的精细控制。现在,他们可以生成高散射(即厚)参与介质,同时仍然确保散射光能够穿透介质,以在阴影侧面显示内部细节 40。

image.png

图 40:积云(左)和积雨云(右)的示例,使用单次散射 N=1(上)和多重散射 N=2(中)以及 N-3(下,具有夸张的多重散射)渲染。

5.9 其他相互作用

寒霜引擎体积云阴影完全是引擎的一部分。预计云将因此与场景的每个元素一致地相互作用。这是为了使一切看起来一致,无论行星、时间和天气如何。

在评估阴影或大气散射时会考虑云,这使得许多全局效果能够发生:

  • 阴影:体积云阴影被烘焙到存储透射率的 2D 纹理中,并投影到世界上。它应用于所有不透明、透明表面,并且还被我们的发射器系统采样以正确照亮粒子。投影非常简单,假设围绕相机的整体平坦行星,这对于典型行星来说是合理的假设。

  • 全局光照:更新动态全局光照系统的输入时也会采样体积云阴影图(使用 Enlighten 实现 [Geo17])。这导致动态全局光照受到云、天气和太阳方向的影响。

  • 云对空中透视的影响:在第 5.9.2 小节中描述。

  • 空中透视对云的影响:在第 5.9.1 小节中描述。

5.9.1 空中透视对云的影响

云通常在大气中很高,离相机很远。因此,它们的外观会受到空中透视的影响,即在云粒子和视点之间发生大气光散射。图 41 - 左显示,如果在不考虑空中透视的情况下渲染云,云与地球之间的地平线处会出现视觉差异。中间图像显示相同的场景,但云应用了空中透视。地平线处的问题不再可见。

 Depth cloud =n=0NTr(xn)Depth(xn)n=0NTr(xn) \text { Depth }_{\text {cloud }}=\frac{\sum_{n=0}^{N} \operatorname{Tr}\left(x_{n}\right) * \operatorname{Depth}\left(x_{n}\right)}{\sum_{n=0}^{N} \operatorname{Tr}\left(x_{n}\right)}

image.png

图 41:云与空中透视的重要相互作用。左:厚云层简单地合成在明亮的白天天空上,中:云应用了空中透视,右:云层覆盖影响空中透视的正确结果。

一种直接的将空中透视应用于云的方法是在对云层进行光线步进期间在积分散射光和透射率时对其进行采样。然而,所有这些额外的纹理采样将使云通道更加昂贵。相反,我们建议分两步实现该目标:

  • 使用方程 21 计算由到视点的透射率加权的云平均前端深度。这允许在考虑每个样本的可见性的同时评估平滑的前端深度,并忽略被遮挡样本的深度。如果没有云粒子被击中,我们只需跳过样本,当透射率为 1 时。这导致平滑的深度缓冲区,如图 42 所示。

  • 仅评估一次空中透视散射 / 透射率纹理,并将其应用于最终积分的云散射亮度和透射率。

5.9.2 云对空中透视的影响

覆盖天空的云将由于它们的覆盖范围和它们散射的光而影响空中透视的外观。在云层下方:

  • 厚云层将阻挡天空光在大气中散射。

image.png

图 42:云样本深度的加权平均值。该深度用于采样应用于云的空中透视散射和透射率作为后处理。

  • 由高反照率产生的明亮云将在大气中传播更多的光。参与介质和密度系数将影响散射光的量和颜色。

LAP=LAPA~—Trcloud +Lcloud (22)L_{A P}=L_{A P} × T r_{\text {cloud }}+L_{\text {cloud }} \quad (22)

如 [Hil16] 中所呈现的,见图 43,我们在地面级从相机视角在半球上采样云平均透射率 Trcloud 和积分散射亮度 Lcloud。这是通过简单地在黑色背景上渲染云并存储每像素散射亮度和透射率来实现的。

image.png

图 43:说明云散射亮度和透射率积分的示意图。

然后使用方程 22 将该结果用于影响第 3.5 节中呈现的空中透视纹理。我们只需根据云层平均透射率衰减空中透视散射太阳亮度,同时添加云积分散射亮度贡献。

改进如图 41 所示,其中中间图像的空中透视不受云层影响,而右图的空中透视受云层影响。你可以注意到大气中存在的散射少得多,并且还可以看到来自深色不透明云层的深蓝色散射颜色。

5.10 性能

为了实现连贯的视觉效果、统一的照明和阴影,必须在多个视图中渲染云:主视图、平面反射、环境贴图或阴影。在本节中,我们给出 Xbox One 上的最新性能结果。

视图性能
720p 主视图0.91 ms
720p 平面反射0.14 ms
1080p 主视图1.60 ms
1080p 平面反射0.20 ms

表 4:Xbox One 上的云渲染性能。

图 4 中给出的性能是针对最坏情况的,即看向地平线,3/5 的屏幕被云覆盖,每个通道 16 个样本。主云视图以一半分辨率渲染,平面反射以四分之一分辨率渲染。此性能也是在启用多重散射且 N=2 时给出的(见第 5.8 节)。

5.11 结果

image.png

图 44:Valentin de Bruyn 的插图 [Wike]。

除了前几节中显示的结果外,我们在这里还呈现了一些在尝试匹配不同云类型后获得的额外视觉效果。实际上,如图 44 所示,云确实可以有各种各样的形状、密度、高度等。非常感谢 Soren Hesse 在这里分享他的一些作品。

image.png

图 45:高层云。

image.png

图 46:积云。

image.png

图 47:一些在黄昏时分预示着大雨的巨大而厚的积云。

image.png

图 48:黄昏时分的许多层积云。

image.png

图 49:大而密的积雨云。

image.png

图 50:远处巨大而高的积雨云砧云向我们袭来。暴风雨即将来临!

《极品飞车:复仇》[Gho17] 将是第一款采用体积云渲染技术的电子艺界游戏。结果如图 51 所示。

image.png

图 51:《极品飞车:复仇》官方屏幕截图,展示了寒霜引擎基于物理的体积云。

6 结论

我们介绍了渲染基于物理的天空、大气、天体和云的技术。我们详细介绍了寒霜引擎中被许多 EA 游戏在制作中使用的特定实现。本文档中介绍的技术也已在许多近期的电子艺界游戏中使用,如图 52 所示。云渲染技术是唯一尚未发布但已在《极品飞车:复仇》[Gho17] 和《圣歌》[Bio17] 游戏的制作中使用的技术。

image.png

图 52:近期的电子艺界/寒霜引擎游戏已采用本文档中介绍的技术。左上至右下:《极品飞车:复仇》[Gho17]、《镜之边缘:催化剂》[DIC16]、《质量效应:仙女座》[BIO17] 和《FIFA 17》[Art16]。

在所有这些游戏的开发过程中遇到的主要挑战是在强约束下保持高视觉质量。这些约束推动了我们必须做出并在本文档中介绍的许多技术选择。首先是性能:《镜之边缘》和《FIFA》都是运行在 60 帧 / 秒的游戏,因此需要最小的 GPU 成本。其次是许多系统之间的相互作用:更改云参数进而影响大气散射、全局光照等,从实现和视觉连贯性的角度来看也具有挑战性。最后,所有这些系统都必须设计用于艺术家的实时预览,同时时间(如一天中的时间或天气)实时变化时具有最小的更新延迟以保持视觉连贯性。

我们希望本文档会有所帮助:(1)初学者已经发现参与介质部分足够完整和详细,足以理解体积渲染背后的所有基本概念,无论你是艺术家还是程序员,(2)本文档的其余部分将帮助你实现和 / 或改进你的天空、云和天体渲染系统。如果你想了解有关所呈现的一些讨论、方程或技术的更多细节,或者如果你发现任何问题或错别字:请随时联系我们:sebastien.hillaire@frostbite.comtwitter.com/SebHillaire

6.1 未来工作

我们在这里给出可以研究以改进本文档中介绍的技术的想法和研究领域:

  • 来自云的空中透视太阳体积阴影。先前的论文中已经提出了解决方案 [BN08][Yus13a],但它们仅针对不透明几何体的体积阴影。我们需要一种解决方案,该方案还将考虑不透明以及参与介质,例如云或局部雾体积 [Hil15]。也许使用相机包裹的体素体积或映射到视锥体的特殊阴影投影。

  • 云在所有物体后面的一层中渲染。如果有人希望云与不透明几何体(如大山)相交,则需要仅光线步进到最近的深度。由于云以较低的分辨率渲染,因此需要额外的合成步骤:下采样深度和从低分辨率到全分辨率的双边上采样。

  • 云环境目前是单一颜色,没有方向性也没有遮挡。可以通过使用寒霜引擎球谐探针主入射光方向来提高质量,或者可以根据云中每帧的不同方向暂时积分单个环境遮挡。也可以考虑来自地形的反射颜色。

  • 实现 Bruneton 的模型(4D 多重散射 LUT)或找到一种廉价的方法来近似地球对大气的遮挡将是一个有趣的选项。在某些情况下,我们发现有这样的视觉选项会很有趣。

参考文献

[Art16] E. Arts. FIFA 2017. 2016. url: www.easports.com/fifa.

[BIO17] BIOWARE. Mass Effect Andromeda. 2017. url: www.masseffect.com/.

[Bio17] Bioware. Anthem. 2017. url: www.ea.com/games/anthe….

[BN08] E. Bruneton and F. Neyret. “Precomputed Atmospheric Scattering”. In: Proceedings of the Nineteenth Eurographics Conference on Rendering. EGSR ’08. Sarajevo, Bosnia and Herzegovina: Eurographics Association, 2008, pp. 1079–1086. doi: 10.1111/j.14678659.2008.01245.x. url: dx.doi.org/10.1111/j.1….

[Bou+08] A. Bouthors, F. Neyret, N. Max, E. Bruneton, and C. Crassin. “Interactive Multiple Anisotropic Scattering in Clouds”. In: Proceedings of the 2008 Symposium on Interactive 3D Graphics and Games. I3D ’08. Redwood City, California: ACM, 2008, pp. 173–182. isbn: 978-1-59593-983-8. doi: 10.1145/1342250.1342277. url: doi.acm.org/10.1145/134….

[Bru17] E. Bruneton. Precomputed Atmospheric Scattering. 2017. url: github.com/ebruneton/p….

[BS] G. Bodare and E. Sandberg. Efficient and Dynamic Atmospheric Scattering. url: publications.lib.chalmers.se/records/ful….

[Chr16] F. Christin. “Lighting the City of Glass”. In: Game Developers Conference. 2016. url: www.gdcvault.com/play/102328….

[CIE95] CIE. “Spatial distribution of daylight-luminance distributions of various reference skies”. In: Color Research and Application 20.1 (1995), pp. 80–81. issn: 1520-6378. doi: 10.1002/col.5080200119. url: dx.doi.org/10.1002/col….

[CK74] G. P. Charles Adams and G. Kattawar. “The influence of Ozone and Aerosol on the Brightness and Color of the twilight Sky”. In: Journal of the Atmospheric Sciences 31 (1974), pp. 1662–1674. url: journals.ametsoc.org/doi/pdf/10.….

[dEo16] E. d’Eon. A HitchHicker’s Guide to Multiple Scattering. 2016. url: www.eugenedeon.com/project/a-h….

[DIC13] DICE. Battlefield4. 2013. url: www.battlefield.com/games/battl….

[DIC15] DICE. Star Wars Battlefront. 2015. url: starwars.ea.com/starwars/ba….

[DIC16] DICE. Mirror’s Edge catalyst. 2016. url: www.mirrorsedge.com/.

[DL07] E. D’Eon and D. Luebke. Advanced techniques for realistic real-time skin rendering. Addison Wesley, 2007. url: http.developer.nvidia.com/GPUGems3/gp….

[Ele+14] O. Elek, T. Ritschel, C. Dachsbacher, and H.-P. Seidel. “Principal-Ordinates Propagation for Real-Time Rendering of Participating Media”. In: Computers & Graphics 45 (2014). doi: 10.1016/j.cag.2014.08.003.

[Ele09] O. Elek. “Rendering Parametrizable Planetary Atmospheres with Multiple Scattering in Real-time”. In: CESCG (2009). url: www.cescg.org/CESCG-2009/….

[Geo17] Geomerics. Enlighten. 2017. url: www.geomerics.com/enlighten/.

[Gho15] Ghost. Need for Speed. 2015. url: www.needforspeed.com.

[Gho17] Ghost. Need for Speed Payback. 2017. url: www.ea.com/games/need-….

[Gue14] K. Guerrette. “Moving the heavens”. In: Game Developers Conference. 2014. url: www.gdcvault.com/play/102014….

[Har02] M. J. Harris. “Real-Time Cloud Rendering for Games”. In: Game Developers Conference. 2002. url: www.markmark.net/PDFs/RTClou….

[Hila] S. Hillaire. O3 Spectrum to RGB absorption. url: www.shadertoy.com/view/ldySWV.

[Hilb] S. Hillaire. Volumetric Stanford Bunny. url: www.shadertoy.com/view/MdlyDs.

[Hilc] S. Hillaire. VolumetricIntegration. url: www.shadertoy.com/view/XlBSRz.

[Hil15] S. Hillaire. “Physically Based and Unified Volumetric Rendering in Frostbite”. In: Advances in Real Time Rendering, Part I, ACM SIGGRAPH 2015 Courses. SIGGRAPH ’15. Los Angeles, California: ACM, 2015. isbn: 978-1-4503-3634-5. doi: 10.1145/2776880.2787701. url: advances.realtimerendering.com/s2015/.

[Hil16] S. Hillaire. “Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite”. In: SIGGRAPH 2016 Course: Physically Based Shading in Theory and Practice, ACM SIGGRAPH 2016 Courses. SIGGRAPH ’16. Los Angeles, California: ACM, 2016. url: blog.selfshadow.com/publication….

[HKS98] M. Hess, P. Koepke, and I. Schult. “Optical Properties of Aerosols and Clouds: The Software Package OPAC”. In: Bulletin of the American Meteorological Society 79.5 (1998), pp. 831–844. doi: 10.1175/1520-0477(1998)079<0831:OPOAAC>2.0.CO;2. eprint: dx.doi.org/10.1175/152…. url: dx.doi.org/10.1175/152….

[HM98] D. Hestroffer and C. Magna. “Wavelength dependency of the Solar limb darkening”. In: Astronomy Astrophysics 333.1 (1998), pp. 338–342. url: www.researchgate.net/publication….

[Hög] R. Högfeldt. Convincing Cloud Rendering: An Implementation of Real-Time Dynamic Volumetric Clouds in Frostbite. url: publications.lib.chalmers.se/records/ful….

[Hul57] H. C. V. de Hulst. Light Scattering by Small Particles. Reprint, edition (December 1, 1981). Dover Publications, 1957. isbn: 978-0486642284.

[HW12] L. Hosek and A. Wilkie. “An Analytic Model for Full Spectral Sky-dome Radiance”. In: ACM Trans. Graph. 31.4 (July 2012), 95:1–95:9. issn: 0730-0301. doi: 10.1145/2185520.2185591. url: doi.acm.org/10.1145/218….

[Jar08] W. Jarosz. “Efficient Monte Carlo Methods for Light Transport in Scattering Media”. PhD thesis. UC San Diego, Sept. 2008. url: www.cs.dartmouth.edu/~wjarosz/pu….

[JB10] J. Jansen and L. Bavoil. “Fourier Opacity Mapping”. In: Proceedings of the 2010 ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games. I3D ’10. Washington, D.C.: ACM, 2010, pp. 165–172. isbn: 978-1-60558-939-8. doi: 10.1145/1730804.1730831. url: doi.acm.org/10.1145/173….

[Jen+01a] H. W. Jensen, F. Durand, J. Dorsey, M. M. Stark, P. Shirley, and S. Premože. “A Physically-based Night Sky Model”. In: Proceedings of the 28th Annual Conference on Computer Graphics and Interactive Techniques. SIGGRAPH ’01. New York, NY, USA: ACM, 2001, pp. 399–408. isbn: 1-58113-374-X. doi: 10.1145/383259.383306. url: doi.acm.org/10.1145/383….

[Jen+01b] H. W. Jensen, S. R. Marschner, M. Levoy, and P. Hanrahan. “A Practical Model for Subsurface Light Transport”. In: Proceedings of the 28th Annual Conference on Computer Graphics and Interactive Techniques. SIGGRAPH ’01. New York, NY, USA: ACM, 2001, pp. 511–518. isbn: 1-58113-374-X. doi: 10.1145/383259.383319. url: graphics.ucsd.edu/~henrik/pap….

[Kut13] P. Kutz. The Importance of Ozone. 2013. url: skyrenderer.blogspot.se/2013/05/the….

[Lav15] P. Laven. MiePlot. 2015. url: www.philiplaven.com/mieplot.htm.

[LR14] S. Lagarde and C. de Rousiers. “Moving Frostbite to PBR”. In: Physically Based Shading in Theory and Practice, ACM SIGGRAPH 2014 Courses. SIGGRAPH ’14. Vancouver, Canada: ACM, 2014, 23:1–23:8. isbn: 978-1-4503-2962-0. doi: 10.1145/2614028.2615431. url: www.frostbite.com/2014/11/mov….

[Ltd] T. I. Ltd. Reset blog. url: reset-game.net/?p=284.

[MH16] S. McAuley and S. Hill. “Physically Based Shading in Theory and Practice”. In: ACM SIGGRAPH 2016 Courses. SIGGRAPH ’16. Anaheim, California: ACM, 2016. isbn: 9781-4503-4289-6. doi: 10.1145/2897826.2927353. url: doi.acm.org/10.1145/289….

[Mie08] G. Mie. “Beiträge zur optik trüber medien, speziell kolloidaler metallösungen”. In: Annalen der Physik. 1908, pp. 377–445. url: www.dca.iag.usp.br/www/materia….

[NAS05] NASA. Sunset on Mars. 2005. url: www.nasa.gov/multimedia/….

[NAS16] NASA. Rover Opportunity Wrapping up Study of Martian Valley. 2016. url: www.nasa.gov/feature/jpl….

[Nec96] H. Neckel. “On the wavelength dependency of solar limb darkening (λλ303 to 1099 nm)”. In: Solar Physics 167.1 (1996), pp. 9–23. issn: 1573-093X. doi: 10.1007/BF00146325. url: dx.doi.org/10.1007/BF0….

[Ney] F. Neyret. Realistic display of star in Hubble images. url: www.shadertoy.com/view/XdsGWs.

[Nis+93] T. Nishita, T. Sirai, K. Tadamura, and E. Nakamae. “Display of the Earth Taking into Account Atmospheric Scattering”. In: Proceedings of the 20th Annual Conference on Computer Graphics and Interactive Techniques. SIGGRAPH ’93. Anaheim, CA: ACM, 1993, pp. 175–182. isbn: 0-89791-601-8. doi: 10.1145/166117.166140. url: doi.acm.org/10.1145/166….

[ONe07] S. O’Neil. Accurate Atmospheric Scattering. Addison Wesley, 2007. url: http.developer.nvidia.com/GPUGems2/gp….

[PH10] M. Pharr and G. Humphreys. Physically Based Rendering, Second Edition: From Theory To Implementation. 2nd. San Francisco, CA, USA: Morgan Kaufmann Publishers Inc., 2010. isbn: 0123750792, 9780123750792. url: www.pbrt.org/.

[PSS99] A. J. Preetham, P. Shirley, and B. Smits. “A Practical Analytic Model for Daylight”. In: Proceedings of the 26th Annual Conference on Computer Graphics and Interactive Techniques. SIGGRAPH ’99. New York, NY, USA: ACM Press/Addison-Wesley Publishing Co., 1999, pp. 91–100. isbn: 0-201-48560-5. doi: 10.1145/311535.311545. url: dx.doi.org/10.1145/311….

[Ray71] J. W. S. L. Rayleigh. “On the scattering of light by small particles”. In: Philosophical Magazine (1871), pp. 447–454. url: journals.ametsoc.org/doi/pdf/10.….

[Ric] C. Riccio. GLM. url: glm.g-truc.net/.

[Ril+04] K. Riley, D. S. Ebert, M. Kraus, J. Tessendorf, and C. Hansen. “Efficient Rendering of Atmospheric Phenomena”. In: Proceedings of the Fifteenth Eurographics Conference on Rendering Techniques. EGSR’04. Norrkoping, Sweden: Eurographics Association, 2004, pp. 375–386. isbn: 3-905673-12-6. doi: 10.2312/EGWR/EGSR04/375-386. url: dx.doi.org/10.2312/EGW….

[Sal+10] M. Salvi, K. Vidimče, A. Lauritzen, and A. Lefohn. “Adaptive Volumetric Shadow Maps”. In: Proceedings of the 21st Eurographics Conference on Rendering. EGSR’10. Saarbrücken, Germany: Eurographics Association, 2010, pp. 1289–1296. doi: 10.1111/j.1467-8659.2010.01724.x. url: dx.doi.org/10.1111/j.1….

[Sch15] A. Schneider. “The Real-time Volumetric Cloudscapes of Horizon: Zero Dawn”. In: Advances in Real Time Rendering, Part I, ACM SIGGRAPH 2015 Courses. SIGGRAPH ’15. Los Angeles, California: ACM, 2015. isbn: 978-1-4503-3634-5. doi: 10.1145/2776880.2787701. url: doi.acm.org/10.1145/277….

[Sch16] A. Schneider. Real-Time Volumetric Cloudscape. Ed. by W. Engel. CRC Press, 2016, pp. 97–127.

[Ser13] A. Serdyuchenko. O3 spectra. 2013. url: www.iup.physik.uni-bremen.de/gruppen/mol….

[VSc] VScauce. The Moon Terminator Illusion. url: www.youtube.com/watch?v=Y2g….

[Wen07] C. Wenzel. “Real time atmospheric effects in game revisited”. In: Game Developers Conference. 2007. url: developer.download.nvidia.com/presentatio….

[Wika] Wikipedia. Angular diameter. url: en.wikipedia.org/wiki/Angula….

[Wikb] Wikipedia. Black body radiation. url: en.wikipedia.org/wiki/Black-….

[Wikc] Wikipedia. Cloud fog bow. url: en.wikipedia.org/wiki/Fog_bo….

[Wikd] Wikipedia. Cloud glory halo. url: en.wikipedia.org/wiki/Glory_….

[Wike] Wikipedia. Cloud Types. url: en.wikipedia.org/wiki/Cloud.

[Wikf] Wikipedia. Day light. url: en.wikipedia.org/wiki/Daylig….

[Wikg] Wikipedia. Light Scattering by Particles. url: en.wikipedia.org/wiki/Light_….

[Wikh] Wikipedia. Limb Darkening. url: en.wikipedia.org/wiki/Limb_d….

[Wiki] Wikipedia. Mole unit. url: en.wikipedia.org/wiki/Mole_(….

[Wikj] Wikipedia. Moon. url: en.wikipedia.org/wiki/Moon.

[Wikk] Wikipedia. Number density. url: en.wikipedia.org/wiki/Number….

[Wikl] Wikipedia. Planck s law. url: goo.gl/PqSGLi.

[Wikm] Wikipedia. Simpson s rule. url: en.wikipedia.org/wiki/Simpso….

[Wikn] Wikipedia. Trapezoidal rule. url: en.wikipedia.org/wiki/Trapez….

[WKL13] M. Wrenninge, C. Kulla, and V. Lundqvist. “Oz: The Great and Volumetric”. In: ACM SIGGRAPH 2013 Talks. SIGGRAPH ’13. Anaheim, California: ACM, 2013, 46:1–46:1. isbn: 978-1-4503-2344-4. doi: 10.1145/2504459.2504518. url: doi.acm.org/10.1145/250….

[Wre11] M. Wrenninge. “Production Volume Rendering”. In: ACM SIGGRAPH 2011 Courses. SIGGRAPH ’11. ACM, 2011.

[WSS13] C. Wyman, P.-P. Sloan, and P. Shirley. “Simple Analytic Approximations to the CIE XYZ Color Matching Functions”. In: Journal of Computer Graphics Techniques (JCGT) (2013). url: jcgt.org/published/0….

[Yus13a] E. Yusov. “Outdoor Light Scattering”. In: Game Developers Conference. 2013. url: software.intel.com/en-us/blogs….

[Yus13b] E. Yusov. Outdoor Light Scattering Sample. 2013. url: software.intel.com/en-us/blogs….

[Yus13c] E. Yusov. Outdoor Light Scattering Sample Update. 2013. url: software.intel.com/sites/defau….

[Yus14] E. Yusov. “High-Performance Rendering of Realistic Cumulus Clouds Using Pre-computed Lighting”. In: Eurographics/ACM SIGGRAPH Symposium on High Performance Graphics. Ed. by I. Wald and J. Ragan-Kelley. The Eurographics Association, 2014. isbn: 9783-905674-60-6. doi: 10.2312/hpg.20141101.

A 天空查找表参数化

在附录中,我们给出了用于将输入参数转换为 LUT 坐标的函数,反之亦然。这些清单表示可用作参考路径的版本(未优化)。清单 3 给出了我们在寒霜引擎中使用的上下文数据、参数化和 LUT 坐标结构的信息。清单 4 给出了将参数转换为查找表坐标的函数。清单 5 给出了逆函数,将查找表坐标转换为参数。

struct SkyLutContext

{

              // 地球属性

              float atmosphereRadius;

              float earthRadius;

                        

              // 查找表分辨率

              float resolutionHeight;

              float resolutionView;

              float resolutionSun;

};

struct SkyLutCoord

{

              // 透射率只是 2D 纹理

              float2 transCoord;

                        

              // 散射是 3D 纹理。

              float3 scattCoord;

};

struct SkyLutParameter

{

              float height; // 相机高度,介于地面 level 0 和大气高度之间

              float cosViewAngle; // 视图天顶角的余弦

              float cosSunAngle; // 太阳天顶角的余弦

};

// \[1] Yusov, Outdoor Light Scattering Sample Update

// \[2] Elek, Rendering Parametrizable Planetary Atmospheres with Multiple Scattering

// \[3] Bruneton, Precomputed Atmospheric Scattering

清单 3:基于物理的天空查找表映射的未优化参考代码。

SkyLutCoord convertSkyParamsToLutCoords(in SkyLutContext context, in SkyLutParameter params)

{

              SkyLutCoord output;

                        

              // 基于相机高度在地面 level 0 和大气高度之间的归一化坐标

              // 在 \[1]\[2]\[3] 中使用,\[1] 中的方程 4

              float normalisedheight = clamp(params.height, 0.f, (context.atmosphereRadius - context.earthRadius));

              normalisedheight = saturate(normalisedheight / (context.atmosphereRadius - context.earthRadius));

              normalisedheight = pow(normalisedheight, 0.5f);

                        

              // 基于天顶方向和视图方向之间角度的归一化坐标

              // \[1] 中的方程 6。用于视图方向,但这里用于太阳方向。

              float normalisedViewZenithTrans = 0.5 \* (atan(max(params.cosViewAngle, -0.45f) \* tan(1.26f \* 0.75f)) / 0.75f + (1.0 - 0.26f));

                        

              // 基于天顶方向和视图方向之间角度的归一化坐标

              // \[1] 中的方程 7

              float height = max(params.height, 0.f);

              float cosHorizon = -sqrt(height \* (2.f \* context.earthRadius + height)) / (context.earthRadius + height);

                        

              float normalisedViewZenithScatt;

              if (params.cosViewAngle > cosHorizon)

              {

                  float cosViewAngle = max(params.cosViewAngle, cosHorizon + 0.0001f);

                  normalisedViewZenithScatt = saturate((cosViewAngle - cosHorizon) / (1.f - cosHorizon));

                  normalisedViewZenithScatt = pow(normalisedViewZenithScatt, 0.2f);

                  normalisedViewZenithScatt = 0.5f + 0.5f / float(context.resolutionView) + normalisedViewZenithScatt \* (float(context.resolutionView) / 2.f - 1.f) / float(context.resolutionView);

              }

              else

              {

                  float cosViewAngle = min(params.cosViewAngle, cosHorizon - 0.0001f);

                  normalisedViewZenithScatt = saturate((cosHorizon - cosViewAngle) / (cosHorizon - (-1.f)));

                  normalisedViewZenithScatt = pow(normalisedViewZenithScatt, 0.2f);

                  normalisedViewZenithScatt = 0.5f / float(context.resolutionView) + normalisedViewZenithScatt \* (float(context.resolutionView) / 2.f - 1.f) / float(context.resolutionView);

              }

                        

              // 太阳角度纹理坐标

              // 论文 \[1] 中的方程 6

              float normalisedSunZenith = 0.5 \* (atan(max(params.cosSunAngle, -0.45f) \* tan(1.26f \* 0.75f)) / 0.75f + (1.0 - 0.26f));

                        

              // 根据分辨率将归一化坐标映射到像素范围之间

              output.transCoord = float2(normalisedheight, normalisedViewZenithTrans);

              output.transCoord = ((output.transCoord \* (float2(context.resolutionHeight, context.resolutionView) - 1) + 0.5) / float2(context.resolutionHeight, context.resolutionView));

                        

              // 根据分辨率将归一化坐标映射到像素范围之间

              output.scattCoord = float3(normalisedheight, normalisedViewZenithScatt, normalisedSunZenith);

              output.scattCoord.xz = ((output.scattCoord \* (float3(context.resolutionHeight, context.resolutionView, context.resolutionSun) - 1) + 0.5) / float3(context.resolutionHeight, context.resolutionView, context.resolutionSun)).xz;

                        

              return output;

}

清单 4:基于物理的天空查找表映射的未优化参考代码。

   // 透射率查找只是 float3,因此 SkyLutParameter.cosSunAngle 将为 0。

SkyLutParameter convertTransmittanceLutCoordsToSkyParams(in SkyLutContext context, in float2 coords)

{

              // 反转有效像素范围映射

              float2 texCoords = saturate((coords \* float2(context.resolutionHeight, context.resolutionView) - 0.5) / (float2(context.resolutionHeight, context.resolutionView) - 1));

                        

              // 反转高度映射

              texCoords.x \*= texCoords.x; // 平方

              float height = texCoords.x \* (context.atmosphereRadius - context.earthRadius);

                        

              // 反转视图映射

              float cosViewAngle = tan((2.0 \* texCoords.y - 1.0 + 0.26) \* 0.75) / tan(1.26 \* 0.75);

              cosViewAngle = clamp(cosViewAngle, -1, 1);

                        

              // 输出

              SkyLutParameter output = (SkyLutParameter)0;

              output.height = height;

              output.cosViewAngle = cosViewAngle;

              return output;

}

SkyLutParameter convertScatteringLutCoordsToSkyParams(in SkyLutContext context, in float3 coords)

{

              // 反转有效像素范围映射

              float3 texCoords = saturate((coords \* float3(context.resolutionHeight, context.resolutionView, context.resolutionSun) - 0.5) / (float3(context.resolutionHeight, context.resolutionView, context.resolutionSun) - 1));

                        

              // 反转高度映射

              texCoords.x \*= texCoords.x; // 平方

              float height = texCoords.x \* (context.atmosphereRadius - context.earthRadius);

                        

              // 反转视图映射

              height = max(height, 0.0);

              float cosHorizon = -sqrt(height \* (height + 2.0 \* context.earthRadius)) / (context.earthRadius + height);

              float cosViewAngle;

                        

              if (texCoords.y > 0.5)

              {

                  texCoords.y = saturate((texCoords.y - (0.5 + 0.5 / context.resolutionView)) \* context.resolutionView / (context.resolutionView / 2.0 - 1.0));

                  texCoords.y = pow(texCoords.y, 5.0);

                  cosViewAngle = max((cosHorizon + texCoords.y \* (1 - cosHorizon)), cosHorizon + 1e-4);

              }

              else

              {

                  texCoords.y = saturate((texCoords.y - 0.5 / context.resolutionView) \* context.resolutionView / (context.resolutionView / 2.0 - 1.0));

                  texCoords.y = pow(texCoords.y, 5);

                  cosViewAngle = min((cosHorizon - texCoords.y \* (cosHorizon - (-1))), cosHorizon - 1e-4);

              }

                        

              cosViewAngle = clamp(cosViewAngle, -1.0, 1.0);

                        

              // 太阳角度的参数化

              float cosSunAngle = tan((2.0 \* texCoords.z - 1. + 0.26) \* 0.75) / tan(1.26 \* 0.75);

              cosSunAngle = clamp(cosSunAngle, -1.0, 1.0);

                        

              SkyLutParameter output = (SkyLutParameter)0;

              output.height = height;

              output.cosViewAngle = cosViewAngle;

              output.cosSunAngle = cosSunAngle;

              return output;

}

清单 5:基于物理的天空查找表映射的未优化参考代码。

B 太阳临边昏暗天体物理模型

我们介绍了两种表示太阳临边昏暗模型的天体物理模型的实现。在这些模型中:

  • centerToEdge:从中心到太阳边缘的归一化距离。

  • finalLuminance:太阳对像素的最终亮度贡献。



    // 模型来自 http://www.physics.hmc.edu/faculty/esin/a101/limbdarkening.pdf

    float3 u = float3(1.0, 1.0, 1.0); // 一些模型有 u!=1

    float3 a = float3(0.397, 0.503, 0.652); // RGB 波长(680,550,440)的系数

    centerToEdge = 1.0 - centerToEdge;

    float mu = sqrt(1.0 - centerToEdge \* centerToEdge);

    float3 factor = 1.0 - u \* (1.0 - pow(mu, a));

    finalLuminance \*= factor;

清单 6:根据 [Nec96] 的太阳临边昏暗模型。

    // 使用来自 http://articles.adsabs.harvard.edu/cgi-bin/nph-iarticle\_query?1994SoPh..153...91N\&defaultprint=YES\&filetype=.pdf 的 P5 多项式模型

    centerToEdge = 1.0 - centerToEdge;

    float mu = sqrt(1.0 - centerToEdge \* centerToEdge);

    // RGB 波长(680,550,440)的系数

    float3 a0 = float3(0.34685, 0.26073, 0.15248);

    float3 a1 = float3(1.37539, 1.27428, 1.38517);

    float3 a2 = float3(-2.04425, -1.30352, -1.49615);

    float3 a3 = float3(2.70493, 1.47085, 1.99886);

    float3 a4 = float3(-1.94290, -0.96618, -1.48155);

    float3 a5 = float3(0.55999, 0.26384, 0.44119);

    float mu2 = mu \* mu;

    float mu3 = mu2 \* mu;

    float mu4 = mu2 \* mu2;

    float mu5 = mu4 \* mu;

    float3 factor = a0 + a1 \* mu + a2 \* mu2 + a3 \* mu3 + a4 \* mu4 + a5 \* mu5;

    finalLuminance \*= factor;

清单 7:根据 [HM98] 的太阳临边昏暗模型。

C 守恒能量的解析散射积分

我们详细介绍了第 5.6.3 节中介绍和讨论的守恒能量的散射光积分数。该函数基本上给出了从均匀参与介质平板(深度 d=b-a)散射出的光量,假设要散射的入射光均匀 S 和消光 σₜ。

x=0dexpσtxA~—S dx=SSexpσtdσtx=abexpσt(xa)A~—S dx=SSexpσt(ba)σt(23) \begin{gathered} \int_{x=0}^{d} \exp ^{-\sigma_{t} x} × S \mathrm{~d} x=\frac{S-S \exp ^{-\sigma_{t} d}}{\sigma_{t}} \\ \int_{x=a}^{b} \exp ^{-\sigma_{t}(x-a)} × S \mathrm{~d} x=\frac{S-S \exp ^{-\sigma_{t}(b-a)}}{\sigma_{t}} \end{gathered} \quad (23)

以下是该结果的数学证明(其中第 3 行是使用 exp (u)'=u'exp (u) 这一事实获得的):

x=0dexpσtxA~—S dx=SA~—x=0dexpσtx dx=S×[expσtx]0xa¨½¿c¸”¨exp(u)=uexp(u),=S×(expσtxσtexpσtA~—0σt)=SA~—expσtx1σt=SSexpσtdσt \begin{aligned} \int_{x=0}^{d} \exp ^{-\sigma_{t} x} × S \mathrm{~d} x & =S × \int_{x=0}^{d} \exp ^{-\sigma_{t} x} \mathrm{~d} x \\ & =S \times\left[\exp ^{-\sigma_{t} x}\right]_{0}^{x} \\ \text{使用} \exp (u)'=u' \exp (u), & \\ & =S \times\left(\frac{\exp ^{-\sigma_{t} x}}{-\sigma_{t}}-\frac{\exp ^{-\sigma_{t} × 0}}{-\sigma_{t}}\right) \\ & =S × \frac{\exp ^{-\sigma_{t} x}-1}{-\sigma_{t}} \\ & =\frac{S-S \exp ^{-\sigma_{t} d}}{\sigma_{t}} \end{aligned}

第 5.6.3 节介绍了将这种能量散射公式用于云渲染所带来的改进。图 53 展示了它如何用于 [Hil15] 中介绍的更一般的参与介质渲染用例。

image.png

图 53:当增加 σₛ 时,参与介质材料应收敛为看起来像固体材料。然而,如第 5.6 节所示,不使用方程 23 而使用迭代方法积分散射光可能会导致过多的能量返回相机(从左到右:σₛ=5,σₛ=50 和 σₛ=5000)。使用守恒能量的散射方程 23,右图中 σₛ=5000 的厚参与介质立方体看起来更像完美的漫反射表面,这在使用均匀相位函数时是预期的。

D 可平铺体积噪声库

我们在第 5.4 节中介绍了体积云渲染所需的重要噪声类型。我们提供了此类函数的源代码:

  1. github.com/sebh/Tileab…

  2. 多个八度的体积 Worley 噪声(Marc-Andre Loyer)

  3. 多个八度的体积 Perlin 噪声,使用 GLM [Ric]

  4. [Sch15] 中描述的 Perlin-Worley 噪声