
为什么使用后处理阶段
旧项目里已经实现了雨、雪、雾和日照效果。它们并不是给每一个模型单独加材质,而是在 Cesium 完成场景渲染后,通过 postProcessStages 对整张画面再处理一次。这样接入简单,也方便统一切换强、中、弱三个等级。
公共调用方式
核心入口只负责两件事:根据场景类型找到对应着色器,再把创建出的后处理阶段返回,方便调用方销毁。
import { PostProcessStage, PostProcessStageLibrary } from "cesium"
export function setSceneEffect(viewer, options) {
if (["RAIN", "SNOW", "FOG"].includes(options.scene)) {
return viewer.scene.postProcessStages.add(new PostProcessStage({
name: options.scene + "_effect",
fragmentShader: shaderMap[options.scene][options.level],
}))
}
if (options.scene === "BEAM") {
const stage = viewer.scene.postProcessStages.add(
PostProcessStageLibrary.createBrightnessStage(),
)
stage.uniforms.brightness = brightnessMap[options.level]
return stage
}
}
雨景着色器的思路
雨滴来自屏幕坐标、时间和随机函数的组合。先把坐标旋转形成倾斜方向,再根据帧数推进雨滴,最后将计算出的颜色与场景原色混合。雨量大小不需要换算法,只要调整雨滴尺寸和混合比例。
float time = czm_frameNumber / 60.0;
vec2 resolution = czm_viewport.zw;
vec2 uv = (gl_FragCoord.xy * 2.0 - resolution.xy)
/ min(resolution.x, resolution.y);
float rain = clamp(abs(sin(20.0 * time + uv.y * 4.0)) - 0.95, 0.0, 1.0);
vec3 color = vec3(0.6, 0.7, 0.8) * rain * 35.0;
out_FragColor = mix(texture(colorTexture, v_textureCoordinates), vec4(color, 1.0), 0.42);
工程化建议
不要把所有 GLSL 塞进组件。把场景枚举、等级参数和 shader 源码拆成独立模块;切换前先移除上一个 stage;低性能设备默认使用较弱等级。这样天气效果才是一项可维护的能力,而不只是一次演示。