NASA 那张航天飞机 Endeavour 的照片很适合当起点:低地球轨道,黑色太空压在上方,地球边缘露出一层薄薄的大气。橙、蓝、黑挤在一起,像把日落剖开给人看。

Maxime Heckel 这篇长文做的事,就是从这张照片往回推。不是发产品,也不是写科普散文,而是用 WebGL 和 Shader,把天空、日落、行星大气壳拆成一套能在浏览器里实时跑的近似模型。

有意思的地方在这里:很多实时天空还停在贴图、渐变、调色。可可信的天空不是一张蓝色背景。它是太阳光穿过空气分子、气溶胶、臭氧之后,被散射、吸收、衰减留下的结果。

这篇文章到底做了什么

目标很清楚:先在浏览器里实时渲染天空穹顶,再把同一套思路扩展到行星外层的大气壳。

它走的不是“做一张漂亮 skybox”的路线,而是把观察方向、太阳方向、大气密度、光学深度都放进计算里。画面要随着太阳高度、相机位置、行星曲率变化,而不是只在一个角度看起来对。

核心模块可以压缩成这张表:

模块解决的问题画面结果
Raymarching沿视线在大气中分段采样空气不再是背景色,而是有体积的介质
光学深度 + Beer 定律估算光穿过介质后的衰减天空亮度和颜色开始有层次
Rayleigh phase / Rayleigh scattering描述空气分子对短波长光的散射白天蓝天成立
Mie scattering描述尘埃、气溶胶等大颗粒散射太阳附近的雾感、光晕成立
Ozone absorption模拟臭氧对部分波长的吸收黄昏和地平线颜色更厚
Sun transmittance / light marching从采样点朝太阳方向再算透光率日出日落不再只是橙色滤镜

最容易低估的是 light marching。

只沿相机视线算一次,只能知道“光从某个点到眼睛损失了多少”。但日落为什么红、为什么暗、为什么越贴近地平线越像烧起来,还要算太阳光抵达那个点之前,已经穿过了多厚的大气。

少了这一步,夕阳很容易变成一团发白的雾。看着有光,逻辑是空的。

这篇文章也没有把 Shader 近似包装成严格物理模拟。它站在实时图形的现实里:要可信,要可交互,还要跑得动。绝对精确不是目标。帧率预算里的“足够像”,才是目标。

真正有用的是变量分工

这类文章对开发者最有价值的地方,不是给一个“复制就完事”的答案,而是把变量的责任分清。

Rayleigh 管蓝天。短波长更容易被空气分子散射,所以蓝色更多进入视线。

Mie 管浑浊感。尘埃、气溶胶、水汽这类更大的粒子,会让太阳附近出现发白、发亮、发糊的光晕。

臭氧吸收不负责“加颜色”。它负责拿走一部分光。很多色彩深度不是加出来的,是减出来的。

这点和摄影很像。好照片不全靠提亮,有时是阴影压得准。

对前端图形和 WebGL/Three.js 开发者,直接动作是:别一上来就堆后期滤镜。先判断你的天空是不是会被用户交互打穿。

场景更适合的做法现实约束
静态官网背景、短暂停留页面渐变、贴图、预渲染 skybox成本低,维护简单,物理一致性要求不高
可拖动太阳角度的 Web 叙事物理近似 + 少量艺术调参需要控制采样数和 Shader 成本
游戏或实时可视化中的昼夜变化大气模型、LUT、分层优化不能只追求真实,要服从性能预算
行星浏览、教育可视化行星大气壳 + sun transmittance曲率、视角高度、背光面都会暴露假模型

对关心游戏渲染、可视化教育的人,判断也很简单:如果用户只看一张图,贴图能赢;如果用户能转动视角、改变时间、穿过大气边缘,模型迟早要上桌。

限制也要说清。Raymarching 不便宜。采样数、步长、噪声、banding、移动端 GPU 压力,都会找上门。Sebastian Hillaire 那类 LUT 路线,本质就是把昂贵计算提前压缩,用查表换实时性能。

真实世界没有免费午餐。只是把成本藏在运行时、预计算、贴图内存,还是美术调参里。

好看的实时画面,正在从调色走向建模

我更在意的是背后的转向。

早年的很多实时画面,是美术资产的胜利。贴图、渐变、后期滤镜,把结果调到顺眼。现在更硬的路线,是把自然现象拆成能运行的近似方程。

这不是为了炫物理。是因为交互会拆穿假象。

用户不动,假图很好骗。用户一动,太阳高度变了,相机升高了,视角擦过大气边缘了,行星转到背光面了。每一个动作都在逼问模型:你理解的是现象,还是只画了一个像它的壳?

这和早期 3D 图形从手绘光影走向实时光照,有点像。不完全一样,但结构相似:当场景开始可交互,静态美术的权力会下降,模型、近似和预算的权力会上升。

“形而上者谓之道,形而下者谓之器。”放在这里不玄。道是散射、吸收、透射这些规律;器是 Shader、WebGL、raymarching、LUT 和性能预算。只谈规律,跑不动。只谈工具,画面空。

所以这篇文章最该被学习的,不是某一段 Shader 写法,而是一种判断顺序:

  • 先问现象由哪些物理变量决定;
  • 再问哪些变量必须实时算;
  • 再问哪些可以近似、查表、预计算;
  • 最后才轮到调色和风格化。

这对团队也有现实影响。做 Web 交互叙事的人,可以先用简化模型验证方向,不必一开始追求电影级真实。做游戏或实时可视化的人,要更早把美术、图形工程、性能预算放在一张桌上谈。否则天空看着更真实,帧时间先炸。

我不太买账的是那种“物理化就天然高级”的说法。工程里没有天然高级,只有适合不适合。一个静态落地页用复杂大气模型,可能只是浪费。一个可飞行的行星场景还靠蓝色渐变,就会露怯。

判断边界在交互强度。交互越多,物理近似越值钱。画面越静,贴图和美术越划算。

回到 Endeavour 那张照片,它打动人的不是颜色多漂亮,而是大气层薄得吓人。Maxime Heckel 这篇文章把这种“薄”拆成了光路、密度、吸收和散射。浏览器里当然不是真正的大气科学,但它至少让天空不再是一块蓝布。

天空不是蓝色背景。日落也不是橙色滤镜。

它们是光在空气里走过一段路,最后交给 GPU 的一笔账。