GPU Gems 2 · Chapter 16. Accurate Atmospheric Scattering

在 GPU shader 中数值积分 Nishita 大气模型,区分 Rayleigh/Mie scattering、optical depth 与 phase function,并通过专用 camera paths 和 HDR 保持实时与稳定。

学习目标

  • 能从相机 ray 与 atmosphere sphere 的交点确定有效积分区间 A→B
  • 能解释 Rayleigh 与 Mie scattering 的粒子、波长和方向性差异
  • 能把嵌套积分离散成 shader loop,并理解 optical depth、in-scattering 和 surface attenuation 的关系
  • 能按 camera 在大气内/外选择专用 shader path,避免端点和条件分支处理混乱
  • 能用 floating-point buffer 与 exponential exposure 将散射结果映射到可显示范围

逼真的天空可以从一条射线开始。与行星表面和 outer atmosphere 的交点定义了需要计算的线段;只对这段做数值积分,才能同时支持地面、飞行和太空视角。

camera ray → atmosphere segment A…B → samples Pᵢplanetouter atmospherecameravertex / skyP₁P₂P₃P₄AB每个 sample 点贡献“太阳 → P → 相机”的 in-scattering
先确定 ray 穿过大气的有效线段 A→B;相机在大气内时 A 是相机,端点在太空时用球体相交求交点。

1. 确定 A→B 与 sample points

若 camera 在 atmosphere 内,A 就是 camera position;若 camera 在 space,A 是 ray 与 outer sphere 的交点。目标 vertex 同理:在 atmosphere 内时 B 是 vertex,否则用 sphere intersection 得到 B。将 A→B 分成 n 个 sample segments,在中心或规则位置取 P₁…Pₙ,每个 sample 代表太阳光进入、在此散射、再朝相机传播的一小段贡献。

积分可以用 trapezoid-like weighted sum 实现:sample count 提高会提高精度,也会线性增加 shader loop 工作。由于射线长度和 density 变化不均匀,可以把相邻采样间距纳入权重,并在 near horizon 或高密度区域分配更多样本。

2. Rayleigh、Mie 与 phase function

按波长大致呈 1 / λ⁴ 的差异:蓝光到处散开,长路径的太阳光则逐渐失去蓝绿,形成黄橙红的 sunset。

不应和 Rayleigh 共用同一颜色常量;它带来灰白 haze、太阳周围的 halo,也能作为彩虹等粒子效果的基础。两类散射都要按 RGB 和各自 scale height 计算。

two particle models → different appearanceRayleighsmall molecules · λ⁻⁴short wavelengths scatter moreMieaerosols · near-uniform colorforward scatter · sun halo总颜色 = Rayleigh contribution + Mie contribution
两类粒子决定颜色和方向性:Rayleigh 解释蓝天与红霞,Mie 解释雾霾灰和太阳 halo。

控制方向性。Rayleigh 可以用 g = 0 的对称情形;Mie 常用负值表示前向散射。phase function 对角度敏感,放在 fragment 阶段比 per-vertex 计算更不容易出现 tessellation artifacts。

3. optical depth 与 in-scattering

或 optical thickness 是内层积分。sample 点高度 h 的 density 可用 exp(-h / H₀) 表示;H₀ 是 scale height,决定密度下降有多快。沿 sample 到太阳的路径计算一份,到相机的路径再计算一份,两个路径的衰减共同决定 sample 能贡献多少光。

nested integrals → weighted sample accumulationsample Pdensity exp(−h/H₀)optical depthsun path P→Pceye path P→Pacolorphase(g)× exp(−τ)sample count ↑ accuracy ↑ cost;trapezoid-style weighted sum 适合 shader loop
嵌套积分的 GPU 版本:外层沿相机 ray 采样,内层估算样本点到太阳和相机路径上的光学厚度。

把 solar intensity、Rayleigh/Mie scattering constants、phase function 和两条 optical depth 的 exponential attenuation 组合起来。若渲染的是有反射面的 terrain,还要把 surface-emitted/reflected radiance 乘上从表面到相机的 out-scattering attenuation,并加上沿视线的新 in-scattering;天空本身没有表面反射项。

4. 把嵌套积分变成实时 shader

直接实现会产生外层 camera samples × 两个内层 optical-depth samples × 两种散射 × 三个颜色通道的巨大计算量。历史做法使用 2D lookup table;本章的 GPU 路径则把可行的积分与采样放进 shader,通过较小 sample count 和多种 shader variant 维持实时。

相机在 atmosphere 内时,针对“到相机中途结束”的 ray,可以用从 sample 到 atmosphere top 的 optical depth 减去从 camera 到 top 的那一段。若 vertex 在 camera 上方,反转相关 ray 方向,避免 lookup/积分高度落到预期范围之外。把这些边界条件挪到 material/shader 选择阶段,减少一个通用 shader 里难以验证的动态分支。

camera location → specialized scattering shadercamera in atmosphereA = camera positioncamera in spaceA = sphere intersectionshader familyGroundFromAtmosphereSkyFromSpaceSpaceFromAtmosphererenderskygroundphase function放在 fragment 阶段,避免 per-vertex tessellation artifacts
把 camera অবস্থation 的分支移到 shader 选择层:地面、天空和太空对象分别使用适合端点几何的路径。

5. HDR:把 radiance 安全地映射到屏幕

散射方程的结果很容易超出 0..1,直接写入普通 8-bit framebuffer 会剪裁亮部或让整体过暗。使用 floating-point render target 保存 radiance,最后再用 exponential exposure 映射:color_display = 1 - exp(-exposure × color_radiance)像相机光圈一样控制整体亮度,曝光应有合理上下限,否则白天可能被压成月光,月光又被拉爆。

6. 动手实验:样本、视角与曝光

下面的实验把 outer sample count、camera altitude、Mie 的 g 和 HDR exposure 暴露出来。调低 samples 可以看到成本下降但精度风险上升;把 g 推向更负值会增强太阳方向的 haze;改变 exposure 只应改变显示映射,不应改变相对的 RGB 散射比例。

Atmospheric scattering 实验

观察数值采样、相机高度、Mie 相位方向和曝光如何影响天空蓝、太阳 haze 与 shader 预算。

camera altitude 38% · samples 12Rayleigh blue 64%Mie haze 44%HDR tone map = 1 − exp(−exposure × radiance) · 0.57estimated shader work: 29 weighted samples · g = -0.82示意值:真实颜色还取决于 Kr、Km、wavelength 与太阳强度

增加采样能改善积分精度,但 shader loop 预算上升。 g 越接近 -1,Mie 越偏向光源方向;不要设为 ±1。

小结

  • A→B 由 camera ray 与 atmosphere sphere 的交点决定,支持地面到太空的统一视角。
  • Rayleigh 负责短波长偏色,Mie 负责气溶胶与前向 halo,两者需要分开建模。
  • optical depth 描述路径衰减,in-scattering 把各 sample 的太阳光贡献累积到视线。
  • shader variant、合理 sample budget 和 fragment 阶段 phase function 共同把嵌套积分变成实时算法。
  • floating-point buffer 与 HDR exposure 保留散射的动态范围,再稳定映射到显示颜色。

练习

问题 1|积分区间 相机在大气内、顶点在太空时,如何确定散射 ray 的 A 和 B?

问题 2|散射模型 为什么 Rayleigh 和 Mie 要分别计算?phase function 的 g 应该如何使用?

问题 3|实时与 HDR 如何降低嵌套积分成本,同时避免结果在普通 framebuffer 中失真?

名词解释

本章出现的专业名词,用大白话再讲一遍。

camera ray
从相机穿过场景顶点、在大气中产生散射的视线。
Rayleigh scattering
小分子造成、对短波长更强的散射。
Mie scattering
气溶胶造成、波长较均匀且可强前向的散射。
phase function
按夹角与各向异性参数 g 分配散射方向的角度函数。
optical depth
沿光路积分密度与距离,表示大气衰减程度的量。
in-scattering
太阳光在 sample 点散射并沿视线增加的光量。
specialized camera path
按 camera 内外和目标类型选择的独立 shader 处理路径。
HDR exposure
在浮点 radiance 上用可调指数映射到显示范围的处理。

资料与写作方式声明

本章以GPU Gems 2 · Chapter 16. Accurate Atmospheric Scattering权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…