J1N9H3
雾、云、天空和大气的环境光源

天空和大气的渲染 透射率 LUT

参考 2020 年 Hillaire 工作的大气透射率预计算实现

完整实现代码

Alpha3D v0.1.8

参照论文 Hillaire 2020 - A Scalable and Production Ready Sky and Atmosphere Rendering Technique 中的实时大气渲染方案实现。

天空和大气的渲染

Transmittance LUT 记录光线积分部分,后续计算 Sky-View LUT 等直接查询这张纹理。

天空和大气的渲染

由于大气和行星都被近似为同心球,透射率只与两个量有关:观察点到行星中心的距离 rr,以及观察方向与当地天顶方向夹角的余弦值 μ=cos(θ)\mu=cos(\theta)。因此可以用一张二维纹理表示:

T(r,μ)=exp[τ(r,μ)].(1)T(r,\mu)=\exp\left[-\tau(r,\mu)\right]. \tag{1}

其中 τ\tau 是光线从观察点到大气层顶端的光学深度,TT 为 RGB 三通道透射率。

构造 Transmittance LUT 输入输出

构造一个函数 ff,输入是归一化纹理坐标 (u,v)(u,v),输出是观察点到行星中心的距离 rr 和观察方向的天顶角余弦 μ\mu。得到 (r,μ)(r,\mu) 后,计算对应方向上的光学深度 τ\tau 与透射率 T(r,μ)T(r,\mu)

参照 Bruneton 2008 - Precomputed Atmospheric Scattering 的参数化,只表示视线切线到垂直地面之间的天顶角部分。看向地面的天顶角不加入计算。

下面推导上述函数 ff

天空和大气的渲染

设行星半径为 RpR_p,大气层半径为 RaR_a。从行星表面的切线点到大气层顶端的距离为:

H=Ra2Rp2,ρ=Hv.(1)H=\sqrt{R_a^2-R_p^2}, \quad \rho=Hv. \tag{1}

易得:

r=ρ2+Rp2.(2)r=\sqrt{\rho^2+R_p^2}. \tag{2}

v=0v=0 对应行星表面,v=1v=1 对应大气层顶端。

相较于直接插值高度 (0,1)(0, 1),这种非线性映射会为靠近地表的区域分配更多纹素。

天空和大气的渲染

在高度 rr 处,沿径向向上到达大气层顶端的最短距离为:

dmin=Rar,dmax=ρ+H,d=(1u)dmin+udmax.(3)d_{\min}=R_a-r, \quad d_{\max}=\rho+H, \quad d=(1-u)d_{\min}+u d_{\max}. \tag{3}

使用余弦定理,易得:

Ra2=r2+d22rdcos(πθ)=r2+d2+2rdμ.(4)R_a^2 =r^2+d^2-2rd\cos(\pi-\theta) =r^2+d^2+2rd\mu. \tag{4}

整理可得:

μ=Ra2r2d22rd.(5)\mu=\frac{R_a^2-r^2-d^2}{2rd}. \tag{5}

代入前式:

H2=Ra2Rp2,ρ2=r2Rp2,H2ρ2=Ra2r2.(6)H^2=R_a^2-R_p^2, \quad \rho^2=r^2-R_p^2, \quad H^2-\rho^2=R_a^2-r^2. \tag{6}

代入上式,最终得到:

μ=H2ρ2d22rd.(7)\mu = \frac{H^2-\rho^2-d^2}{2rd}. \tag{7}

其中 μ=1\mu=1 表示光线方向垂直地面竖直向上,μ=0\mu=0 表示光线方向与远方地平线相切。

写入 Transmittance LUT

为 LUT 的每个纹素写入这条射线对应的透射率 T(r,μ)T(r,\mu)

计算积分上限 stops_{\mathrm{top}},即射线沿射线方向从观察点 pp 到大气层顶端的路径长度。

天空和大气的渲染

从点 p0\boldsymbol{p}_0 出发,沿方向 ω\boldsymbol{\omega} 前进距离 ss,得到射线上的位置:

p(s)=p0+sω.\boldsymbol{p}(s)=\boldsymbol{p}_0+s\boldsymbol{\omega}.

p0\boldsymbol{p}_0 对应的单位向量为:

n=p0r.\boldsymbol{n}=\frac{\boldsymbol{p}_0}{r}.

天顶角 θ\theta 是当地天顶方向 n\boldsymbol{n} 与观察方向 ω\boldsymbol{\omega} 的夹角,易得:

μ=cosθ=nω=p0rω.(9)\mu =\cos\theta =\boldsymbol{n}\cdot\boldsymbol{\omega} =\frac{\boldsymbol{p}_0}{r}\cdot\boldsymbol{\omega}. \tag{9}

根据前面得到的观察点半径 rr 和观察方向 ω\boldsymbol{\omega},求出射线到达大气层顶端时的参数 stops_{\mathrm{top}}

p0+sω2=Ra2.(10)\left\|\boldsymbol{p}_0+s\boldsymbol{\omega}\right\|^2=R_a^2. \tag{10} p02+2sp0ω+s2ω2=Ra2.\left\|\boldsymbol{p}_0\right\|^2 +2s\,\boldsymbol{p}_0\cdot\boldsymbol{\omega} +s^2\left\|\boldsymbol{\omega}\right\|^2=R_a^2.

p0=r\|\boldsymbol{p}_0\|=rω=1\|\boldsymbol{\omega}\|=1,以及式(9)中的 p0ω=rμ\boldsymbol{p}_0\cdot\boldsymbol{\omega}=r\mu,代入式(10)得到:

r2+2rμs+s2=Ra2.r^2+2r\mu s+s^2=R_a^2.

移项后得到关于 ss 的二次方程:

s2+2rμs+(r2Ra2)=0.s^2+2r\mu s+(r^2-R_a^2)=0.

使用求根公式:

s=2rμ±(2rμ)24(r2Ra2)2=rμ±r2(μ21)+Ra2.\begin{aligned} s &=\frac{-2r\mu\pm\sqrt{(2r\mu)^2-4(r^2-R_a^2)}}{2} &=-r\mu\pm\sqrt{r^2(\mu^2-1)+R_a^2}. \end{aligned}

两个根对应直线与大气层球面的两个交点:较小的根位于射线反方向,较大的根位于观察方向的前方。

光学深度只沿观察方向积分,因此取较大的根,得到观察点到大气层顶端的距离:

stop=rμ+r2(μ21)+Ra2.(11)s_{\mathrm{top}} =-r\mu+\sqrt{r^2(\mu^2-1)+R_a^2}. \tag{11}

接下来,对一条长度为 stops_{\mathrm{top}} 的射线,三种介质各自的柱密度为:

Di(r,μ)=0stopρi ⁣(h(s))ds,i{R,M,A}.(14)D_i(r,\mu) = \int_0^{s_{\mathrm{top}}} \rho_i\!\left(h(s)\right)\,\mathrm{d}s, \qquad i\in\{R,M,A\}. \tag{14}

其中,射线上距离起点 ss 处的高度半径(地心距离)为:

rs=r2+s2+2rμs,h(s)=rsRp.(15)r_s=\sqrt{r^2+s^2+2r\mu s}, \qquad h(s)=r_s-R_p. \tag{15}

实现将射线平均分成 NN 段,每段长度为 Δs=stop/N\Delta s=s_{\mathrm{top}}/N,并使用中点法近似积分:

Di(r,μ)j=0N1ρi ⁣(h((j+12)Δs))Δs.(16)D_i(r,\mu) \approx \sum_{j=0}^{N-1} \rho_i\!\left(h\left((j+\tfrac12)\Delta s\right)\right)\Delta s. \tag{16}

中点法不会恰好采样行星表面或大气层顶端,能够减弱球形边界和密度突变对数值积分的影响。transmittanceSteps 越大,积分越准确,但生成 LUT 的成本也越高。

βR\boldsymbol{\beta}_RβM\boldsymbol{\beta}_MβA\boldsymbol{\beta}_A 分别为三种介质的 RGB 消光系数,总光学深度为:

τ=βRDR+βMDM+βADA.(17)\boldsymbol{\tau} = \boldsymbol{\beta}_R D_R +\boldsymbol{\beta}_M D_M +\boldsymbol{\beta}_A D_A. \tag{17}

根据 Beer–Lambert 定律,最终透射率为:

T(r,μ)=exp(τ).(18)\boldsymbol{T}(r,\mu)=\exp(-\boldsymbol{\tau}). \tag{18}

三种介质都会移除沿原方向传播的光,因此它们的消光贡献应当相加。

处理行星遮挡

Transmittance LUT 只描述光线穿过大气后的衰减,它并不知道当前计算的光线是否会先撞到行星表面。太阳落到地平线以下时,太阳光方向已经穿过行星,不能继续为该位置的大气提供直接光照。

行星遮挡部分代码

v0.1.9

None未处理
None处理

采样 Transmittance LUT

视觉上看,直接读取 LUT 和 64 步光线步进效果完全一样。

None64 Light Steps
NoneLUT

相比不用 LUT,使用 LUT 分别比 64、32 和 16 个 Light Steps 快约 28.4 倍、14.9 倍和 8.2 倍。

GPU 时间对比

0.231 ms
6.565 ms
3.450 ms
1.900 ms

下一步可以继续阅读 03 Sky-View LUT 实现,了解如何在视线积分中复用这张透射率表,并缓存天空散射结果。

On this page