太阳接近地平线时,光在空气中走得更远,颜色与亮度一起改变。大气渲染需要同时计算太阳到散射点、散射点到相机的损失,再累积沿视线进入相机的光。查找表(LUT)缓存这份计算中的稳定维度;表的坐标、积分边界和更新依赖共同决定结果。
大气介质与射线区间
以行星中心为原点,地表半径为 Rg,大气外半径为 Rt。位置 x 的高度是 h=∥x∥−Rg,距离统一用米。一个可实现的球对称模型使用密度 ρR(h)=e−h/HR、ρM(h)=e−h/HM,其中 HR,HM 是尺度高度。海平面的瑞利散射系数 βR、气溶胶散射与吸收系数 βMs,βMa 都按 RGB 通道分别给出,单位为每米。
局部散射系数为 σs=βRρR+βMsρM,消光系数为 σt=σs+βMaρM。臭氧等吸收层可再添加独立密度与吸收系数。密度、系数和高度单位必须一起传给预计算与运行着色器;例如真实路径1千米、消光系数0.001/米,正确光学深度为1000×0.001=1;若路径数值仍用千米的1直接相乘,就得到0.001,光学深度被缩小一千倍,透射率从约0.368错误地变成约0.999。
相机射线为 o+td,d 是单位向量。对任一球半径 R,令 b=o⋅d、q=∥o∥2−R2,交点为 t=−b±b2−q。先求外球的进入与离开位置,将进入位置截到0,再用地表球最近的有效正交点截短区间。相机在大气外时先移动到进入点;视线未穿过外球时没有大气贡献。地表遮挡后的背面空气不参与积分。
单次散射积分
两条光路的透射
从 a 到 b 的透射率为 T(a,b)=exp[−∫abσt(x)ds],RGB 分量各自计算。均匀介质每米消光0.1,十米路径得到 e−1≈0.368;两个五米段各为0.607,相乘得到同一结果。
令 s 指向太阳,d 指向观察射线的远方,取 ν=d⋅s。太阳光沿 −s 传播,散射光沿 −d 回到相机,因此 ν=1 表示看向太阳的前向散射。瑞利相函数为 pR(ν)=3(1+ν2)/(16π)。气溶胶可用 Henyey–Greenstein 近似 pM(ν)=(1−g2)/[4π(1+g2−2gν)3/2],∣g∣<1;g>0 使太阳附近更亮。两者在完整立体角上的积分均为1,g 改变方向分配。
太阳垂直入射辐照度为 E⊙。散射点 x 向太阳的路径若穿过地表,取 T⊙(x)=0,否则积分到外球。局部每单位距离的源项为:
j(x)=E⊙T⊙(x)[βRρR(x)pR(ν)+βMsρM(x)pM(ν)].
沿视线的天空辐亮度是 L=∫0dendT(o,x(s))j(x(s))ds。观察路径和太阳路径的透射各出现一次。只积分观察路径会让被地球遮住太阳的空气仍然发亮,也会丢失日落时较长太阳路径对短波光的过滤。
分段累积
把区间分成小段,在每段中点计算密度、太阳透射与源项,近似它们在本段恒定。累计透射初值为1、辐亮度初值为0。长度 Δs 的一段更新为:
L+=Tprefixjσt1−e−σtΔs,Tprefix∗=e−σtΔs.
每个通道在消光接近零时用极限 Δs,实现可用 -expm1(-sigmaT*ds) 避免小量相减。取标量模型 σt=0.1/米、σs=0.04/米、入射光乘相函数为1,十米散射为 0.4(1−e−1)≈0.25285。分成两段时第一段贡献0.15739,第二段经前缀透射后贡献0.09546,总和不变。真实指数密度只在小段内恒定,增加段数应使结果收敛;十米均匀算例不能证明地平线采样已充足。
透射查找表
坐标与预计算
球对称介质中,到外球的透射只依赖半径 r=∥x∥ 和射线天顶余弦 μ=x^⋅d,因此可存为二维 RGB 表。穿地射线单独判断:μ<0 且 r2(μ2−1)+Rg2≥0。把穿地和不穿地的值直接混合插值会在地平线泄光。
一个向地平线分配更多采样的映射使用:
H=Rt2−Rg2,ρ=r2−Rg2,d=−rμ+r2(μ2−1)+Rt2,
xr=ρ/H,xμ=ρ+H−(Rt−r)d−(Rt−r).
该坐标只覆盖到外球且不穿地的半射线。宽 W、高 B 的表使用 u=[0.5+xμ(W−1)]/W、v=[0.5+xr(B−1)]/B,使参数端点落在首末纹素中心。预计算每个纹素时先还原 ρ=Hxr、r=ρ2+Rg2、d=Rt−r+xμ[ρ+H−(Rt−r)],再求 μ=(H2−ρ2−d2)/(2rd);d 接近零的外球出射点取 μ=1,透射为1。然后沿这条射线按前节积分消光,写入 RGB 透射。
例如取无量纲教学球 Rg=1,Rt=2、地面向上射线 r=1,μ=1,有 ρ=0,d=1,xr=xμ=0,结果存入左下首纹素中心。增加半径或向地平线转动会改变实际路径长度,坐标不能只用“高度、角度归一化”几个字代替。
有限线段与太阳查询
同一条不穿地射线上,点 a,b 到外球的距离满足路径拼接,因此 T(a,b)=Ttop(a,d)/Ttop(b,d)。若向前延伸会穿地,则沿反方向查到外球,取 Ttop(b,−d)/Ttop(a,−d)。两者都要求实际线段位于大气内且没有地表遮挡。极小透射的比值会下溢,浓介质可保存光学深度再做差,或直接对短段积分。
太阳查询在每个散射点计算 r 和 μs=x^⋅s,通过地表遮挡后查这张表,省去内层太阳光路积分。太阳圆盘可按有限角半径采样多条太阳方向再平均;点太阳模型在日落边界给出硬切换,有限圆盘会逐渐被地平线遮住。
散射缓存与运行合成
天空方向缓存
固定相机高度、太阳方向及介质参数后,可把单次散射积分存为天空视图表。一个易实现的坐标约定是以局部竖直轴建立正交基,表横轴存方位角 ϕ=2πu,纵轴存 μ=2v−1,还原方向 d=1−μ2(cosϕe1+sinϕe2)+μeup。每个纹素按完整视线积分,段内向太阳查透射表,得到 RGB 天空辐亮度。运行时把观察方向投到同一基底,取 atan2 得到方位角,再查表。
横轴环绕、纵轴钳制;地表相交与天空射线分支应分开,或者在地平线两侧保留独立采样,避免线性插值混合不同边界。均匀角度表在地平线和太阳光晕处容易欠采样,可增加局部分辨率或使用非线性方向映射。相机升高、太阳转动会改变此表;球对称密度下相同高度的水平平移可在匹配局部基底后复用。
高阶散射
单次散射只接收直射太阳。高阶散射还接收其他方向已经散射过的光。其核心计算是对方向积分。定义 Ln(x,ω) 为从x朝单位方向omega查询到的第n阶入射辐亮度,因而入射光传播方向为−omega,去往相机的方向为−d。下一阶局部源项为 jn+1(x,d)=σs(x)∫4πp((−ω)→(−d))Ln(x,ω)dω,再沿视线按相同透射积分得到 Ln+1。本页HG的余弦为dot(omega,d);omega=d时入射与出射传播方向相同,g>0应得到前向峰,不能改成负点积。含两种散射介质时各用自身系数与相函数后相加;地面反射需作为入射边界加入。
离散参考方法把天顶余弦分为 M 档、方位角分为 K 档,每个方向权重为 4π/(MK),查询上一阶辐亮度并求加权和。每一阶完成后才能供下一阶读取,累积 L1+L2+⋯。完整球对称方向场需要半径、视线天顶余弦、太阳天顶余弦和视线与太阳夹角四个参数;它不能由固定相机的一张二维天空表任意查询。
实时的低维多次散射表通常进一步近似角分布,再缓存高度和太阳天顶角等变量。采用这类压缩时须明确近似的角分布与迭代方式;单纯给二维纹理命名“多次散射”并没有定义高阶光的来源。本页可复现模型覆盖单次散射与透射坐标,高阶递推给出计算定义,完整高阶预计算未在本机执行。
空气透视与资源依赖
远处物体只需要积分到物体深度 d。保存沿视线累计的散射 L(0,d) 和 RGB 透射 T(0,d),按 C=L(0,d)+T(0,d)Csurface 合成。可按屏幕方向和距离切片建立三维缓存:每条方向从近到远执行分段更新,在各深度端点写出累计量。距离切片较稀时近处轮廓会染上错误深度的雾,需用真实物体深度插值并检查遮挡边界;RGB 透射压成单通道会丢失波长相关消光。
资源依赖是介质参数与半径生成透射表,透射表与太阳状态生成单次散射及其后续阶,当前相机状态再生成天空视图和空气透视。只改变相机方向时可复用覆盖全部方向的天空表;改变曝光只影响最后显示。修改密度、吸收或行星尺度则要重建依赖它们的全部缓存,否则画面会同时使用两套不同的大气。
验证方法
运行 python 知识库/examples/mechanism_depth/water_atmosphere/test_reference.py。独立 CPU 模型检查均匀消光、分段散射合成、零消光极限、非穿地射线的透射坐标往返、指数密度球壳积分、9×5透射表生成与纹素节点查询及前向相函数,并包含水面频域检查。此模型没有构建完整天空纹理,也没有执行高阶散射、GPU 着色器或性能捕获。
实际大气实现还需选择垂直、掠射和近地表三条射线,加倍积分段数记录 RGB 收敛;以直接积分对照 LUT 查询,分别统计插值和积分误差。改变相机高度与太阳天顶角,检查地平线分支和缓存更新;把不透明平面放在多个已知距离,验证空气透视仅积到各自深度。地平线漏光、日落跳变和远景染色分别指向几何分支、太阳可见比例与有限深度合成。
相关主题
参考资料