Cesium 实现超真实动态体积云 | 光线步进RayMarching原理详解(学习原理版本)

48 阅读7分钟

Cesium 实现超真实动态体积云 | 光线步进RayMarching原理详解

简介

在 Cesium 数字孪生、三维GIS、水文气象仿真项目开发中,传统面片贴云存在明显短板:无法贴合地球曲率、无动态随风飘动效果、光影表现生硬、云层层次单一。

本文不贴完整冗长着色器源码,只讲核心原理+关键架构+精简关键代码,基于 RayMarching 光线步进 + 三维噪声 + 球壳云层模型 + 大气散射,实现可参数调控、动态漂移、真实光影的体积云效果,兼顾视觉效果与渲染性能,可直接落地项目。

一、效果核心亮点

  • 云层采用地球球壳模型,完美贴合地表曲率,无穿帮、无平面割裂
  • 算法程序化生成云朵,模拟积云、层积云多层自然云形态
  • 支持云量、云底高度、云层厚度、风向、风速实时可调
  • 基于帧时间驱动风场,云朵可动态漂移+细微形变,动画丝滑
  • 对接Cesium太阳光照系统,实现云层明暗、散射通透真实光影
  • 内置远近LOD自适应优化,远景降精度、近景保细节,帧率稳定
  • 基于Cesium后处理通道开发,低侵入、易集成、可复用

二、整体渲染流程

整个体积云依托 Cesium PostProcessStage 后处理通道实现,整体流程:

  1. 采样屏幕原图 + 深度纹理
  2. 通过深度值逆向重构世界空间坐标
  3. 构建当前像素相机视线射线
  4. 射线与球形云层求交,确定云层有效采样区间
  5. 光线步进逐点采样,计算空间云层密度
  6. 结合大气散射模型计算光照与颜色
  7. 云层图层与原场景纹理插值混合,输出最终画面

三、核心技术原理

3.1 球壳云层空间建模

不使用传统平面面片,以 WGS84 地球椭球为基准:

  • 定义云底高度、云顶高度参数
  • 换算为云底球体半径、云顶球体半径
  • 将云层抽象为空心球壳圈层

通过射线球体相交算法,求解视线射线进入云层、离开云层的距离范围,仅在有效区间内做采样计算,减少无效渲染开销。

3.2 三维噪声构建云朵形态

云朵不规则轮廓依靠三维分层噪声实现:

  • 低频噪声:控制云朵整体分布与大轮廓
  • 高频噪声叠加:丰富云朵边缘细碎纹理
  • 按云层高度占比做权重混合,区分积云、层积云不同特征

根据采样点所处云层高度,动态适配云型权重,还原真实大气云层分布规律。

3.3 风场动态飘动实现原理

借助 Cesium 内置帧计数器 czm_frameNumber 做时间驱动:

  • 外部定义风向向量、风速比例系数
  • 每帧给噪声采样坐标叠加「时间 × 风向偏移」
  • 实现云朵整体平移+局部细微形变,模拟自然风吹效果

所有风场参数对外开放,可通过前端控件实时调节,无需修改着色器代码。

3.4 RayMarching 光线步进核心逻辑

是体积云渲染的核心算法:

  1. 以相机世界位置为起点,构建像素视线射线
  2. 计算射线与云层球壳的起止采样距离
  3. 采用动态步长策略:云外大步长快速掠过,云内小步长精细采样
  4. 逐步进采样三维噪声,求解当前点位云层密度
  5. 密度超阈值判定云内,执行光照散射计算;否则跳过
  6. 透明度达标后提前终止循环,优化性能

3.5 LOD 远距离性能优化

针对大范围三维视距做分级适配:

  • 根据像素与相机直线距离自动划分LOD等级
  • 远距离降低噪声层数与采样精度
  • 中近距离保留完整多层噪声细节
  • 限制云层最大可视距离,超出直接截断渲染

有效避免大范围场景全量计算导致的帧率卡顿。

3.6 大气光照散射原理

集成经典光学散射模型:

  • 引入 Schlick 散射、各向同性散射算法
  • 对接Cesium太阳光照,计算云层亮部与阴影层次
  • 混合天空环境光、地面环境光,规避云层死黑问题
  • 通过消光系数、散射系数模拟光线在云内部的衰减与弥散

最终将云层与原场景纹理插值混合,过渡自然不生硬。

3.7 可视化参数可配置

将核心参数统一抽为 Uniform 变量,JS 层可实时动态传参:

  • 云层覆盖率:控制云朵疏密与空缺
  • 地球基准半径:适配自定义椭球场景
  • 云底/云顶高度:自由调整云层高低与厚度
  • 风向、风速:控制云朵运动方向与漂移速度

可快速搭建前端控制面板,滑块实时调节效果。

四、关键精简核心代码

4.1 着色器基础常量与工具方法

// 基础数学常量
const float PI = 3.14159265359;
const float FOUR_PI = 12.5663706144;

// 云层步进配置
#define MAXIMUM_CLOUDS_STEPS 300
#define CLOUDS_MAX_VIEWING_DISTANCE 250000.0

// 工具截断函数
float saturate(float value) {
    return clamp(value, 0.0, 1.0);
}

4.2 射线球体相交核心方法

射线与球体求交是整个体积云的基础,用来判断当前视线射线什么时候进入云层、什么时候离开云层,只在有效云层区间内做光线步进计算,大幅节省性能。

核心原理: 利用射线参数方程与球体方程联立求解,通过一元二次方程判别式判断是否相交,再计算出进入点和离开点的距离。

vec2 raySphereIntersect(vec3 r0, vec3 rd, float sr) {
    float a = dot(rd, rd);
    float b = 2.0 * dot(rd, r0);
    float c = dot(r0, r0) - (sr * sr);
    float d = (b * b) - 4.0 * a * c;

    if (d < 0.0) return vec2(-1.0, -1.0);
    float squaredD = sqrt(d);
    return vec2(
        (-b - squaredD) / (2.0 * a),
        (-b + squaredD) / (2.0 * a)
    );
}

4.3 Cesium 后处理接入核心代码

本方案基于 Cesium 官方 PostProcessStage 后处理通道实现云层渲染,无需修改场景底层架构,低侵入、易集成,核心代码如下:

// 初始化Cesium场景
const viewer = new Cesium.Viewer('cesiumContainer');

// 云层渲染统一配置参数(支持外部实时修改)
const cloudUniforms = {
    // 云量覆盖率 0~1
    cloudCover: 0.8,
    // 地球基准半径
    realPlanetRadius: Cesium.Ellipsoid.WGS84.radii.x,
    // 云底高度(单位:米)
    cloudBase: 1000.0,
    // 云顶高度(单位:米)
    cloudTop: 5000.0,
    // 风向向量
    windVector: new Cesium.Cartesian3(1.0, 0.0, 0.0),
    // 云层厚度
    cloudThickness: 4000.0,
    // 云底/云顶球体半径
    cloudBaseRadius: Cesium.Ellipsoid.WGS84.radii.x + 1000.0,
    cloudTopRadius: Cesium.Ellipsoid.WGS84.radii.x + 5000.0
};

// 创建体积云后处理阶段
const cloudPostStage = new Cesium.PostProcessStage({
    fragmentShader: volumetricCloudShaderSource,
    uniforms: cloudUniforms
});

// 添加到场景渲染队列
viewer.scene.postProcessStages.add(cloudPostStage);

五、性能优化总结

  • 区间裁剪优化:通过射线球体相交计算,仅在云层范围内执行光线步进,剔除无效渲染区域
  • 动态步长切换:云外使用大步长快速采样,云内使用小步长保证细节,平衡效果与性能
  • LOD 远近分级:根据相机距离自动调整噪声精度,远距离降低计算量
  • 循环提前终止:云层完全不透明时直接跳出光线步进循环,减少着色器运算
  • 参数统一抽离:将渲染参数外置为 Uniform 变量,支持实时修改,无需重启着色器

六、应用场景

  • Cesium 数字孪生大气环境仿真
  • 气象、水文三维云场可视化推演
  • 智慧城市、智慧园区三维大气特效
  • 三维航拍漫游、真实天空场景渲染
  • 洪涝、台风等气象灾害可视化模拟

七、总结

本文基于 Cesium 后处理架构,结合光线步进、三维噪声、球壳云层建模、大气散射光学模型,实现了参数可配置、动态随风漂移、远近自适应优化的真实体积云效果。

纯算法实现无需额外模型贴图,低侵入易集成,可直接复用在各类三维 GIS、数字孪生、水文气象项目中,还可在此基础上扩展雾效、雨雪、晨昏光晕等全套大气特效。

完整源码包含:体积云着色器、风向风速云量控制面板、性能优化版本、一键集成示例。有需要的朋友直接私信我即可获取。