GraphicsLab 之 Atmospheric Scattering (一)

 

做者:i_dovelemon程序员

日期:2020-10-11api

主题:Atmospheric Scattering, Volume Scattering, Rayleigh Scattering, Mie Scattering, Single Scattering, Multiple Scattering数组

引言

        Atmospheric Scattering(大气散射),是不少 3A 大做的标配。好的大气系统,可以给游戏带来很好的体验,诸多的游戏都花费了大量的精力来构建一整套复杂的大气系统。less

        通常来讲,一个大气系统至少要包含:天空渲染(Sky Rendering),云层渲染(Cloud Rendering)和各类光线效果(Light Shaft, Volumetric Lighting)等。函数

        今天这篇文章,主要是想和你们聊聊天空渲染(Sky Rendering)的部分,但愿经过几篇文章,讲解清楚天空渲染(Sky Rendering)背后的知识以及相关实现的方法。spa

体积散射

        在具体讲解 Sky Rendering 以前,咱们先来了解一下 Volume Scattering 相关的知识。3d

        学过渲染的同窗可能都知道,物体渲染的方式主要分为两个大的类别:一种是基于物体表面(Surface)进行建模的渲染,好比石头,建筑,角色等等大量的物体都是采用这种方式进行渲染。除此以外,还有一种基于体积(Volume)的渲染方式,好比烟,雾,云等等经过大量微小颗粒汇集而成的物体就须要采用这种方式进行渲染。blog

        基于体积的渲染和基于表面的渲染之间的区别在于,基于表面的渲染是假设物体处在真空当中,表面与表面之间的光线是以一种不会发散,衰减的方式进行传播的。固然现实世界中的物体都不是如此的,空气中存在大量的微小颗粒,这些颗粒会致使光线在传播过程当中发生散射(Scattering)。游戏

       对于 Sky Rendering 来讲,因为大气中存在了大量的粒子,太阳光线通过大气,传播进入眼睛以后就通过了这样的一系列散射过程。因此,Sky Rendering 就是一种基于体积的渲染方式。ip

体积散射过程

        这里介绍一些基本的 Volume Scattering 的概念。首先总体上描述下 Volume Scattering 包含了哪些部分:

Absorption 光线在传播过程当中,碰撞到物体的时候,一部分能量会转换成为热能的形式丢失
Emission 光源物体,会增长新的光线到环境中去
Scattering 光线在传播过程当中,碰撞到物体的时候,从一个方向散射到另一个方向上去

        其中,Absorption 和 Emission 比较简单,容易理解,这里再也不赘述。可是对于 Scattering 部分,就比较复杂。

        对于观察者来讲,直接向观察者照射的光线在传播过程当中,会因为散射到其余方向,致使一部分的能量丢失。这部分称之为 Out-Scattering,以下所示:

        一样的,因为 Scattering,一些本来不会直接照射到观察者眼中的光线也会被散射进来,致使一部分的能量增长。这部分称之为 In-Scattering,以下所示:

 

         因为 Absorption 和 Out-Scattering,都会致使光线在传播过程当中能量丢失,因此将这两部分丢失能量合在一块儿,称之为 Attenuation 或者 Extinction。

         Extinction 表示的是单个点的能量衰减程度,那么对两个点之间线段上能量的衰减,咱们使用一个 Transmitance 来表示,即通过该段线段以后,因为 Absorption 和 Out-Scattering 只有一部分光线传输出去,以下图所示:

 

         对于表面渲染来讲,咱们使用 BRDF 表示入射光线有多少被反射到指定的方向上去。一样的,对于体积渲染来讲,也有相似的表示,咱们称之为 Phase Function,它定义了向某个特定方向散射的几率分布状况。

         这里只是简单的,概念性的介绍了体积渲染相关的知识,更多的细节能够查看参考文献 [1] 进行了解。

天空渲染

        前面介绍了一点 Volume Scattering 相关的背景知识。因为天空主要是有各类颗粒组成的,因此对天空的渲染,实际上就是体积渲染。

        知道了渲染的方式,那么接下来,咱们须要对大气进行建模,以便于了解它的组成,从而配合体积散射相关的理论,进行最终的渲染。

大气模型

        大气其实是一层包裹着地球的一团气体,天空的颜色就主要是太阳光照射到这层气体,进行散射以后所呈现出来的。

        这层气体具备必定的厚度,因此咱们将整个大气建模成一个包裹着地球的具备必定厚度的空心球壳。

        同时大气中颗粒密度并非均匀分布的,大致上来讲,随着海拔的升高,颗粒密度愈来愈低。咱们经过一个名为 Density Ratio 的函数来描述这种随海拔升高,密度降低的特性。

        大气中存在各类各样的粒子,它们的光学性质并不相同。为了简化问题,主要将大气粒子分为两种大类:Air Molecules 和 Aerosols。

        Air Molecules 表示大气中较小的粒子,经过 Rayleigh Scattering 模拟散射状况。

        Aerosols 表示大气中较大的粒子,经过 Mie Scattering 模拟散射状况。

        以下图是这种大气模型的概念示意图:

 

        其中,Re = 6360 km,表示的是地球的半径。Ra = 6420 km 表示的是大气的半径。数据来源于参考文献 [2]。

天空颜色

        对大气进行建模以后,咱们须要知道怎么去渲染大气。一般咱们使用一个后处理 Pass 来渲染天空做为场景的背景。那么对于每个像素来讲,它所呈现的颜色是来源于什么了?

        对于每个像素来讲,咱们均可以从观察者位置投射出一条观察射线,观察射线会与大气层相交,而在整个相交的线段上面,全部的大气颗粒均可以经过对太阳光散射的形式贡献颜色,以下图所示:

 

        观察射线与大气层相交获得 AB 线段,对于 AB 线段上的任意一点 P 来讲,均可能经过散射在 PA 方向贡献一部分光照。

        因此对于像素的颜色来讲,咱们就须要计算出这条 AB 线段上每个点 P 向 PA 方向上散射出来的光照的总和,该总和值,就是当前像素的颜色。

大气散射方程

        正如前面一节所说的,像素的颜色是 AB 线段上全部点 P 在 PA 方向散射出来的光照的总和。假设咱们已经知道了点 P 接受的光照强度为 $I_p$,那么有多少的光照强度被散射向 A 点了?定义以下公式来表达:

$$I_{out} = I_p * S(\lambda ,\theta ,h)$$(Eq 1)

        其中 $S(\lambda ,\theta ,h)$ 表示了有多少光照强度被散射向 PA 方向,即大气散射函数(Atmospheric Scattering Equation)。

        值得注意的是,这里只是讨论了有多少被散射向 PA 方向,并非说 A 点接受了多少来自 P 点的光照强度。注意区分这里的细微差异。缘由在于,P 点散射向 PA 方向的光照强度,通过 PA 线段的大气层以后,也会有衰减发生。

        而 $S(\lambda ,\theta ,h)$ 的定义以下所示:

$$S(\lambda ,\theta ,h)=\beta (\lambda ,h) * \gamma (\theta)$$(Eq 2)

        其中:

        $\beta (\lambda ,h)$  表示的是,因为 Out-Scattering 致使了有多少能量被散射向各个方向上去,咱们称之为散射系数(Scattering Coefficient);

        $\gamma (\theta)$ 表示的 Phase Function,即在 $\theta$ 角度方向上散射出去的几率;

        $\lambda$ 表示的是光线的波长,不一样的波长散射系数可能并不一致,对普通渲染来讲,即对光照的 RGB 份量分别有不一样的散射系数;

        $h$ 表示的是海拔高度,前面 Atmospheric Model 一节已经说过,随着海拔高度的不一样,大气密度不一样,因此散射系数也并不相同;

        $\theta$ 表示的是点 P 处接受的光线入射方向与散射方向 PA 的夹角,以下图所示:

 

 

        这两个函数组合在一块儿,就描述了点 P 处有多少光照强度反射向了 A 点。

散射系数

        从上面一节中咱们得知:$\beta (\lambda ,h)$ 表示的是在海拔高度 $h$ ,光线波长 $\lambda$ 处的散射系数。前面提到过大气模型中,大气密度是随着高度慢慢变的稀薄,因此为了模拟这种关系,提出了一个 Denstiy Ratio 的函数来描述这种关系。

        而这种关系主要就体如今散射系数中,因此咱们能够将散射系数的函数拆分红以下两个函数的组合:

$$\beta (\lambda ,h)=\beta (\lambda,0) * \rho (h)$$(Eq 3)

        其中:

        $\beta (\lambda,0)$ 表示的是海拔高度 0 处的散射系数;

        $\rho (h)$ 表示的是随海拔高度变化的 Denstiy Ratio 函数,完整定义以下所示:

$$\rho (h)=e^{-\frac{h}{H}}$$(Eq 4)

        其中:

        $H$ 表示的大气的平均密度所在的高度,通常称之为 Scale Height。

        咱们以前说过,大气中粒子成分过于复杂,因此分为了两个大类,分别使用 Rayleigh Scattering 和 Mie Scattering 进行模拟。为此上面提到的几个数据都分别给出 Rayleigh 和 Mie 的参数:

Type $\beta (\lambda,0)$ $H$
Rayleigh R 3.8e-6f 7994m
G 13.5e-6f
B 33.1e-6f
Mie R 21e-6f 1200m
G 21e-6f
B 21e-6f

数据来源与参考文献 [2]

Phase Function

        回忆以前说到的 Atmospheric Scattering Equation:

$$S(\lambda ,\theta ,h)=\beta (\lambda ,h) * \gamma (\theta)$$(Eq 2)

        目前只剩下了最后一个 $\gamma (\theta)$ 没有说明了。以前介绍 Volume Scattering 的时候说过,这个函数是 Phase Function,用于表示在指定方向上,光线散射出去的几率。

        一样的,这里也给出 Rayleigh Scattering 和 Mie Scattering 对应的 Phase Function:

Type $\gamma (\theta)$
Rayleigh

$\gamma (\theta) = \frac{3}{16 \pi}(1 + \mu^{2})$

$\mu = \cos \theta$

Mie

$\gamma (\theta) = \frac{3}{8 \pi}\frac{(1-g^{2})(1+\mu^2)}{(2+g^2)(1+g^2-2g\mu)^{\frac{3}{2}}}$

$g=0.76$

$\mu = \cos \theta$

数据来源与参考文献 [2]

Transmittance Function

        前面一节,讲述了线段 AB 上点 P,在接受到入射光 $I_p$ 的状况下,有多少关照强度被散射到 PA 方向上去。以前说过,这里只是计算了有多少被散射到 PA 方向,而达到 A 点处的并非这么多。因为大气的缘由,在 PA 路径上依然会发生散射的现象,这就致使了达到 A 点的将小于 P 点散射向 PA 方向上的光线。而根据前面基础概念一节中的接受,这个比例关系咱们经过一个名为 Transmittance Function 的函数来描述,以下所示:

$$I_a = I_{pa}*T_{pa}$$(Eq 5)

而,

$$T_{pa}= e^{-{\int_{0}^{d}\beta(\lambda,h)}}$$(Eq 6)

公式来自参考文献 [1]

其中 $d$ 表示 PA 之间的距离,$e$ 是天然数。

        实际上,Transmittance Function 描述了任意两个点之间,因为大气散射致使的能量衰减所剩余的光照比例,不只能够描述上述 P 点到 A 点路径上能量的衰减状况,也能够描述空间中任意两点之间的衰减。

Single Scattering vs Multiple Scattering

        根据前面两节的描述,咱们知道了 AB 线段上任意一点 P 在通过大气散射以后,达到 A 点的光照能量为:

$$I_a = I_p * S(\lambda ,\theta ,h) * T_{pa}$$(Eq 7)

        前面两节已经讲述了 $S$ 和 $T$ 是什么,如今惟一剩下的就是 $I_p$ 自己了。

        这里就要涉及到 Single Scattering vs Multiple Scattering 了。对于 Single Scattering 来讲,$I_p$ 能够认为只有太阳光 $I_{sun}$ 到 P 点这条散射路径会作出光照贡献。

        而对于 Multiple Scattering,状况就很复杂了。因为太阳光进入大气以后,会被粒子散射,致使光照方向进行屡次改变,因此不只仅有太阳光直接入射到 P 点的光照,也会有空气中粒子对其余方向的太阳光通过屡次散射以后,反射而来的光照。

        这里,为了简化问题,下降实现难度,咱们只考虑 Single Scattering。也就是说,

$$I_p = I_{sun} * T_{cp}$$(Eq 8)

 

        其中,$T_{cp}$ 表示的 CP 线段上的衰减 Transmittance。C 点为太阳光入射向量与大气层最外围相交的点。

        将 Eq 8 带入 Eq 7 便可获得太阳光 $I_{sun}$ 入射向点 P,讲过 PA 方向散射以后,到达 A 点所剩余的光照:

$$I_a = I_{sun} * T_{cp} * S(\lambda ,\theta ,h) * T_{pa}$$(Eq 9)

天空渲染方程

        前面几节,完整的讲述了 Single Scattering 下,AB 线段上任意一点 P 通过太阳的入射和大气的衰减,最终达到 A 点的光照强度。可是最开始的时候,咱们也讲述了,天空的颜色其实是 AB 线段上全部点贡献的最终结果。单单一个 P 点的结果,仍是没法获得最终的颜色,咱们须要累积 AB 线段上全部点 P反射到 A 上的光照能量的总和,才是最终须要显示的天空的颜色,即:

$$I_{final}=\int_{A}^{B}{I_{sun} * T_{cp} * S(\lambda ,\theta ,h) * T_{pa}}$$(Eq 10)

这个公式,即为最终须要计算视线沿着 AB 方向所看到的天空的颜色。

总结

        本篇文章主要讲述了天空渲染背后的理论知识以及相关的数学原理。固然不少公式背后的原理并无给出来,一方面是篇幅有限,另一方面是我本身也没有搞明白是怎么推导出来的。做为程序员,我这里只是帮助你们梳理清楚和最终实现最接近的数学原理,更深层次的原理,感兴趣的能够根据参考文献继续了解。强烈建议阅读参考文献[2]和[3] 来了解更多相关的背景知识。

        接下来的一篇文章,将向你们展现如何实现这里的数学公式,从而渲染出题图所示的天空出来。

参考

[1] Physically Based Rendering From Theory to Implementation Third Edition

[2] Simulating the Colors of the Sky

[3]  Volumetric Atmospheric Scattering

相关文章
相关标签/搜索