NatureGL Weatherv1.1.0

Guides

Composing with other packs

NatureGL Weather renders into a scene you own. It takes its light from whatever lights your world, draws its particles on whatever layer the frame needs, and patches any standard material, including ones other libraries have already patched.

#The contract

  • Particles are meshes in your scene. Rain streaks, splashes, snow and bolts are four transparent meshes (weather.particleMeshes). They follow the camera, and nothing is drawn outside your render.
  • Light comes in through setLighting(). The library has no sky of its own. It uses the key light, ambient and sky colours you pass. That's cheap enough to call every frame.
  • Materials are patched, not replaced. patchMaterial() chains any existing onBeforeCompile and program cache key.
  • The render is optional. weather.update(dt) does all the simulation, so another library can own the frame.

#Light from NatureGL Sky

NatureGL Sky computes a key light (the sun by day, the moon at night), an ambient colour and a horizon colour every frame. Hand them over after sky.update:

js
import { SkySystem } from 'naturegl-sky';
import { WeatherSystem } from 'naturegl-weather';

const sky = await SkySystem.create({ renderer, scene, camera, preset: 'storm' });
const weather = await WeatherSystem.create({ renderer, scene, camera, preset: 'downpour' });

renderer.setAnimationLoop(() => {
  sky.update(dt);
  weather.setLighting({
    sunDirection: sky.keyLight.direction,
    sunColor: sky.keyLight.color,
    sunIntensity: sky.keyLight.intensity,
    ambient: sky.ambient.color,
    skyHorizon: sky.fogColor,
  });
  weather.update(dt);
  renderer.render(scene, camera);
});

NatureGL Sky has its own rain veils and lightning inside the clouds (precipitation, lightning in its params). Use its storm or monsoon preset for the sky and NatureGL Weather for the rain around the camera. NatureGL Sky's sky.lightning reports its flash, and NatureGL Weather's weather.lightning.flash reports its own. They aren't synchronised, so pick one to drive your lights.

Both libraries can patch the same material. NatureGL Sky's patchMaterial adds cloud shadows, NatureGL Weather's adds wetness, and each chains the other:

js
sky.patchMaterial(terrain.material);                        // cloud shadows
weather.patchMaterial(terrain.material, { ground: true });  // wetness, puddles, snow

#Rain over NatureGL Water

NatureGL Water's water.render() owns the depth pipeline, the tone mapping and scene.fog. Transparent objects in its main pass are drawn under the water surface. So:

  1. Put the particles on water.overlayLayer, which NatureGL Water draws after the water, depth-tested against it.
  2. Stop NatureGL Weather from driving scene.fog.
  3. Don't call weather.render().
js
const weather = await WeatherSystem.create({ renderer, scene, camera, layer: water.overlayLayer });
// or later: weather.setLayer(water.overlayLayer);
weather.fog.sceneFog = false;   // NatureGL Water manages scene.fog (FogExp2)

renderer.setAnimationLoop(() => {
  weather.update(dt);
  water.update(dt);
  water.render();
});

setLayer(layer) calls layers.set(layer) on every particle mesh and returns the weather, so it chains. Do the same for your own transparent particles. The overlay layer defaults to 30 in NatureGL Water.

#NatureGL Island, as a worked example

NatureGL Island runs all three. Its optional rain mode, in src/world/rain.js, is a compact reference:

naturegl-island/src/world/rain.js (excerpt)
const w = await WeatherSystem.create({
  renderer: g.renderer, scene: g.scene, camera: g.camera,
  quality: g.qualityName === 'ultra' ? 'high' : 'medium', preset: 'clear',
  lights: false,                                  // the game flashes its own lights
  occlusion: { size: 80, resolution: 256 },
  layer: g.water.overlayLayer,                    // draw after the ocean
});
w.fog.sceneFog = false;
w.setOccluders([g.village.group, g.vegetation.group, g.boat.group]);
w.patchMaterial(g.terrainMesh.material, {});      // also patched by NatureGL Sky for cloud shadows
w.patchMaterial(g.village.material, {});

// toggling rain on
w.set({ rain: 0.85, wind: 0.65, fog: 0.1, lightning: 0.25, wetness: 1 });

// per frame
w.setLighting({ sunDirection: s.keyLight.direction, sunColor: s.keyLight.color, sunIntensity: s.keyLight.intensity,
  ambient: g.hemi.color.clone().multiplyScalar(g.hemi.intensity), localLights: g.village.lights });
w.update(dt);

#Any other renderer or library

  • Your own post chain. Render with renderer.render() or composer.render(). Everything but the volumetric fog, SSR and bloom works. See Render paths.
  • Other material patches. patchMaterial chains onBeforeCompile and customProgramCacheKey, so NatureGL Grass's or your own patches can sit on the same material.
  • Custom shaders. weather.uniforms is the shared uniform block, and its values update in place every frame.
  • Your own sky. Do what the demo does: compute a key light and sky colours from your time of day and pass them with setLighting every frame. The presets' time and cloud are suggestions for that sky.