Dynamic Cloud and Rain Shaders for CesiumJS Using Post-Processing
Adding weather to a geospatial visualization usually means swapping tile sets or injecting particle systems, both of which are expensive and complex. Screen-space post-processing shaders sidestep that entirely: the effect costs a single full-screen quad per frame, works on any Cesium scene without modifying the globe, and can be toggled or tuned at runtime with a uniform.
CesiumJS ships without built-in weather effects, so dynamic atmosphere must be painted onto the final frame through its PostProcessStage pipeline. This implementation provides two shaders: one that layers four octaves of FBM noise to generate slow-moving dark clouds, and another that uses a hash function to scatter animated rain streaks across the screen. Both effects run as post-processing passes on the color texture, meaning they operate purely in screen space without touching the 3D scene geometry.
A sky mask derived from the screen-space Y coordinate confines the cloud overlay to the upper portion of the view, leaving terrain and buildings untouched. The rain shader applies a slight darkening and a blue-grey tint, with intensity blended via a uniform so the effect scales from a drizzle to a downpour. Each shader is driven by a requestAnimationFrame loop that increments a time uniform, producing continuous animation.
The Vue 3 integration wraps everything in a single component with Element Plus sliders and toggle buttons. Cleanup on unmount removes the post-process stages and destroys the Cesium viewer to prevent memory leaks, and the code targets GLSL 300-ES for compatibility with Cesium 1.141.0.
Screen-space weather effects are surprisingly cheap because they skip geometry entirely; the entire cloud system is just a few noise lookups per pixel.
Using a sky mask based on screen Y is a pragmatic shortcut that works for most ground-level views but would fail if the camera pitched upward, exposing the hard cutoff.
The rain shader's hash-based placement means streaks are stateless and deterministic per frame, which avoids any need for particle buffers or persistent state across draws.
Tying animation to requestAnimationFrame rather than Cesium's clock decouples the weather from simulation speed, so pausing the scene doesn't freeze the rain.