Cesium 实现超真实动态体积云 | 光线步进RayMarching原理详解
简介
在 Cesium 数字孪生、三维GIS、水文气象仿真项目开发中,传统面片贴云存在明显短板:无法贴合地球曲率、无动态随风飘动效果、光影表现生硬、云层层次单一。
本文不贴完整冗长着色器源码,只讲核心原理+关键架构+精简关键代码,基于 RayMarching 光线步进 + 三维噪声 + 球壳云层模型 + 大气散射,实现可参数调控、动态漂移、真实光影的体积云效果,兼顾视觉效果与渲染性能,可直接落地项目。
一、效果核心亮点
- 云层采用地球球壳模型,完美贴合地表曲率,无穿帮、无平面割裂
- 算法程序化生成云朵,模拟积云、层积云多层自然云形态
- 支持云量、云底高度、云层厚度、风向、风速实时可调
- 基于帧时间驱动风场,云朵可动态漂移+细微形变,动画丝滑
- 对接Cesium太阳光照系统,实现云层明暗、散射通透真实光影
- 内置远近LOD自适应优化,远景降精度、近景保细节,帧率稳定
- 基于Cesium后处理通道开发,低侵入、易集成、可复用
二、整体渲染流程
整个体积云依托 Cesium PostProcessStage 后处理通道实现,整体流程:
- 采样屏幕原图 + 深度纹理
- 通过深度值逆向重构世界空间坐标
- 构建当前像素相机视线射线
- 射线与球形云层求交,确定云层有效采样区间
- 光线步进逐点采样,计算空间云层密度
- 结合大气散射模型计算光照与颜色
- 云层图层与原场景纹理插值混合,输出最终画面
三、核心技术原理
3.1 球壳云层空间建模
不使用传统平面面片,以 WGS84 地球椭球为基准:
- 定义云底高度、云顶高度参数
- 换算为云底球体半径、云顶球体半径
- 将云层抽象为空心球壳圈层
通过射线球体相交算法,求解视线射线进入云层、离开云层的距离范围,仅在有效区间内做采样计算,减少无效渲染开销。
3.2 三维噪声构建云朵形态
云朵不规则轮廓依靠三维分层噪声实现:
- 低频噪声:控制云朵整体分布与大轮廓
- 高频噪声叠加:丰富云朵边缘细碎纹理
- 按云层高度占比做权重混合,区分积云、层积云不同特征
根据采样点所处云层高度,动态适配云型权重,还原真实大气云层分布规律。
3.3 风场动态飘动实现原理
借助 Cesium 内置帧计数器 czm_frameNumber 做时间驱动:
- 外部定义风向向量、风速比例系数
- 每帧给噪声采样坐标叠加「时间 × 风向偏移」
- 实现云朵整体平移+局部细微形变,模拟自然风吹效果
所有风场参数对外开放,可通过前端控件实时调节,无需修改着色器代码。
3.4 RayMarching 光线步进核心逻辑
是体积云渲染的核心算法:
- 以相机世界位置为起点,构建像素视线射线
- 计算射线与云层球壳的起止采样距离
- 采用动态步长策略:云外大步长快速掠过,云内小步长精细采样
- 逐步进采样三维噪声,求解当前点位云层密度
- 密度超阈值判定云内,执行光照散射计算;否则跳过
- 透明度达标后提前终止循环,优化性能
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、数字孪生、水文气象项目中,还可在此基础上扩展雾效、雨雪、晨昏光晕等全套大气特效。
完整源码包含:体积云着色器、风向风速云量控制面板、性能优化版本、一键集成示例。有需要的朋友直接私信我即可获取。