Guides
Render paths
Rain, snow, lightning, wet materials and shelter work however you render. What changes is the fog, the puddle reflections and the tone mapping. Use weather.render() for the full look, or keep renderer.render() and your own post chain.
#Side by side
weather.render() | renderer.render(scene, camera) | |
|---|---|---|
| Rain, snow, splashes, lightning | ✓ | ✓ |
| Wet and snowy materials, shelter | ✓ | ✓ |
| Fog | Volumetric height fog, shadowed shafts, lamp halos, lightning glow | THREE.FogExp2 on scene.fog (fog.sceneFog = 'auto') |
| Puddles | Screen-space reflections, distorted by raindrop rings | Environment-map reflections, or a sky tint with no env map |
| Bloom, exposure, tone mapping | Built in: bloom, exposure, ACES | Your renderer settings |
Works with EffectComposer | Render into a target and post-process that | ✓ |
#weather.render()
renderer.setAnimationLoop(() => {
weather.update(dt);
weather.render(); // replaces renderer.render(scene, camera)
});The first call creates weather.pipeline, a WeatherPipeline. Each frame it runs:
#Scene to HDR
Your scene renders into a half-float target with depth. Ground materials write their puddle reflectivity into its alpha.
#Volumetric fog
The fog is raymarched at fogScale of the resolution with fogSteps steps. It samples the shadowLight's shadow map for shafts.
#SSR and composite
Puddle reflections, ssrSteps steps long, then the fog is composited over the scene.
#Bloom
A six-level downsample and upsample chain.
#Exposure and ACES
exposure × the preset's exposure, then the ACES tonemapper, to the screen or to target.
#Exposure and bloom
weather.exposure = 1.4; // base exposure (default 1.4), × the preset's `exposure`
weather.pipeline.bloomStrength = 0.35;
weather.pipeline.bloomThreshold = 1.2;
weather.pipeline.ssr = true;The pipeline eases toward the target exposure (exposureAdapt, 1/s). weather.render() snaps on its first frame and then sets it to 2 on every call, so changing it has no effect through the facade.
Presets scale the exposure: downpour uses 0.8, foggyDawn 0.62, drizzle 0.92, and the rest 1. The demo drives weather.exposure from its time-of-day model every frame, so nights get brighter exposure and noon less.
#Render into a target
const rt = new THREE.WebGLRenderTarget(w, h, { type: THREE.HalfFloatType });
weather.render(rt); // then post-process rt.texture yourselfThe output is already tone-mapped. render() doesn't compose with EffectComposer passes directly: render into a target and post-process that, or use the plain path.
#renderer.render()
renderer.toneMapping = THREE.ACESFilmicToneMapping; // your choice
renderer.setAnimationLoop(() => {
weather.update(dt);
renderer.render(scene, camera); // or composer.render()
});The particles are ordinary meshes in your scene, and the materials are patched, so everything except the pipeline effects works. The fog becomes a FogExp2 on scene.fog with matching visibility. The puddles use the material's environment map; set scene.environment for real reflections, otherwise they reflect a sky tint.
Try it: open examples/basic/ from npm run dev. It uses weather.render().
Add ?plain to the URL: examples/basic/?plain switches to renderer.render(scene, camera) with ACES from the renderer.
#Other renderers own the frame
Some libraries own the render, like NatureGL Water's water.render(). Call weather.update(dt) only, let the other library render, and put the particles on its overlay layer. See With other packs.