NatureGL Weatherv1.1.0

Reference

API reference

Everything exported from src/index.js and build/index.js. Types are in build/*.d.ts. Units are metres, seconds and radians, and colours are linear RGB.

js
import {
  WeatherSystem,
  RainSystem, SnowSystem, LightningSystem, FogSystem,
  SurfaceWeather, WeatherAudio, OcclusionMap, WeatherPipeline,
  createWeatherUniforms, MAX_LOCAL_LIGHTS,
  PRESETS, PRESET_LABELS, getPresetParams, QUALITY_LEVELS,
} from 'naturegl-weather';

Wherever a colour is accepted (ColorLike), you can pass a THREE.Color, a THREE.Vector3 or an [r, g, b] array.

#WeatherSystem

#WeatherSystem.create(options): Promise<WeatherSystem>static async

Builds every subsystem, adds the particle meshes (and, by default, the flash lights) to options.scene, applies the quality level and applies the preset instantly. new WeatherSystem(options) does the same synchronously.

OptionTypeDefault
rendererTHREE.WebGLRenderer—Required. WebGL2 with EXT_color_buffer_float for render()
sceneTHREE.Scene—Required. Particles, the bolt and the flash lights are added here
cameraTHREE.PerspectiveCamera—Required. Rain and snow follow it
quality'low', 'medium', 'high', 'ultra''high'See Quality levels
presetstring or WeatherPreset'clear'Applied instantly
lightsbooleantrueAdd a flash DirectionalLight and HemisphereLight for lightning
occlusion{ size, resolution, follow, floor }80, 512, true, 0The top-down occlusion map
managePixelRatiobooleanfalseLet setQualityLevel() cap renderer.setPixelRatio() at the tier's pixelRatio
layernumber—1.1 Render layer for the particle meshes. See setLayer

#Frame

#weather.update(dt): voidmethod

Call once per frame, after moving the camera. dt is in seconds and clamped to 0.1. It reads the camera's current transform, eases the weather toward the targets, gusts the wind, accumulates wetness and snow, fires automatic strikes and the thunder events, drives the fog and the audio, and re-renders the occlusion map when it needs it.

#weather.render(target?): voidmethod

Renders scene through the weather pipeline: HDR scene → volumetric fog at reduced resolution → puddle SSR and fog composite → bloom → exposure × ACES → target (a WebGLRenderTarget) or the screen when null. It replaces renderer.render(scene, camera) and is optional. Leave renderer.toneMapping at its default when you use it. See Render paths.

#weather.resize(): voidmethod

Call after the canvas size or pixel ratio changes. render() also detects size changes on its own.

#weather.dispose(): voidmethod

Removes the meshes and lights, frees GPU resources and closes the audio context.

#Parameters and presets

#weather.loadPreset(preset, { instant? }): voidmethod

Eases to a built-in preset by name, or to a partial WeatherPreset (missing keys come from clear). wetness and snowCover ease over about 4.5 s, then natural accumulation resumes. A preset with lightning > 0 arms a strike 1.5 s later. instant: true snaps everything. Throws on unknown names.

#weather.set(values, { instant? }): voidmethod

Sets any subset of the targets. wetness and snowCover go through wetness.force() (or setImmediate() with instant).

#weather.getParams(): WeatherPresetmethod

The targets plus the current wetness and snow cover, rounded to 3 decimals. JSON-ready, and usable as a preset.

#weather.setQualityLevel(level): voidmethod

Switches tier at runtime: particle counts, fog and SSR steps, fog resolution, shelter taps and the shadowLight's shadow map size. Throws on unknown levels. Read the current level from weather.quality.

Property
params: WeatherPresetThe targets
state: WeatherPreset & { gust, daylight }The eased values in use
transitionRate: numberEasing speed in 1/s (default 0.9)
exposure: numberBase exposure for render() (default 1.4), multiplied by the preset's exposure
quality: stringCurrent quality level
time: numberSeconds of weather time, advanced by update

#Composition

#weather.patchMaterial(material, { ground?, sway? }): Materialmethod

Adds wetness, raindrop ripples, snow cover and shelter to a MeshStandardMaterial or MeshPhysicalMaterial, and returns it. ground: true adds puddles, the full snow blanket and SSR reflectivity. sway: true bends vertices above y = 0.6 m with the wind. Chains an existing onBeforeCompile, and is idempotent. See Wet surfaces.

#weather.setOccluders(objects): voidmethod

The objects that block rain and snow: an array, one object, or null for every visible mesh. They must be in the scene. Objects with userData.weatherOccluder = false are always skipped. Re-renders the occlusion map.

#weather.setLayer(layer): thismethodsince 1.1

Calls layers.set(layer) on the particle meshes (layer 0–31). The same as the layer option of create(). Next to NatureGL Water use water.overlayLayer. The camera must see that layer if you render with renderer.render() or weather.render() yourself.

#weather.setLighting(lighting): voidmethod

Feeds your scene's light to the particles, the fog and the snow glints. Every field is optional, and it's cheap enough to call every frame.

Field
sunDirectionUnit vector toward the key light (sun or moon)
sunColor, sunIntensityKey light radiance. sunIntensity defaults to 1
ambientAmbient radiance for the particles, and for the fog when no sky colours are given
skyHorizon, skyZenithSky colours for SSR misses, the fog tint and a derived ambient. Only applied as a pair
daylight0–1 drying speed. Defaults to a value derived from sunDirection.y
localLightsUp to 4 THREE.PointLights or { position, color, intensity }, read every frame. Contribution = colour × intensity × localLightScale (1/14)
shadowLightA shadow-casting DirectionalLight for shadowed fog shafts. Its shadow map size follows the quality tier
#weather.strike(options?): StrikeEventmethod

A lightning strike now. options.position is a ground point, or options.distance a distance in a random direction roughly ahead of the camera. See LightningSystem.

#weather.on(type, callback): () => voidmethod

Subscribes to 'strike' (immediately) or 'thunder' (when the sound arrives). Returns an unsubscribe function.

Property
particleMeshes: Object3D[]1.1 Rain streaks, splashes, snow and the bolt
uniformsThe shared uniform block, bound by reference in every weather shader and patched material (advanced)
localLightScale: numberLocal light contribution scale (default 1/14)
pipeline: WeatherPipeline | nullCreated by the first render()
rain, snow, lightning, fog, wetness, audio, occlusionThe subsystems, below

#Subsystems

Each subsystem can be constructed on its own. It then creates its own uniforms with createWeatherUniforms() and needs the camera in update(dt, camera). Inside a WeatherSystem they share the facade's uniforms and are updated for you.

#RainSystem

#new RainSystem({ scene, uniforms?, maxDrops?, maxSplashes? })class

Instanced streaks in a 36 × 26 × 36 m box around the camera, and splashes on the occlusion surface within 16 m. maxDrops defaults to 90000 and maxSplashes to 2400.

Member
intensity0–1 (set by the facade from state.rain)
dropCount, splashCountInstances at intensity 1, from the tier
splashesSplashes on or off
snowCover0–1. Splashes fade with it and hide above 0.9
opacityStreak brightness (default 0.32)
streakLengthStreak length multiplier (default 0.55)
mesh, splashMeshThe two instanced meshes
setQuality(q), update(dt, camera?), dispose()

#SnowSystem

#new SnowSystem({ scene, uniforms?, maxFlakes? })class

Swaying billboard flakes in a 34 × 22 × 34 m box. maxFlakes defaults to 42000.

Member
intensity0–1
flakeCountFlakes at intensity 1, from the tier
flakeSizeFlake radius in metres (default 0.022)
meshThe instanced mesh
setQuality(q), update(dt, camera?), dispose()

#LightningSystem

#new LightningSystem({ scene, camera, uniforms?, lights? })class

Branching bolts, multi-pulse flashes, automatic strikes and thunder timing. lights defaults to true.

Member
frequency0–1 automatic strike rate. Off at 0.05 and below
minDistance, maxDistanceRandom strike range, 110 / 370 m
strike({ position?, distance? })Strike now. Returns the StrikeEvent
on('strike' | 'thunder', cb), off(type, cb)Events. on returns an unsubscribe function
flashCurrent flash, 0 to about 1.5
flashDirectionUnit vector from the camera to the last bolt's top
thunderInSeconds until the last thunder (negative once it has arrived)
lastStrikeThe last StrikeEvent, or null
flashLight, flashHemiThe flash lights, or null with lights: false
scheduleSoon(seconds = 1.5)Arm the next automatic strike
meshThe bolt mesh

StrikeEvent is { position, top, direction, distance, delay }, with delay = distance / 343.

#FogSystem

#new FogSystem({ scene?, uniforms? })class

Maps the weather to height-fog values, and drives scene.fog when the pipeline isn't used.

Member
densityExtinction at the fog base, 1/m
heightExponential height falloff, m
baseHeightWorld height where the fog is densest (default 0)
lightIntensityIn-scattering multiplier (from fogLight)
raysShadowed shafts on or off
maxDistanceRaymarch distance (default 170 m)
visibilityRead-only: 3 / density, in metres
sceneFog'auto' (default), true or false
windOffsetFog drift, advanced by the wind

#SurfaceWeather

#new SurfaceWeather({ uniforms? })class

The wetness and snow model, and the material patch behind weather.patchMaterial.

Member
wetness, snowCover0–1, current
puddlesPuddles on or off
rateAccumulation speed multiplier (default 1)
force(wetness, snowCover = null, seconds = 4.5)Ease toward these values, then resume. null leaves one alone
setImmediate(wetness, snowCover)Jump there now
patchMaterial(material, options)See weather.patchMaterial
setQuality({ shelterTaps })Recompiles the patched materials
materialsSet of patched materials

#WeatherAudio

#new WeatherAudio()class

Synthesized rain hiss, gusting wind and distance-filtered thunder (WebAudio, no assets). Muted by default.

Member
unmute()Start or resume. Call from a user gesture
mute(), setEnabled(on)
mutedtrue until unmute()
volumeMaster volume, 0–1 (default 0.7)
update(rain, wind, gust), thunder(delay, distance)Called by the facade
contextThe AudioContext, created on the first unmute()
dispose()

#OcclusionMap

#new OcclusionMap({ renderer, scene, uniforms?, size?, resolution?, top?, depth?, follow?, floor? })class

A top-down depth map around the camera. Defaults: size 80 m, resolution 512, top 40 m, depth 60 m, follow true, floor 0.

Member
setOccluders(objects)Restrict the map to these objects, or null for the whole scene
excludeSet of objects never drawn into the map
needsUpdateSet true to re-render on the next update
render()Re-render now
update(camera)Re-centres when the camera leaves the middle 40 %
setFloor(y)Height returned where nothing was drawn
center, baseY, depthTexture

#WeatherPipeline

#weather.pipelineWeatherPipelineproperty

Created by the first weather.render().

Member
exposureWritten by weather.render() every frame: set weather.exposure instead
exposureAdaptExposure easing, 1/s. weather.render() keeps it at 2
bloomStrength, bloomThreshold0.35, 1.2
ssrPuddle SSR on or off
shadowLightFrom setLighting
skyHorizon, skyZenithVector3 sky colours for SSR misses
setQuality(q), resize(), render(scene, camera, dt, target)

#Other exports

Export
PRESETSRecord<string, WeatherPreset>, the seven built-in presets
PRESET_LABELSDisplay names, such as 'Foggy Dawn'
getPresetParams(name)A deep clone. Throws on unknown names
QUALITY_LEVELSRecord<level, QualitySettings>. See Quality levels
MAX_LOCAL_LIGHTS4
createWeatherUniforms()A fresh shared uniform block, for standalone subsystems