# 星球大气、海洋与气候

本笔记处理从大气密度与散射，到辐射平衡、水循环、云、冰层和气候的连续物理链。星球尺度与相机参数见《星球尺度、视锥与轨道》。

## 大气物理与 Shader 模型

### 模型范围与计算链

对于星球 Shader，大气层通常不需要逐层模拟真实流体，而是建立一个连续的球壳模型：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \fill[fill=cyan!45] (-1.92,0.03) circle (3.45);
  \fill[fill={rgb,255:red,54;green,211;blue,114}] (-1.92,0.03) circle (2.27);
  \draw[draw={rgb,255:red,28;green,62;blue,72}, thick] (-1.92,0.03) circle (3.45);
  \draw[draw={rgb,255:red,28;green,62;blue,72}, thick] (-1.92,0.03) circle (2.27);
  \draw[draw={rgb,255:red,28;green,62;blue,72}, thick, ->] (-1.92,0.03) -- (0.27,0.06);
  \draw[draw={rgb,255:red,28;green,62;blue,72}, thick, ->] (-1.92,0.56) -- (1.53,0.56);
  \draw[draw={rgb,255:red,28;green,62;blue,72}, thick, ->] (0.35,0.07) -- (1.53,0.07);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,28;green,62;blue,72}] at (-0.77,-0.28) {$R_p$};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,28;green,62;blue,72}] at (0.43,1) {$R_a$};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (2.12,-0.36) {$h_{\max}=R_a-R_p$};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,28;green,62;blue,72}] at (-1.92,0.03) {星球};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (-1.92,3.78) {大气顶};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (-1.92,-3.77) {连续球壳大气模型};
\end{tikzpicture}
```
定义：

* $R_p$：星球半径
* $R_a$：大气层外半径
* $\mathbf{x}$：空间位置
* $r=|\mathbf{x}|$：距星球中心距离
* $h=r-R_p$：海拔高度
* $H$：大气尺度高度
* $\rho(h)$：高度 $h$ 处的大气密度
* $P(h)$：气压
* $T(h)$：温度
* $g(h)$：重力加速度

其中：

$$R_a=R_p+h_{\max}$$


### 大气结构与密度

#### 几何高度、重力与静力平衡

这一组关系从球面几何开始：先定义采样点高度，再计算随半径变化的重力，最后由静力平衡把重力、密度和压力连接起来。

对于世界空间中的一点：

$$r=|\mathbf{x}-\mathbf{C}|$$

其中 $\mathbf{C}$ 是星球中心。

高度：

$$h=r-R_p$$

Shader 中通常写成：

```hlsl
float height = length(worldPos - planetCenter) - planetRadius;
```

归一化高度：

$$h_n= \frac{h}{R_a-R_p}$$

其中：

$$0\le h_n\le1$$

牛顿引力：

$$g(r)=\frac{GM}{r^2}$$

星球表面：

$$g_0=\frac{GM}{R_p^2}$$

因此：

$$g(h) = g_0 \left( \frac{R_p}{R_p+h} \right)^2$$

当大气厚度远小于星球半径：

$$h\ll R_p$$

可以近似：

$$g(h)\approx g_0$$

对于地球：

$$g_0\approx9.81\ \mathrm{m/s^2}$$

实时 Shader 中通常直接使用常数 $g_0$。

稳定大气满足：

$$\frac{dP}{dh} = -\rho g$$

含义是：

高度增加时，气压下降，其下降速度取决于上方空气的重量。
理想气体方程：

$$P=\rho R_sT$$

其中：

* $R_s$：气体比气体常数
* $T$：绝对温度

于是：

$$\rho= \frac{P}{R_sT}$$

代入静力平衡：

$$\frac{dP}{dh} = -\frac{Pg}{R_sT}$$

即：

$$\frac{dP}{P} = -\frac{g}{R_sT}dh$$


#### 指数大气、尺度高度与密度实现

在等温、组分不变且重力近似常量时，静力平衡可以积分为指数密度；尺度高度给出密度下降的实际长度，Shader 只是对这条物理关系的离散采样。

如果近似：

$$g=\text{constant}$$

$$T=\text{constant}$$

积分得到：

$$P(h) = P_0 e^{-h/H}$$

其中尺度高度：

$$\boxed{ H= \frac{R_sT}{g} }$$

因此密度同样近似：

$$\boxed{ \rho(h) = \rho_0 e^{-h/H} }$$

这是实时大气 Shader 中最重要的基础公式之一。

尺度高度 $H$ 表示密度下降到原来的：

$$\frac1e \approx0.368$$

所需要增加的高度。

对于单种分子：

$$H= \frac{k_BT}{mg}$$

其中：

* $k_B$：玻尔兹曼常数
* $m$：单个分子质量

对于混合气体：

$$H= \frac{R_uT}{Mg}$$

其中：

* $R_u$：通用气体常数
* $M$：平均摩尔质量

地球低层大气尺度高度大约：

$$H\approx8\ \mathrm{km}$$

例如：

$$\rho(8\mathrm{km}) \approx 0.37\rho_0$$

$$\rho(16\mathrm{km}) \approx 0.14\rho_0$$

$$\rho(24\mathrm{km}) \approx 0.05\rho_0$$

最简单的大气密度函数：

$$D(h)=e^{-h/H}$$

HLSL：

```hlsl
float atmosphereDensity(float height, float scaleHeight)
{
    return exp(-max(height, 0.0) / scaleHeight);
}
```

对于：

$$h<0$$

意味着进入星球内部，一般直接截断。


#### 多组分尺度高度与大气层边界

真实大气渲染通常不会只使用一种密度。

定义：

$$\rho_R(h) = e^{-h/H_R}$$

$$\rho_M(h) = e^{-h/H_M}$$

其中：

* $H_R$：Rayleigh 分子尺度高度
* $H_M$：Mie 气溶胶尺度高度

典型地球模型：

$$H_R\approx8\ \mathrm{km}$$

$$H_M\approx1.2\ \mathrm{km}$$

因此气溶胶更加集中在地表附近。

```hlsl
float densityRayleigh(float h)
{
    return exp(-h / rayleighScaleHeight);
}

float densityMie(float h)
{
    return exp(-h / mieScaleHeight);
}
```

真实大气：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \fill[fill=cyan!45] (-1.64,-0.43) circle (3.31);
  \fill[fill={rgb,255:red,54;green,211;blue,138}] (-1.64,-0.43) circle (1.26);
  \draw[draw=cyan, thick] (-1.64,-0.43) circle (3.31);
  \draw[draw={rgb,255:red,15;green,16;blue,16}, thick, densely dashed] (-1.64,-0.43) circle (2.55);
  \draw[draw={rgb,255:red,48;green,53;blue,54}, thick, densely dashed] (-1.64,-0.43) circle (1.86);
  \draw[draw=cyan, thick] (-1.64,-0.43) circle (1.26);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,73;green,108;blue,111}] at (-1.64,-0.43) {星球};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text={rgb,255:red,63;green,106;blue,110}] at (-0.78,0.06) {对流层};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text={rgb,255:red,63;green,79;blue,80}] at (-0.05,-1.06) {平流层};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text={rgb,255:red,64;green,87;blue,89}] at (0.32,-2.08) {高层大气};
  \draw[draw=cyan!85, thick, ->] (-1.24,-1.6) -- (-0.39,-3.46);
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=white] at (-0.1,-3.81) {$h_{\max}$};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (-0.46,3.82) {离散分层：便于渲染};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (-0.56,3.01) {连续模型：$\rho(h)=\rho_0e^{-h/H}$};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```
Shader 通常简化成：

$$\rho(h)=\rho_0e^{-h/H}$$

也就是说：

真实大气可分为对流层、平流层、中间层、热层和散逸层；实时渲染则通常把它近似为连续的指数密度球壳。

各层仍然可以用于控制：

温度、云层高度、臭氧、极光、电离层、夜光层。

### 散射与相函数

#### Rayleigh 散射、系数与相函数

Rayleigh 部分需要同时说明波长依赖、单位长度散射系数和角分布；只给蓝色系数而没有相函数，无法解释天空不同方向的亮度。

空气中的分子尺寸远小于可见光波长时，会产生 Rayleigh 散射。

Rayleigh 散射强度近似：

$$I_R \propto \frac1{\lambda^4}$$

因此：

$$\lambda_B<\lambda_G<\lambda_R$$

导致：

$$\beta_B>\beta_G>\beta_R$$

蓝光比红光更容易被散射。

因此：

白天天空偏蓝、日落时太阳偏红。

可以写成：

$$\boldsymbol{\beta}_R = \begin{bmatrix} \beta_{R,r}\\ \beta_{R,g}\\ \beta_{R,b} \end{bmatrix}$$

例如：

```hlsl
float3 betaRayleigh;
```

其本质满足：

$$\beta_R(\lambda) \propto \lambda^{-4}$$

局部散射系数：

$$\beta_R(h) = \rho_R(h)\beta_{R0}$$

散射方向并不是完全均匀的。

定义：

$$\mu=\cos\theta$$

其中：

$$\mu= \mathbf{V}\cdot\mathbf{L}$$

Rayleigh 相函数：

$$\boxed{ P_R(\theta) = \frac{3}{16\pi} (1+\cos^2\theta) }$$

即：

$$P_R(\mu) = \frac{3}{16\pi} (1+\mu^2)$$

HLSL：

```hlsl
float phaseRayleigh(float cosTheta)
{
    return 3.0 / (16.0 * PI)
         * (1.0 + cosTheta * cosTheta);
}
```


#### Mie 散射与 Henyey–Greenstein 相函数

Mie 散射主要由：

灰尘、水滴、气溶胶、烟尘。

等尺寸接近或大于光波长的粒子产生。

它对波长的依赖远弱于 Rayleigh 散射。

因此近似表现为：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \fill[fill={rgb,255:red,65;green,147;blue,210}] (0.25,-0.15) circle (1.08);
  \draw[draw=cyan, thick] (0.25,-0.15) circle (1.08);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,41;green,46;blue,46}] at (0.25,-0.15) {大气};
  \draw[draw=white, thick, ->] (-2.25,0.95) -- (-0.8,0.3);
  \draw[draw=white, thick, ->] (-2.35,0.2) -- (-0.87,0);
  \draw[draw=white, thick, ->] (-2.35,-0.55) -- (-0.87,-0.33);
  \draw[draw=white, thick, ->] (-2.15,-1.3) -- (-0.73,-0.65);
  \draw[draw=white, thick, ->] (-0.38,0.4) -- (2.17,1.3);
  \draw[draw=white, thick, ->] (-0.3,-0.6) -- (2.25,-1);
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (2.25,1.3) {短波散射（Rayleigh）};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (2.35,-1) {颗粒散射（Mie）};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (1.7,0) {$I\propto\lambda^{-4}$：蓝光更强};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```


Mie 通常使用 Henyey-Greenstein 相函数：

$$P_M(\mu) = \frac{1-g^2} { 4\pi (1+g^2-2g\mu)^{3/2} }$$

其中：

$$-1<g<1$$

$g$ 控制散射方向：


地球大气 Mie 通常：

$$g\approx0.7\sim0.9$$

HLSL：

```hlsl
float phaseMie(float cosTheta, float g)
{
    float g2 = g * g;

    return
        (1.0 - g2) /
        (
            4.0 * PI *
            pow(
                1.0 + g2 - 2.0 * g * cosTheta,
                1.5
            )
        );
}
```


### 消光、光学深度与积分

#### 消光、光学深度与 Beer–Lambert 定律

局部消光系数描述每单位长度损失多少光，光学深度是它沿路径的积分，Beer–Lambert 定律再把光学深度转换为透射率。三者量纲不同，不能混用。

光穿过大气时会因为：

散射、吸收。

而衰减。

定义总消光系数：

$$\beta_e = \beta_s+\beta_a$$

其中：

* $\beta_s$：散射系数
* $\beta_a$：吸收系数

进一步：

$$\beta_e = \beta_R + \beta_M + \beta_O +\cdots$$

其中 $\beta_O$ 可以表示臭氧吸收。

光经过距离 $s$ 后：

$$I(s) = I_0e^{-\tau}$$

其中 $\tau$ 为光学深度。

如果介质均匀：

$$\tau=\beta_es$$

所以：

$$I(s) = I_0 e^{-\beta_es}$$

定义透射率：

$$\boxed{ T=e^{-\tau} }$$

由于密度随高度变化：

$$\beta_e=\beta_e(\mathbf{x})$$

所以：

$$\boxed{ \tau(a,b) = \int_a^b \beta_e(\mathbf{x}(s)) ds }$$

其中射线：

$$\mathbf{x}(s) = \mathbf{o} +s\mathbf{d}$$

因此透射率：

$$\boxed{ T(a,b) = \exp \left[ -\int_a^b \beta_e(\mathbf{x}(s))ds \right] }$$

这是大气 Shader 的核心积分之一。

假设：

$$\rho(h) = e^{-h/H}$$

定义：

$$D(a,b) = \int_a^b \rho(h(s))ds$$

那么：

$$\tau = \beta D$$

多种散射介质：

$$\tau = \beta_R D_R + \beta_M D_M + \beta_O D_O$$

最终：

$$T=e^{-\tau}$$

RGB 形式：

$$\boxed{ \mathbf{T} = e^{-\boldsymbol{\tau}} }$$

指数对 RGB 分量分别计算。


#### 数值积分与单次散射

实现时分别沿观察路径和太阳路径积分。采样点数、步长、边界求交和提前终止共同决定误差，单纯增加采样数并不能修复错误的路径范围。

实时 Shader 中通常使用离散积分。

对于路径长度 $L$，采样 $N$ 次：

$$\Delta s=\frac{L}{N}$$

光学深度：

$$D \approx \sum_{i=0}^{N-1} \rho(h_i)\Delta s$$

更准确可以用中点：

$$s_i= \left( i+\frac12 \right)\Delta s$$

$$\mathbf{x}_i = \mathbf{o} +s_i\mathbf{d}$$

$$h_i = |\mathbf{x}_i|-R_p$$

观察者看到的大气光来自太阳光在路径上的散射。

对于视线：

$$\mathbf{x}(s) = \mathbf{C} +s\mathbf{V}$$

某一个采样点 $\mathbf{x}$ 的入射太阳光：

$$L_\odot T_{\odot}(\mathbf{x})$$

其中：

$$T_{\odot} = T(\mathbf{x},\text{Sun})$$

然后在该点发生散射。

最终还需要乘采样点到摄像机的透射率：

$$T_V = T(\text{Camera},\mathbf{x})$$

因此：

$$dL = L_\odot T_{\odot} T_V \beta_s P(\theta) ds$$

积分：

$$\boxed{ L = \int L_\odot T_{\odot}(s) T_V(s) \beta_s(s) P(\theta) ds }$$

这就是单次大气散射方程的核心形式。

展开：

$$L = L_\odot \int T_{\odot} T_V \left[ \beta_R\rho_RP_R + \beta_M\rho_MP_M \right] ds$$

其中：

$$\beta_R\rho_RP_R$$

产生天空的大范围蓝色散射。

而：

$$\beta_M\rho_MP_M$$

产生太阳附近强烈的白色前向散射。

单次散射可以近似：

$$L \approx \sum_i T_{view,i} T_{sun,i} \left[ \rho_{R,i}\beta_RP_R + \rho_{M,i}\beta_MP_M \right] \Delta s$$

结构可写成：

```hlsl
for (int i = 0; i < VIEW_SAMPLE_COUNT; ++i)
{
    float3 samplePos = rayOrigin + rayDir * sampleDistance;

    float height =
        length(samplePos - planetCenter)
        - planetRadius;

    float densityR =
        exp(-height / rayleighScaleHeight);

    float densityM =
        exp(-height / mieScaleHeight);

    // Camera -> sample
    float3 transmittanceView = ...;

    // sample -> Sun
    float3 transmittanceSun = ...;

    scattering +=
        transmittanceView *
        transmittanceSun *
        (
            betaRayleigh *
            densityR *
            phaseR
            +
            betaMie *
            densityM *
            phaseM
        )
        * stepSize;
}
```


### 观测几何与光学现象

#### 射线求交、地平线光程与边缘增强

因为星球和大气都是球体，大气渲染首先需要求射线与球体交点。

射线：

$$\mathbf{P}(t) = \mathbf{O} +t\mathbf{D}$$

球：

$$|\mathbf{P}-\mathbf{C}|^2=R^2$$

代入：

$$|\mathbf{O}+t\mathbf{D}-\mathbf{C}|^2 = R^2$$

令：

$$\mathbf{L} = \mathbf{O}-\mathbf{C}$$

得到：

$$t^2 + 2(\mathbf{L}\cdot\mathbf{D})t + (|\mathbf{L}|^2-R^2) = 0$$

假设：

$$|\mathbf{D}|=1$$

定义：

$$b=\mathbf{L}\cdot\mathbf{D}$$

$$c=|\mathbf{L}|^2-R^2$$

判别式：

$$\Delta=b^2-c$$

若：

$$\Delta<0$$

没有交点。

否则：

$$\boxed{ t_0=-b-\sqrt{\Delta} }$$

$$\boxed{ t_1=-b+\sqrt{\Delta} }$$

HLSL：

```hlsl
float2 raySphere(
    float3 origin,
    float3 dir,
    float3 center,
    float radius)
{
    float3 oc = origin - center;

    float b = dot(oc, dir);
    float c = dot(oc, oc) - radius * radius;

    float d = b * b - c;

    if (d < 0.0)
        return float2(-1.0, -1.0);

    float s = sqrt(d);

    return float2(
        -b - s,
        -b + s
    );
}
```

这个函数可以同时用于：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \fill[fill={rgb,255:red,41;green,143;blue,148}] (-1.65,-0.17) circle (1.35);
  \draw[draw=cyan, thick] (-1.65,-0.17) circle (1.35);
  \draw[draw=cyan!85, thick, densely dashed] (-1.65,-0.17) -- (-1.65,1.18);
  \draw[draw=cyan!85, thick] (-1.65,1.18) -- (1.9,1.18);
  \draw[draw={rgb,255:red,58;green,64;blue,65}, thick] (-1.65,-1.52) -- (-1.65,1.18);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (-1.65,-0.17) {星球};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (1.92,1.55) {观察者};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (-1.24,1.57) {切线：地平线};
  \node[anchor=east, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (-2.09,0.37) {$2R$};
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (-0.03,0.42) {视线与球面相交：$\mathrm{raySphere}$};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```


从星球表面向上看：


接近地平线方向时，光穿过的大气路径明显增长。

因此：

$$\tau_{\text{horizon}} \gg \tau_{\text{zenith}}$$

导致：

地平线颜色更浓、蓝光经过更强的 Rayleigh 散射、太阳接近地平线时直射光逐渐变红、大气边缘产生明显的边缘辉光。

因此真实大气边缘并不需要简单：

```hlsl
pow(1.0 - dot(N, V), power)
```

人为制造。

球形大气的光学深度本身就会自然产生 limb glow。


#### 日落颜色、臭氧吸收与波段差异

Rayleigh：

$$\beta_R(\lambda) \propto \frac1{\lambda^4}$$

当太阳接近地平线：

$$L_{\text{path}}\uparrow$$

导致：

$$\tau_B \gg \tau_R$$

因此透射率：

$$T_B=e^{-\tau_B}$$

迅速下降。

而：

$$T_R=e^{-\tau_R}$$

仍然较大。

所以太阳直射光：

$$L_{sun} = L_0 \begin{bmatrix} T_R\\ T_G\\ T_B \end{bmatrix}$$

逐渐变成：

白 → 黄 → 橙 → 红。


臭氧主要分布于平流层：

$$h\approx15\sim35\ \mathrm{km}$$

不能简单使用地面最大密度的指数函数。

可以构造一个高度分布函数：

$$\rho_O(h) = \exp \left[ -\frac{(h-h_O)^2}{2\sigma_O^2} \right]$$

其中：

* $h_O$：臭氧层中心高度
* $\sigma_O$：层宽

例如：

$$h_O\approx25\ \mathrm{km}$$

臭氧吸收：

$$\tau_O = \int \beta_O \rho_O(h) ds$$

总透射率：

$$\mathbf{T} = \exp \left[ - ( \boldsymbol{\tau}_R+ \boldsymbol{\tau}_M+ \boldsymbol{\tau}_O ) \right]$$

臭氧对于真实的：

黄昏颜色、天顶蓝色、长距离大气颜色。

有明显影响。


### 高层大气与大气保持

#### 温度分层、电离层与散逸层

如果还要表现真实大气结构，可以定义：

$$T=T(h)$$

简单分段模型：

$$T(h)= \begin{cases} T_0-L_1h, &0<h<h_1 \\ T_1+L_2(h-h_1), &h_1<h<h_2 \\ T_2-L_3(h-h_2), &h_2<h<h_3 \\ T_3+L_4(h-h_3), &h>h_3 \end{cases}$$

对应：

温度随高度并非单调变化：对流层中下降，平流层中上升，中间层中再次下降，进入热层后又上升。

如果密度需要更真实，则：

$$\rho(h) = \frac{P(h)}{R_sT(h)}$$

并根据：

$$\frac{dP}{dh} = -\rho g$$

数值计算。

但实时渲染通常没有必要这么复杂。

电离层并不是普通可见光大气散射的主要来源。

其主要物理变量为：

$$n_e$$

即电子数密度。

电子密度随高度：

$$n_e=n_e(h)$$

并受到太阳辐射影响。

最基本的电离过程：

$$A+h\nu \rightarrow A^++e^-$$

电子与离子重新结合：

$$A^++e^- \rightarrow A$$

简单平衡：

$$q = \alpha n_e^2$$

因此：

$$n_e = \sqrt{\frac q\alpha}$$

其中：

* $q$：电离产生率
* $\alpha$：复合系数

星球 Shader 中，电离层更适合用于：

极光、夜侧辉光、高层大气 glow、科幻能量层。

而不是基础天空颜色。

逃逸速度：

$$\boxed{ v_e= \sqrt{\frac{2GM}{r}} }$$

如果某些高层大气粒子的速度达到：

$$v>v_e$$

则可能逃离星球。

热运动的典型速度：

$$v_{rms} = \sqrt{\frac{3k_BT}{m}}$$

因此：

温度越高、分子质量越小、星球重力越弱。

大气越容易逃逸。

这解释了为什么：

因此，小型星球或卫星通常难以长期保留厚大气。

#### 热逃逸与大气长期保持

核心参数：

$$\lambda_J = \frac{GMm} {k_BTr}$$

也称 Jeans 参数。

等价地：

$$\lambda_J = \frac{v_e^2} {2v_{thermal}^2}$$

如果：

$$\lambda_J\gg1$$

粒子被强烈束缚。

如果：

$$\lambda_J$$

较小，则大气更容易发生热逃逸。

因此程序化星球可以利用：

星球质量、星球半径、大气温度和平均分子质量。

自动推导大气厚度趋势。

星球表面重力：

$$\boxed{ g= \frac{GM}{R_p^2} }$$

尺度高度：

$$\boxed{ H= \frac{k_BT}{mg} }$$

代入：

$$H = \frac{k_BT R_p^2} {mGM}$$

所以：

$$H \propto \frac{TR_p^2} {mM}$$

这给程序化星球一个非常重要的关系：

由 $H=k_BT/(mg)$ 可直接看出：温度升高会增大尺度高度，而表面重力或分子质量增大都会减小尺度高度。

因此不需要完全手工指定 atmosphereHeight。


### Shader 参数与组合

#### 统一参数、最小物理链与 Shader 组合

一个基础星球大气可以只需要：

```hlsl
struct AtmosphereParams
{
    float3 planetCenter;

    float planetRadius;
    float atmosphereRadius;

    float rayleighScaleHeight;
    float mieScaleHeight;

    float3 betaRayleigh;
    float3 betaMie;

    float mieG;

    float3 betaOzone;
    float ozoneHeight;
    float ozoneWidth;

    float sunIntensity;
};
```

其中：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-6,0.2) {空间位置};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-3,0.2) {高度与密度};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (0,0.2) {光学深度};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (3,0.2) {散射相函数};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node5) at (6,0.2) {天空颜色};
  \draw[cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[cyan!85, thick, ->] (node4.east) -- (node5.west);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (-3,-0.56) {$\rho(h)=\rho_0e^{-h/H}$};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (0,-0.56) {Beer--Lambert};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (3,-0.56) {Rayleigh + Mie};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```


星球 Shader 的核心计算可整理为一张数据流表，而不是把公式竖直串联：

| 阶段 | 计算 | 输出及用途 |
| --- | --- | --- |
| 几何 | $h=\lVert\mathbf x\rVert-R_p$ | 当前采样点高度，决定是否位于地表与大气之间 |
| 密度 | $\rho_i(h)=\rho_{i,0}e^{-h/H_i}$ | Rayleigh、Mie 与吸收组分各自的局部密度 |
| 光学深度 | $\tau=\int\sum_i\beta_i\rho_i(h)\,ds$ | 观察路径或太阳路径上的累计消光 |
| 透射率 | $T=\exp(-\tau)$ | 光线穿过该段大气后剩余的比例 |
| 局部散射 | $dL=L_\odot T_{sun}T_{view}\beta\rho P(\theta)\,ds$ | 当前采样段送入相机的辐亮度 |
| 路径积分 | $L=\int dL$ | 像素最终获得的大气散射亮度 |

计算时，每个视线采样点先求高度与各组分密度，再分别积分太阳方向和观察方向的光学深度。只有同时乘上 $T_{sun}$ 与 $T_{view}$，地平线、背光面和日落颜色才会自然出现。多重散射属于后续修正项，不能用提高太阳强度替代。

最终渲染应明确分为固体地表与海洋、大气散射、云与天气、高层发光以及最终光照合成五个层级。


基础大气应优先实现球壳求交、高度与密度、Rayleigh/Mie 系数、双路径光学深度、相函数和辐亮度积分；臭氧、多重散射、云及高层效果在主链正确后再加入。


完成这些环节后，才能得到物理意义较完整的**球形行星大气 Shader**。


## 海洋、水循环、冰层与气候

### 模型范围与计算链

程序化表面环境以恒星光度、轨道距离、星球重力、大气质量和总水量为输入，先求辐射与温度，再求水相、云、冰和环流，最终形成可供地表与 Shader 使用的气候状态：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-6.4,0.6) {恒星辐射};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-3.2,0.6) {表面温度};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (0,0.6) {蒸发与水汽};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (3.2,0.6) {云与降水};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node5) at (6.4,0.6) {反照率 / 温室效应};
  \draw[cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[cyan!85, thick, ->] (node4.east) -- (node5.west);
  \draw[cyan!85, thick] (6.4,0.1) -- (6.4,-0.6);
  \draw[cyan!85, thick] (6.4,-0.6) -- (-6.4,-0.6);
  \draw[cyan!85, thick, ->] (-6.4,-0.6) -- (-6.4,0.1);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (0,-0.95) {水循环与气候反馈闭环};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```

### 辐射收支与表面温度

#### 恒星通量、全球平均与反照率

气候能量输入依次经历轨道距离反平方衰减、球面平均和反照率扣除；每一步代表不同几何或材料作用。

星球距离恒星为 $d$。

恒星光度：

$$L_\star$$

星球接收到的辐射通量：

$$\boxed{ S= \frac{L_\star}{4\pi d^2} }$$

这就是局部的恒星常数。

对于地球：

$$S_\oplus \approx 1361\ \mathrm{W/m^2}$$

星球截获恒星光的面积：

$$\pi R_p^2$$

但热量平均分布到整个球面：

$$4\pi R_p^2$$

因此全球平均入射通量：

$$\boxed{ F_{in} = \frac{S}{4} }$$

星球不会吸收全部恒星辐射。

定义 Bond 反照率：

$$A$$

吸收比例：

$$1-A$$

因此：

$$\boxed{ F_{abs} = \frac{S(1-A)}{4} }$$

反照率受到：

云、冰雪、海洋、沙漠、植被、大气。

共同影响。


#### 平衡温度、表面温度与局部照度

黑体辐射：

$$F_{out} = \sigma T^4$$

其中：

$$\sigma = 5.670374419\times10^{-8} \ \mathrm{W\,m^{-2}\,K^{-4}}$$

平衡：

$$F_{abs}=F_{out}$$

得到：

$$\boxed{ T_{eq} = \left( \frac{ S(1-A) }{ 4\sigma } \right)^{1/4} }$$

这是没有温室效应时的星球平均有效温度。

有大气时：

$$T_s>T_{eq}$$

可以粗略写成：

$$\boxed{ T_s = T_{eq} + \Delta T_{greenhouse} }$$

地球：

$$T_{eq} \approx255\ \mathrm{K}$$

实际全球平均地表温度：

$$T_s \approx288\ \mathrm{K}$$

因此温室增温约：

$$33\ \mathrm{K}$$

对于地表法线 $\mathbf N$ 和太阳方向 $\mathbf L$：

$$\mu= \max(0,\mathbf N\cdot\mathbf L)$$

局部入射：

$$\boxed{ F_{local} = S\mu }$$

Shader：

```hlsl
float mu = saturate(dot(normal, sunDir));
float irradiance = stellarFlux * mu;
```


### 海洋、水相与海平面

#### 水量、覆盖率与海平面

定义总水量：

$$M_w$$

如果知道表面水的平均等效深度：

$$h_w$$

则：

$$V_w = 4\pi R_p^2h_w$$

水质量：

$$\boxed{ M_w = 4\pi R_p^2h_w\rho_w }$$

其中：

$$\rho_w \approx1000\ \mathrm{kg/m^3}$$

程序化星球可以使用：

使用 `waterMassFraction` 控制海洋总规模。
控制海洋规模。

如果有高度场：

$$H(\theta,\phi)$$

海平面高度：

$$H_{sea}$$

则：

$$H<H_{sea}$$

的位置被海洋覆盖。

Shader 中：

```hlsl
float oceanMask =
    step(terrainHeight, seaLevel);
```

平滑版本：

```hlsl
float oceanMask =
    1.0 -
    smoothstep(
        seaLevel - shoreWidth,
        seaLevel + shoreWidth,
        terrainHeight
    );
```


#### 水的相态、相图与压力边界

水主要以冰、液态水和水蒸气三种相态存在。

最简单可以通过温度判断。

在近似标准压力下：

$$T<273.15\ \mathrm K$$

倾向于冰。

$$273.15<T<373.15\ \mathrm K$$

倾向于液态。

$$T>373.15\ \mathrm K$$

倾向于气态。

但真实相态还强烈依赖压力。

水的物态由：

$$P,T$$

共同决定。

因此更正确的是：

$$Phase = Phase(P,T)$$

程序化星球可以至少保留三个重要边界：

Melting Curve、Boiling Curve、Sublimation Curve。


沸腾条件：

$$P_{vapor}(T) = P_{atm}$$

大气压越低：

$$T_{boil}\downarrow$$

大气压越高：

$$T_{boil}\uparrow$$

因此不能固定使用：

$$100^\circ C$$

作为所有星球的沸点。


### 水汽、云与水循环

#### 饱和水汽、相对湿度与云形成

水汽部分先由 Clausius–Clapeyron 关系求饱和上限，再用实际水汽与饱和值之比得到相对湿度；抬升冷却使空气达到饱和后才形成云。

饱和蒸气压变化：

$$\boxed{ \frac{d\ln P_{sat}}{dT} = \frac{L_v} {R_vT^2} }$$

积分近似：

$$\boxed{ P_{sat}(T) = P_0 \exp \left[ -\frac{L_v}{R_v} \left( \frac1T-\frac1{T_0} \right) \right] }$$

其中：

* $L_v$：汽化潜热
* $R_v$：水蒸气气体常数

这是湿度和云模型中最重要的基础方程。

理想气体：

$$\rho_v = \frac{P_v}{R_vT}$$

因此饱和水汽密度：

$$\boxed{ \rho_{sat} = \frac{P_{sat}(T)} {R_vT} }$$

温度升高时：

$$P_{sat}\uparrow$$

非常迅速。

所以暖空气能够容纳更多水汽。

定义：

$$RH = \frac{P_v}{P_{sat}}$$

或者：

$$RH = \frac{\rho_v}{\rho_{sat}}$$

通常写成：

$$\boxed{ RH= \operatorname{clamp} \left( \frac{\rho_v}{\rho_{sat}}, 0,1 \right) }$$

当：

$$RH\approx1$$

空气接近饱和。

基本条件：

$$RH\ge1$$

此时多余的水汽凝结：

$$Water\ Vapor \rightarrow Liquid\ Droplets$$

或者低温下：

$$Water\ Vapor \rightarrow Ice\ Crystals$$

程序化云密度可以写成：

$$\boxed{ \rho_c = \max( \rho_v-\rho_{sat}, 0 ) }$$

```hlsl
float saturation =
    saturationDensity(temperature);

float cloudDensity =
    max(
        vaporDensity - saturation,
        0.0
    );
```

实际渲染再乘：

高度分布、3D Noise、Weather Map、风场。

#### 蒸发、凝结、降水与质量守恒

水循环必须维护海洋、陆地水、冰、大气水汽和云水五类储库。蒸发、凝结和降水只是储库间通量，不能在每一步凭空创建或删除水。

蒸发率粗略可以写成：

$$\boxed{ E \propto (1-RH) f(T) f(wind) }$$

更简单：

$$E = k_E (1-RH) \max(T-T_f,0)$$

其中：

$$T_f$$

为冻结温度。

海洋表面：

高温提高饱和水汽压，低湿度扩大水汽压差，强风带走近地表水汽，三者共同增强蒸发。


如果：

$$\rho_v>\rho_{sat}$$

凝结量：

$$\boxed{ C = k_C (\rho_v-\rho_{sat}) }$$

于是：

$$\frac{d\rho_v}{dt} = E-C$$

当云水含量超过阈值：

$$\rho_c>\rho_{crit}$$

可以产生降水：

$$\boxed{ R = k_R \max( \rho_c-\rho_{crit}, 0 ) }$$

其中 $R$ 可以表示降雨率。

总水量：

$$M_{water} = M_{ocean} + M_{ice} + M_{vapor} + M_{cloud} + M_{ground}$$

理想情况下：

$$\boxed{ \frac{dM_{water}}{dt}=0 }$$

只是不同储库之间转移。

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-6.4,0.6) {海洋};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-3.2,0.6) {蒸发 / 水汽};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (0,0.6) {凝结成云};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (3.2,0.6) {降水};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node5) at (6.4,0.6) {地表径流};
  \draw[cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[cyan!85, thick, ->] (node4.east) -- (node5.west);
  \draw[cyan!85, thick] (6.4,0.1) -- (6.4,-0.6);
  \draw[cyan!85, thick] (6.4,-0.6) -- (-6.4,-0.6);
  \draw[cyan!85, thick, ->] (-6.4,-0.6) -- (-6.4,0.1);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (0,-0.95) {水循环};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```
冰层还会通过：

冻结、融化、升华和凝华。

参与循环。


### 冰雪与海洋热容量

#### 冻结、融化与冰雪反照率反馈

如果：

$$T<T_f(P)$$

液态水可能冻结。

冰量增长：

$$\boxed{ \frac{dM_i}{dt} = F_{freeze} - F_{melt} }$$

简单冻结率：

$$F_{freeze} = k_f \max( T_f-T, 0 )$$

融化率：

$$\boxed{ F_{melt} = k_m \max( T-T_f, 0 ) }$$

如果加入恒星照度：

$$F_{melt} \propto S\mu(1-A_i)$$

冰雪反照率通常较高。

因此：

$$Ice\uparrow$$

导致：

$$A\uparrow$$

然后：

$$F_{abs}\downarrow$$

导致：

$$T\downarrow$$

进一步：

$$Ice\uparrow$$

形成正反馈：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \begin{scope}
    \clip (-12,-7.6) rectangle (12,7.6);
  \end{scope}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-4.8,0.6) {降温};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-1.6,0.6) {冰层增加};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (1.6,0.6) {反照率增加};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (4.8,0.6) {吸收减少};
  \draw[cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[cyan!85, thick] (4.8,0.1) -- (4.8,-0.6);
  \draw[cyan!85, thick] (4.8,-0.6) -- (-4.8,-0.6);
  \draw[cyan!85, thick, ->] (-4.8,-0.6) -- (-4.8,0.1);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (0,-0.95) {正反馈：冰--反照率};
  \pgfresetboundingbox
  \path[use as bounding box] (-12,-7.6) rectangle (12,7.6);
\end{tikzpicture}
```
这一闭环称为冰—反照率反馈。


#### 海洋热容量与陆海温差

海洋一般反照率较低。

但具有明显方向性。

太阳接近地平线时：

$$A_{ocean}\uparrow$$

因为 Fresnel 反射增强。

可以使用：

$$F_0= \left( \frac{n_1-n_2}{n_1+n_2} \right)^2$$

Schlick 近似：

$$\boxed{ F= F_0+ (1-F_0)(1-\cos\theta)^5 }$$

非常适合海洋 Shader。

水的比热很高：

$$c_{p,w} \approx 4180\ \mathrm{J/(kg\,K)}$$

因此海洋具有巨大热惯性。

局部温度变化：

$$\boxed{ C \frac{dT}{dt} = F_{in}-F_{out} }$$

其中：

$$C = \rho_w c_pw h$$

因此海洋星球昼夜温差通常较小。

陆地热容量：

$$C_{land}$$

通常明显小于：

$$C_{ocean}$$

所以：

陆地、升温快、降温快、海洋、升温慢、降温慢。

这也是大气环流和季风的重要来源。


### 温室、云与对流

#### 温室、灰色大气与红外光学深度

温室近似将长波吸收压缩为红外光学深度；灰色大气可以估算数量级，但不能把短波反照率与长波吸收合并成同一个参数。

地表吸收恒星短波辐射后，以红外辐射：

$$\sigma T_s^4$$

向外释放。

温室气体吸收部分红外：

H₂O、CO₂、CH₄、N₂O。

导致逃逸到太空的红外减少。

最简单温室模型可以用红外光学深度：

$$\tau_{IR}$$

表示。

灰色大气近似下：

$$\boxed{ T_s^4 \approx T_{eq}^4 \left( 1+\frac34\tau_{IR} \right) }$$

因此：

$$\boxed{ T_s \approx T_{eq} \left( 1+\frac34\tau_{IR} \right)^{1/4} }$$

这非常适合程序化星球气候估算。

可以近似：

$$\boxed{ \tau_{IR} = \sum_i \kappa_i m_i }$$

其中：

* $\kappa_i$：吸收系数
* $m_i$：该气体柱质量

对于单一均匀大气：

$$m \approx \frac{P_s}{g}$$

所以：

$$\boxed{ \tau_{IR} \propto \kappa \frac{P_s}{g} }$$

地表压强：

$$P_s$$

单位面积大气质量：

$$\boxed{ m_{column} = \frac{P_s}{g} }$$

这是非常重要的星球参数。

意味着：

在表面气压相同时，较强重力对应较小的大气柱质量，较弱重力则对应较大的大气柱质量。

#### 水汽与云的辐射反馈

温度升高：

$$T\uparrow$$

导致：

$$P_{sat}\uparrow$$

于是大气可容纳更多水汽：

$$H_2O\uparrow$$

水蒸气本身又是温室气体：

$$\tau_{IR}\uparrow$$

最终：

$$T\uparrow$$

由此形成水汽正反馈。

云同时具有两种效应。

短波：

$$Cloud \rightarrow Reflection$$

提高反照率：

$$A\uparrow$$

产生冷却。

长波：

$$Cloud \rightarrow IR\ Absorption$$

产生温室效应。

因此云既可能通过反射短波产生冷却，也可能通过吸收长波产生增温
取决于：

云高度、云厚度、云滴大小、覆盖率。

程序化模型：

$$\boxed{ C_f = \operatorname{saturate} \left( \frac{ RH-RH_0 }{ 1-RH_0 } \right) }$$

其中：

$$RH_0$$

是开始产生明显云层的湿度阈值。

例如：

$$RH_0\approx0.7$$

只是视觉模型参数，并非严格物理常数。


#### 露点、云底高度与对流

空气上升时会膨胀冷却。

干绝热递减率：

$$\boxed{ \Gamma_d = \frac{g}{c_p} }$$

地球约：

$$9.8\ \mathrm{K/km}$$

所以：

$$T(h) = T_0-\Gamma_dh$$

当温度降到露点：

$$T=T_{dew}$$

开始形成云。

给定水汽压 $e$：

$$e=P_{sat}(T_{dew})$$

因此：

$$\boxed{ T_{dew} = P_{sat}^{-1}(e) }$$

程序化模型可直接使用温度与露点之差估算云底高度。

地球经验近似：

$$h_{cloud} \approx 125 (T-T_{dew})$$

单位：

* 温度差：°C
* 高度：m

例如：

$$T-T_{dew}=8^\circ C$$

则：

$$h_{cloud} \approx1000\ \mathrm m$$

这个公式仅适合近地球环境，可作为视觉近似。

如果底部空气较热：

$$\rho_{warm}<\rho_{cold}$$

会产生浮力。

浮力近似：

$$\boxed{ a_b \approx g \frac{ T'-T }{ T } }$$

暖空气：

$$T'>T$$

则：

$$a_b>0$$

发生上升。

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \draw[draw=cyan!85, thick] (-5,-1.25) -- (5,-1.25);
  \draw[draw=cyan!85, thick, densely dashed] (-5,1.45) -- (5,1.45);
  \node[anchor=west, inner sep=0pt, outer sep=0pt, text=cyan] at (-5,-1.6) {赤道};
  \node[anchor=east, inner sep=0pt, outer sep=0pt, text=cyan] at (5,-1.6) {极地};

  \draw[draw=cyan!85, thick, ->] (-4.55,-1.25) .. controls (-4.8,-0.5) and (-4.7,0.5) .. (-4.25,0.95);
  \draw[draw=cyan!85, thick, ->] (-4.25,0.95) .. controls (-3.6,1.25) and (-2.45,1.25) .. (-1.85,0.75) .. controls (-1.55,0.2) and (-1.55,-0.65) .. (-1.8,-1.25);
  \draw[draw=cyan!85, thick, ->] (-1.8,-0.82) .. controls (-2.55,-0.62) and (-3.55,-0.62) .. (-4.35,-0.82);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (-3.1,-1.65) {Hadley};

  \draw[draw=cyan!85, thick, ->] (1.45,-1.25) .. controls (1.7,-0.5) and (1.65,0.5) .. (1.2,0.95);
  \draw[draw=cyan!85, thick, ->] (1.2,0.95) .. controls (0.55,1.25) and (-0.55,1.25) .. (-1.15,0.75) .. controls (-1.45,0.2) and (-1.45,-0.65) .. (-1.2,-1.25);
  \draw[draw=cyan!85, thick, ->] (-1.2,-0.82) .. controls (-0.45,-0.62) and (0.45,-0.62) .. (1.25,-0.82);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (0,-1.65) {Ferrel};

  \draw[draw=cyan!85, thick, ->] (1.8,-1.25) .. controls (1.55,-0.5) and (1.6,0.5) .. (2.05,0.95);
  \draw[draw=cyan!85, thick, ->] (2.05,0.95) .. controls (2.7,1.25) and (3.75,1.25) .. (4.35,0.75) .. controls (4.65,0.2) and (4.65,-0.65) .. (4.4,-1.25);
  \draw[draw=cyan!85, thick, ->] (4.4,-0.82) .. controls (3.7,-0.62) and (2.75,-0.62) .. (1.95,-0.82);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (3.1,-1.65) {Polar};

  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=orange] at (-4.55,1.7) {上升};
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text=cyan] at (4.4,1.7) {下沉};
\end{tikzpicture}
```
这可以作为程序化积云生成逻辑。


### 环流、纬度与季节

#### 气压梯度、科里奥利力与大尺度环流

风由气压梯度加速，再受旋转参考系中的科里奥利项偏转，并通过摩擦和质量连续性达到大尺度环流。纬向条带只是结果之一，不应直接作为输入纹理。

水平气压差产生加速度：

$$\boxed{ \mathbf a = -\frac1\rho \nabla P }$$

因此：

旋转星球上：

$$\boxed{ \mathbf a_C = -2 \boldsymbol\Omega \times \mathbf v }$$

其中：

$$\Omega = \frac{2\pi}{P_{rot}}$$

因此自转速度决定大尺度风带偏转程度。

对于类似地球的旋转星球，可以形成：


概念上：

以赤道环流为例：强烈加热使空气上升，高空空气流向高纬并冷却下沉，随后在近地面返回低纬，形成闭合环流。

#### 纬度温度、入射角与季节

最简单：

$$T(\phi) = T_{equator} - \Delta T \sin^2\phi$$

其中：

* $\phi=0$：赤道
* $|\phi|=90^\circ$：极地

因此：

$$\boxed{ T(\phi) = T_e - \Delta T\sin^2\phi }$$

星球有轴倾角：

$$\varepsilon$$

恒星直射纬度随时间变化：

$$\boxed{ \delta = \varepsilon \sin( 2\pi t/P_{orbit} ) }$$

其中：

$$\delta$$

是太阳赤纬。

因此，季节主要来源于轴倾角，而不是星球与恒星距离的变化。

纬度 $\phi$，太阳赤纬 $\delta$，时角 $H$：

$$\boxed{ \cos Z = \sin\phi\sin\delta + \cos\phi\cos\delta\cos H }$$

其中 $Z$ 是太阳天顶角。

局部太阳通量：

$$F= S\max(0,\cos Z)$$

这可以直接用于星球表面气候贴图生成。


### 极端气候与水资源保持

#### 冰盖、雪线与海冰

如果长期平均：

$$T(\phi)<T_f$$

则形成稳定冰盖。

冰覆盖：

$$\boxed{ I(\phi) = 1- \operatorname{smoothstep} ( T_f-\Delta T_i, T_f+\Delta T_i, T(\phi) ) }$$

雪线高度由：

$$T(h)=T_f$$

决定。

若：

$$T(h) = T_0-\Gamma h$$

则：

$$\boxed{ h_{snow} = \frac{ T_0-T_f }{ \Gamma } }$$

因此高山自然出现积雪。

Shader 可以直接使用：

```hlsl
float snowLine =
    (surfaceTemperature - freezeTemperature)
    / lapseRate;
```

海洋表面温度：

$$T_o<T_{freeze}$$

产生海冰。

海冰厚度可以通过简单导热模型：

$$h_i \propto \sqrt t$$

经典 Stefan 问题近似：

$$\boxed{ h_i = \sqrt{ \frac{ 2k_i\Delta T }{ \rho_iL_f } t } }$$


#### 冻结与失控温室极限

如果冰覆盖率过大：

$$A\uparrow$$

使：

$$T\downarrow$$

可能进入：

**Snowball Planet**

即全球冰冻状态。

如果温度不断升高：

$$T\uparrow$$

导致：

$$H_2O\ vapor\uparrow$$

进一步：

$$\tau_{IR}\uparrow$$

温度继续升高。

在极端条件下可能形成：

**Runaway Greenhouse**

类似金星方向的气候演化。


#### 海洋蒸发与水资源长期保持

温度很高时：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-4.8,0) {海洋};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-1.6,0) {强烈蒸发};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (1.6,0) {蒸汽大气};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.48cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (4.8,0) {强化温室效应};
  \draw[draw=cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[draw=cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[draw=cyan!85, thick, ->] (node3.east) -- (node4.west);
\end{tikzpicture}
```
如果高层水分子被紫外线分解：

$$H_2O+h\nu \rightarrow H+OH$$

轻氢可逃逸：

$$H\rightarrow Space$$

长期可能导致星球永久失水。

是否保留水取决于：

表面温度、重力、逃逸速度、大气状态、紫外通量、磁环境和年龄。

所以海洋系统最终又与大气逃逸模型连接。


### 气候实现与环境闭环

#### 气候状态变量与最小更新链

最小气候模型也应区分外部常量、慢变量和快速状态，并给每个变量明确单位、更新频率和守恒关系。

可以定义：

```hlsl
struct ClimateParams
{
    float stellarFlux;

    float bondAlbedo;
    float surfacePressure;

    float waterFraction;

    float greenhouseOpticalDepth;

    float rotationPeriod;
    float axialTilt;

    float surfaceTemperature;

    float humidity;
    float cloudCoverage;

    float iceCoverage;
};
```

输入：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.8cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-2,1.2) {恒星光度 / 轨道};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-2,0) {半径 / 重力};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.12cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (-2,-1.2) {大气 / 水 / 反照率};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.48cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (2,0) {宜居环境状态};
  \draw[draw=cyan!85, thick, ->] (node1.east) -- (node4.west);
  \draw[draw=cyan!85, thick, ->] (node2.east) -- (node4.west);
  \draw[draw=cyan!85, thick, ->] (node3.east) -- (node4.west);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (2,-0.75) {温度、压强与气候};
\end{tikzpicture}
```

恒星与轨道输入先确定辐射通量和无温室平衡温度：

$$S=\frac{L_\star}{4\pi d^2},\qquad T_{eq}=\left[\frac{S(1-A)}{4\sigma}\right]^{1/4}.$$

随后用温室光学深度、热容量和热输送求表面温度 $T_s$。$T_s$ 决定水的相态及蒸发，水汽又改变云量、降水、反照率和红外光学深度，因此反馈关系应按下表迭代，而不是单向排列：

| 状态变化 | 直接影响 | 返回气候系统的量 |
| --- | --- | --- |
| 海洋升温 | 蒸发增强、湿度升高 | 水汽温室效应与云量 |
| 云量增加 | 短波反射和长波保温同时改变 | 行星反照率与红外光学深度 |
| 冰雪扩张 | 高反照率区域增加 | 吸收的恒星能量下降 |
| 降水与径流 | 大气水汽回到地表储库 | 云水量、土壤湿度和海洋质量 |

一次气候步应保存能量与水量两套收支，循环迭代至 $T_s$、云量和冰量变化低于容差。这样得到的是闭环状态，而非从恒星到颜色的一次性流水线。


#### 环境闭环、Shader 接口与系统总链

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-4.8,0.6) {恒星辐射};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.8cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-1.6,0.6) {陆地 / 海洋 / 冰};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.2cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (1.6,0.6) {蒸发与水汽};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=2.8cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (4.8,0.6) {云、降水与径流};
  \draw[draw=cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[draw=cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[draw=cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[draw=cyan!85, thick] (4.8,0.1) -- (4.8,-0.6);
  \draw[draw=cyan!85, thick] (4.8,-0.6) -- (-4.8,-0.6);
  \draw[draw=cyan!85, thick, ->] (-4.8,-0.6) -- (-4.8,0.1);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (0,-0.95) {水汽、云与表面状态耦合};
\end{tikzpicture}
```
气候反馈至少包含两条闭环：冰量改变反照率并反馈温度；水汽、CO₂ 和 CH₄ 改变温室效应并反馈温度。

因此最终气候本质上是一个反馈系统。

Shader 层可以对应：

```tikz
\usetikzlibrary{arrows.meta}
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=4.08cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-2.25,1.2) {表面：地形、海洋、雪冰};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=4.72cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-2.39,-0.02) {大气：密度、散射、水汽、云};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=5.68cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (-3.03,-1.18) {气候：日照、季节、湿度、风、降水};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.44cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (2.8,0.03) {统一着色 / 气候模型};
  \draw[draw=cyan!85, thick, -{Latex}] (node1.east) -- (node4.west);
  \draw[draw=cyan!85, thick, -{Latex}] (node2.east) -- (node4.west);
  \draw[draw=cyan!85, thick, -{Latex}] (node3.east) -- (node4.west);
\end{tikzpicture}
```


现在可以把星球内部、表面与大气连成：

```tikz
\begin{tikzpicture}[scale=1.18, line cap=round, line join=round]
  \color{white}
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.12cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node1) at (-6.51,0.58) {成分、质量、半径};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.12cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node2) at (-2.29,0.6) {内部、重力与火山};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.44cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node3) at (1.6,0.6) {大气压、密度与散射};
  \node[draw=cyan!85, thick, rounded corners=3pt, minimum width=3.76cm, minimum height=0.72cm, align=center, fill=black!55, text=white] (node4) at (5.66,0.6) {辐照、海洋冰层与气候};
  \draw[draw=cyan!85, thick, ->] (node1.east) -- (node2.west);
  \draw[draw=cyan!85, thick, ->] (node2.east) -- (node3.west);
  \draw[draw=cyan!85, thick, ->] (node3.east) -- (node4.west);
  \draw[draw=cyan!85, thick] (5.47,0.13) -- (5.47,-0.57);
  \draw[draw=cyan!85, thick] (5.47,-0.57) -- (-6.44,-0.6);
  \draw[draw=cyan!85, thick, ->] (-6.44,-0.6) -- (-6.44,0.1);
  \node[anchor=center, inner sep=0pt, outer sep=0pt, text={rgb,255:red,255;green,165;blue,0}] at (0,-0.95) {从行星本体到大气--气候的闭环};
\end{tikzpicture}
```
至此，一个程序化岩质星球的**内部—地表—海洋—大气—气候**基础物理链已经基本闭合。

