共计 1823 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点:为什么需要 GPU 风场
传统 CPU 计算风场粒子运动(如用 setInterval 更新 10,000 个粒子位置)会导致:

- 数据更新延迟:每次风速数据变化需全量回传 CPU,主线程阻塞明显
- 规模受限:实测在 i7-11800H 上超过 5 万粒子时帧率降至 20fps 以下
- 动态效果差:CPU 计算的粒子轨迹缺乏流体连续性(如图 1 左稀疏分布)
技术方案对比
测试环境:Chrome 120/RTX 3060/100k 粒子
| 方案 | 平均帧率 | 内存占用 | 适用场景 |
|---|---|---|---|
| WebWorker | 38fps | 420MB | 简单路径计算 |
| Canvas 2D | 17fps | 210MB | 静态展示 |
| WebGL (本方案) | 62fps | 150MB | 动态大规模风场 |
核心实现:GPU 粒子系统
1. Cesium.ParticleSystem 配置
// 创建基础粒子系统(需关闭 CPU 更新)const particleSystem = viewer.scene.primitives.add(
new Cesium.ParticleSystem({
image: 'path/to/particleTexture.png',
capacity: 100000,
emitter: new Cesium.CircleEmitter(0.5),
updateCallback: null // 关键!禁用 CPU 更新
})
);
2. CustomShader 关键代码
风速场纹理采样(Vertex Shader)
// 风速纹理 RG 通道存储 UV 方向速度(单位:m/s)uniform sampler2D windTexture;
vec2 getWindVelocity(vec2 lonLat) {
vec2 uv = vec2((lonLat.x - west) / (east - west),
(lonLat.y - south) / (north - south)
);
return texture2D(windTexture, uv).rg * 20.0; // 缩放系数
}
双缓冲位置更新(Fragment Shader)
// 使用两个 RGBA32F 纹理交替读写
uniform sampler2D positionTextureRead;
uniform sampler2D positionTextureWrite;
void main() {vec4 pos = texture2D(positionTextureRead, v_textureCoordinates);
vec2 velocity = getWindVelocity(pos.xy);
// 欧拉积分更新位置
pos.xy += velocity * deltaTime;
// 边界循环
if(pos.x > east) pos.x = west;
if(pos.y > north) pos.y = south;
gl_FragColor = pos; // 写入新位置
}
性能优化实战
1. 高精度数据支持
// 初始化时检查扩展
const ext = gl.getExtension('EXT_color_buffer_float');
if (!ext) {console.warn('FP32 纹理支持不可用,降级到 RGBA16F');
}
2. LOD 分级策略
// 根据粒子到相机距离计算显示等级
float lodLevel = clamp(distance(cameraPos, particlePos) / 100000.0,
0.0, 1.0
);
if(lodLevel > 0.7) {
particleSize *= 0.3; // 远处粒子缩小
skipPhysicsUpdate(); // 降低物理更新频率}
常见坑点解决方案
WebGL 上下文丢失
viewer.scene.contextLost.addEventListener(() => {
// 1. 保存当前粒子状态
const positions = saveParticlePositions();
// 2. 重建后恢复
viewer.scene.contextRestored.addEventListener(() => {recreateTextures();
restorePositions(positions);
});
});
安卓设备兼容
- 使用
OES_texture_half_float替代 FP32 - 在片元着色器中加入精度声明:
precision highp float;
进阶思考:地形耦合
现有方案的风场高度固定,如何实现以下效果?
1. 粒子随地形高程动态调整高度
2. 山体对风场的阻挡效应
3. 峡谷区域的湍流模拟
提示:需要采样 Cesium 地形瓦片(TerrainTile)的高度图纹理
正文完
