OptionalterrainMaterial?: ShaderMaterial | nullOptionalroadMaterial?: ShaderMaterial | nullRoad overlay material, so a cloud passing overhead dims the road with the ground it sits on rather than sliding over a bright ribbon.
Optionalsky?: OvercastTarget | nullSky dome to grey out under rain/snow. Also settable later via setSky.
OptionalliquidMaterials?: () => Iterable<LiquidMaterialSet>Provider for the liquid material sets so cloud shadows darken water in
step with the ground. A function (not a snapshot) so swapped liquid
materials are picked up — pass () => world.liquidMaterials.values()
style accessors.
Optionalwind?: WindThe world's shared Wind. Omit and this system keeps a private one
(and advances it itself); pass one — as HexWorld does — and the clouds
and rain answer the same wind that bends the trees.
How much of the world wind the falling particles take, 0–1. Default 0.1.
Deliberately far below 1. The wind that bends a tree is measured against the tree standing still, but rain is already moving — it is falling at several times the wind's own speed, and it only spends a second or two in the air. Handing the particles the full ground wind slants the fall as hard as a gale and makes every gust visible as a lurch across the whole sky, which reads as the camera moving rather than as weather. A tenth is enough to see the rain lean the way the trees do without either of those.
It scales the drift and the streak angle together, so raising it tilts the fall and lengthens the sideways travel as one thing.
The sustained wind in world units/sec. Mutate freely — clouds turn smoothly, because the drift offset is integrated rather than recomputed.
This is windField's base vector, so writing here is writing to
the shared wind the whole world reads.
How grey the sky should read right now, 0–1 — the weather's contribution to a SkyDome. Scales with intensity, so a storm ramping up greys the sky as it comes in.
The current particle layer (null when clear) — for advanced tweaking.
Switch weather. Rebuilds the particle layer; cloud shadows re-style in place.
Ramp the current weather 0–1 (particles + cloud darkness + sky greying) — animate for smooth transitions.
Attach (or detach, with null) the sky dome this weather greys out. Every later weather/intensity change pushes to it automatically.
Gate precipitation on a per-cell mask — a ClimateData texture, in
practice. Snow is masked to where snow is lying and rain to the inverse,
so a single climate texture splits the map into the two cleanly and no hex
receives both.
Held across weather changes: setWeather rebuilds the particle layer, and
the mask is re-applied to the new one, so callers set it once.
Optionalrect: { x: number; z: number; width: number; depth: number }Re-point at a new terrain material after a swap (setTerrainDescriptors / loadHexPack).
Re-push cloud config onto the current materials (call after swapping liquid materials).
Advance the weather one frame: drift the shared cloud field by wind and
update the particle layer. center is the camera's ground target.
Remove particles, switch off cloud shadows, clear the sky, free resources.
One knob for the whole weather picture: drifting cloud shadows on the terrain plus a matching precipitation layer, driven off a single wind and a single world-space cloud field so rain visibly falls under the clouds that shade the ground (and moves with them). Lighter clouds stay dry — see WeatherOptions.precipCoverage. Give it a sky dome and it greys that out too, so a storm doesn't fall out of a clear blue sky.
The cloud drift offset is integrated on the CPU each update, so changing wind mid-storm turns the field smoothly instead of teleporting it.
Example