NatureGL Riverv1.0.0

Reference

API reference

Everything exported from src/index.js and build/index.js. Units are metres, seconds and radians unless noted; preset angles are degrees. The types are in build/index.d.ts.

js
import {
  RiverSystem, River, Lake, Waterfall, RiverPath, Floaters,
  PRESETS, getPresetParams, QUALITY_LEVELS,
} from 'naturegl-river';

#RiverSystem

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

Builds the system: the render target with its depth texture, the overlay scene, the optional sky dome (added to options.scene) and the water map. new RiverSystem(options) does the same synchronously.

OptionTypeDefault
rendererTHREE.WebGLRenderer—Required. WebGL2
sceneTHREE.Scene—Required. Your world; only the sky dome is added to it
cameraTHREE.PerspectiveCamera—Required
quality'low', 'medium', 'high', 'ultra''high'See Quality levels
presetstring or preset object'clear'A complete preset; see Presets
builtInSkybooleantrueAdd the analytic sky dome. It is removed while setSky() is active
manageFogbooleantrueCreate and update a FogExp2 on scene from the preset
manageExposurebooleantrueSet renderer.toneMappingExposure from the preset
manageToneMappingbooleantrueSwitch NoToneMapping to ACESFilmicToneMapping

It throws if renderer, scene or camera is missing.

#Frame

#water.update(dt): voidmethod

Call once per frame, before render(). It advances time (dt in seconds, clamped to 0 – 0.1), eases the displayed values toward params, rebuilds meshes after authoring or quality changes, re-renders the water map when bodies change, applies lighting, fog and exposure, picks the nearest obstacles and moves the floaters.

#water.render(output?): voidmethod

Draws the whole frame: scene into the HalfFloat render target with a DepthTexture, then the overlay (composite of that target, tone mapped with depth restored, then lakes, rivers, waterfall sheets, mist and spray). Use it instead of renderer.render(scene, camera). Pass a WebGLRenderTarget as output to draw somewhere other than the screen, for example for your own post-processing.

#water.resize(): voidmethod

Matches the internal target to renderer.getDrawingBufferSize() × the tier's rtScale. Call it after renderer.setSize() or setPixelRatio(). render() also checks the size on every frame.

#water.dispose(): voidmethod

Frees every GPU resource, removes the sky dome and the library's meshes, and clears the floaters.

#Authoring

#water.addRiver(options): Rivermethod

Adds a ribbon along a spline. The mesh is built on the next update() or render().

OptionDefault
path—Vector3[], at least 2 points. Centripetal Catmull-Rom. y is the water level
width / widths6Full width in metres, constant or one per path point
depth / depths1.5Depth at the centre, constant or per point. Used by carveTerrain
flowSpeed1.5Centre-line surface speed at the mean width (m/s)
conserveFlowtrueSpeed ∝ 1 / width (constant discharge)
margin0.4Ribbon extension past each bank, as a fraction of the half width
extend0.3 × mean half widthMetres past the path ends, number or [start, end]
fade'auto'[in, out] metres of alpha fade. 'auto' fades ends inside a lake
bankSlope0.32Carve: bank rise per metre
bankWidth1.2Carve: blend width beyond the bank, in half widths
endBlendmean half widthCarve: how fast the channel fades out past the path ends (m)
normalScale, foamScale1, 1Per-body multipliers
nameriver-<id>Mesh name

See Rivers and lakes.

#water.addLake(options): Lakemethod

Adds calm, flat water inside a polygon or a circle. Give polygon, or center and radius; otherwise it throws.

OptionDefault
polygon—Vector2[] (x, z) or Vector3[] (y ignored), at least 3 points
center, radius—A circle instead
levelcenter.y, or 0Water level
depth2.5Basin depth
shelfradius / 2, or 5 for polygonsDistance from the shore to full depth
driftVector2(0.03, 0.05)Slow surface drift (m/s); floaters feel it too
margin1.5Mesh extension past the shore (m)
bankSlope, bankWidth0.3, 6Carve
calm1Suppresses the standing-wave detail, 0 – 1
normalScale, foamScale0.55, 0.6
namelake-<id>
#water.addWaterfall(options): Waterfallmethod

Adds a cascade from a lip to a pool.

OptionDefault
top—Centre of the lip; y is the upstream level
bottom—Where the curtain meets the pool; y is the pool level
width—Curtain width
flow1Streak speed, spray power, plunge foam
directionbottom − top in xzVector2 fall direction, for near-vertical drops
plungeDepthmin(2.2, 0.6 + 0.3 × drop)Carve depth of the pool
plungeRadius0.55 × widthCarve radius and foam radius
clipUpstreamtrueDiscard water at top.y beyond the lip line
spray, misttrue, trueParticles
namewaterfall-<id>

Up to 4 waterfalls feed lip clips, plunge foam, ripple rings and splash zones. See Waterfalls.

#water.addObstacle(position, radius, strength = 1): Obstaclemethod

Adds a foam ring, bow pillow and downstream wake. position is a Vector3 or { x, z }, and radius is measured at the waterline. Returns { position, radius, strength }; edit it in place to move the obstacle. Each frame the nearest maxObstacles to the camera are used.

#water.removeObstacle(obstacle): voidmethod

Removes an obstacle returned by addObstacle().

#water.remove(body): voidmethod

Removes a River, Lake or Waterfall and disposes its geometry.

#water.carveTerrain(heightFn): (x, z) => numbermethod

Returns heightFn with every current body's bed, basin and plunge pool blended in, and low banks raised to the water. Where bodies overlap the lowest result wins. It's a snapshot: call it again after adding or removing bodies. See Terrain and materials.

#water.patchMaterial(material): materialmethod

Injects the waterline wet band, splash zones, underwater tint, sun attenuation, caustics and caustic reflections into a MeshStandardMaterial or MeshPhysicalMaterial. Lambert and Phong get the colour and caustic parts. Chains an existing onBeforeCompile; patching the same material twice does nothing. Returns the material.

#Queries

#water.sample(x, z): WaterSample | nullmethod

The highest water surface at (x, z): { height, flow: Vector2, speed, edge, inside, body }. flow and speed include the global water.flow multiplier. null where there is no water. See Flow, rocks and floaters.

#water.sampleHeight(x, z): number | nullmethod

The water level, or null.

#water.sampleFlow(x, z, target?): Vector2 | nullmethod

The surface velocity in m/s, copied into target (a new Vector2 if omitted), or null.

#water.isInWater(x, z): booleanmethod

true inside a river's banks or a lake's shore.

#water.isUnderwater(camera?): booleanmethod

true when the camera (default: the system's) is below a water surface. Nothing is rendered differently.

#water.getFlowMultiplier(): numbermethod

The eased water.flow value.

#Sky and lights

#water.setSky(sky | null): voidmethod

Uses an external sky. Every field is optional and read by reference each frame: sun: { direction, color?, intensity? }, envMap (equirect), envIntensity, cloudShadow: { texture, matrix }, fogColor, skyColor. While set, the built-in dome is removed and bound lights aren't driven. null restores the built-in sky. See Sky and lights.

#water.bindLights(directional, hemisphere?, distance = 120): voidmethod

Lets the preset drive a DirectionalLight (colour, intensity, and position at target.position + sunDirection × distance) and a HemisphereLight. Either can be null. Only active with the built-in sky.

#Presets and quality

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

Replaces params with a preset name or a complete preset object. Lighting eases over about 1.5 s and water over about 0.3 s; instant: true snaps. Throws on an unknown name.

#water.getParams(): RiverPresetmethod

A deep copy of the current settings, in preset format.

#water.setParam(path, value): voidmethod

Sets one value by dotted path, for example setParam('water.clarity', 1.4) or setParam('light.sunColor', '#ffd9a0').

#water.setQualityLevel(level): voidmethod

Switches tier: recompiles the water shaders and patched materials, rebuilds meshes, resizes the water map, and recreates the render target when MSAA changes. Unknown levels and the current level are ignored.

#Properties

Property
paramsThe settings you set, in preset format. Live: edit it directly
lightingCurrent { sunDirection, sunColor, sunIntensity, hemiSky, hemiGround, hemiIntensity, fogColor, fogDensity, exposure }
floatersThe Floaters instance
qualityLevel, qualityThe tier name and a copy of its settings
rivers, lakes, waterfalls, obstaclesThe authored bodies, read-only by convention
timeSeconds accumulated by update()
externalSkyThe object passed to setSky(), or null
renderer, scene, cameraAs passed to create()

#Floaters

#water.floaters.add(obj, options?): objmethod

Floats anything with a position (and optionally a rotation) from its current xz.

OptionDefault
radius0.3
drag0.9Fraction of the surface velocity it reaches
bob0.012Bob amplitude (m)
draft0Height offset from the surface (m)
spin0.4Yaw rate while drifting
alignfalseYaw along the velocity instead of spinning
onExit—(obj) => void, called when it leaves the water
#water.floaters.remove(obj): voidmethod

Stops floating obj.

#water.floaters.clear(): voidmethod

Removes every floater.

#Bodies

River, Lake and Waterfall are returned by the add* calls. You rarely construct them yourself.

Member
type'river', 'lake' or 'waterfall'
name, id
meshRiver and lake surface mesh (in the overlay scene), null until built
groupWaterfall sheet and particle group
sample(x, z)This body's own sample, without the global flow multiplier: { height, flowX, flowZ, speed, inside, edge } or null
carve(x, z)[profileHeight, weight] or null
River.pathIts RiverPath
Lake.signedDistance(x, z)Distance to the shore, negative inside
Waterfall.plunge, .drop, .directionThe landing point, the height of the drop and the fall direction

#RiverPath

#new RiverPath(points, options?)class

A centripetal Catmull-Rom centre line, resampled by arc length every 0.5 m, with per-sample level, half width, depth and tangent, and a uniform grid for fast nearest-point queries. options takes width, widths, depth, depths, and step (resample spacing, default 0.5 m).

#path.query(x, z, out?): PathSample | nullmethod

The nearest point on the centre line: { s, lateral, dist, overshoot, level, halfWidth, depth, tx, tz, slope }. s is metres along the path, lateral the signed distance across, and overshoot the distance past either end.

Also: length, meanHalfWidth, maxHalfWidth, count and the sample arrays x, y, z, tx, tz, s, hw, depth.

#Presets and quality exports

#PRESETS: Record<string, RiverPreset>const

Every built-in preset by name: clear, morning, golden, overcast, glacial, muddy, swamp, dusk, night.

#getPresetParams(name): RiverPresetfunction

A deep clone of a built-in preset. Throws on an unknown name.

#QUALITY_LEVELS: Record<QualityLevel, QualitySettings>const

{ rtScale, samples, ssrSteps, normalLayers, maxObstacles, ribbonStep, crossSegments, spray, mist, waterMap, causticLayers } per tier. See Quality levels.