雾、云、天空和大气的环境光源
天空和大气的渲染 透射率 LUT
参考 2020 年 Hillaire 工作的大气透射率预计算实现
完整实现代码
参照论文 Hillaire 2020 - A Scalable and Production Ready Sky and Atmosphere Rendering Technique 中的实时大气渲染方案实现。
Transmittance LUT 记录光线积分部分,后续计算 Sky-View LUT 等直接查询这张纹理。
由于大气和行星都被近似为同心球,透射率只与两个量有关:观察点到行星中心的距离 r,以及观察方向与当地天顶方向夹角的余弦值 μ=cos(θ)。因此可以用一张二维纹理表示:
T(r,μ)=exp[−τ(r,μ)].(1)
其中 τ 是光线从观察点到大气层顶端的光学深度,T 为 RGB 三通道透射率。
构造一个函数 f,输入是归一化纹理坐标 (u,v),输出是观察点到行星中心的距离 r 和观察方向的天顶角余弦 μ。得到 (r,μ) 后,计算对应方向上的光学深度 τ 与透射率 T(r,μ)。
参照 Bruneton 2008 - Precomputed Atmospheric Scattering 的参数化,只表示视线切线到垂直地面之间的天顶角部分。看向地面的天顶角不加入计算。
下面推导上述函数 f:
设行星半径为 Rp,大气层半径为 Ra。从行星表面的切线点到大气层顶端的距离为:
H=Ra2−Rp2,ρ=Hv.(1)
易得:
r=ρ2+Rp2.(2)
v=0 对应行星表面,v=1 对应大气层顶端。
相较于直接插值高度 (0,1),这种非线性映射会为靠近地表的区域分配更多纹素。
在高度 r 处,沿径向向上到达大气层顶端的最短距离为:
dmin=Ra−r,dmax=ρ+H,d=(1−u)dmin+udmax.(3)
使用余弦定理,易得:
Ra2=r2+d2−2rdcos(π−θ)=r2+d2+2rdμ.(4)
整理可得:
μ=2rdRa2−r2−d2.(5)
代入前式:
H2=Ra2−Rp2,ρ2=r2−Rp2,H2−ρ2=Ra2−r2.(6)
代入上式,最终得到:
μ=2rdH2−ρ2−d2.(7)
其中 μ=1 表示光线方向垂直地面竖直向上,μ=0 表示光线方向与远方地平线相切。
为 LUT 的每个纹素写入这条射线对应的透射率 T(r,μ)。
计算积分上限 stop,即射线沿射线方向从观察点 p 到大气层顶端的路径长度。
从点 p0 出发,沿方向 ω 前进距离 s,得到射线上的位置:
p(s)=p0+sω.
p0 对应的单位向量为:
n=rp0.
天顶角 θ 是当地天顶方向 n 与观察方向 ω 的夹角,易得:
μ=cosθ=n⋅ω=rp0⋅ω.(9)
根据前面得到的观察点半径 r 和观察方向 ω,求出射线到达大气层顶端时的参数 stop:
∥p0+sω∥2=Ra2.(10)
∥p0∥2+2sp0⋅ω+s2∥ω∥2=Ra2.
由 ∥p0∥=r、∥ω∥=1,以及式(9)中的 p0⋅ω=rμ,代入式(10)得到:
r2+2rμs+s2=Ra2.
移项后得到关于 s 的二次方程:
s2+2rμs+(r2−Ra2)=0.
使用求根公式:
s=2−2rμ±(2rμ)2−4(r2−Ra2)=−rμ±r2(μ2−1)+Ra2.
两个根对应直线与大气层球面的两个交点:较小的根位于射线反方向,较大的根位于观察方向的前方。
光学深度只沿观察方向积分,因此取较大的根,得到观察点到大气层顶端的距离:
stop=−rμ+r2(μ2−1)+Ra2.(11)
接下来,对一条长度为 stop 的射线,三种介质各自的柱密度为:
Di(r,μ)=∫0stopρi(h(s))ds,i∈{R,M,A}.(14)
其中,射线上距离起点 s 处的高度半径(地心距离)为:
rs=r2+s2+2rμs,h(s)=rs−Rp.(15)
实现将射线平均分成 N 段,每段长度为 Δs=stop/N,并使用中点法近似积分:
Di(r,μ)≈j=0∑N−1ρi(h((j+21)Δs))Δs.(16)
中点法不会恰好采样行星表面或大气层顶端,能够减弱球形边界和密度突变对数值积分的影响。transmittanceSteps 越大,积分越准确,但生成 LUT 的成本也越高。
设 βR、βM 和 βA 分别为三种介质的 RGB 消光系数,总光学深度为:
τ=βRDR+βMDM+βADA.(17)
根据 Beer–Lambert 定律,最终透射率为:
T(r,μ)=exp(−τ).(18)
三种介质都会移除沿原方向传播的光,因此它们的消光贡献应当相加。
Transmittance LUT 只描述光线穿过大气后的衰减,它并不知道当前计算的光线是否会先撞到行星表面。太阳落到地平线以下时,太阳光方向已经穿过行星,不能继续为该位置的大气提供直接光照。
行星遮挡部分代码
未处理
处理
视觉上看,直接读取 LUT 和 64 步光线步进效果完全一样。
64 Light Steps
LUT
相比不用 LUT,使用 LUT 分别比 64、32 和 16 个 Light Steps 快约 28.4 倍、14.9 倍和 8.2 倍。
Without LUT, 64 Light Steps 6.565 msWithout LUT, 32 Light Steps 3.450 msWithout LUT, 16 Light Steps 1.900 ms
下一步可以继续阅读 03 Sky-View LUT 实现,了解如何在视线积分中复用这张透射率表,并缓存天空散射结果。