NatureGL Riverv1.0.0

naturegl-river v1.0.0

Rivers you draw with a spline

NatureGL River turns a few points into a flowing river, a calm lake or a waterfall in your three.js scene. It carves the terrain to match, wets the rocks at the waterline and throws caustics on the bed. The water absorbs light by depth, so the shallows stay clear and the pools go dark.

$ npm install && npm run dev

#Author water like you author geometry

Give addRiver() a centre line whose y is the water level, then add a lake with addLake() and a cascade with addWaterfall(). carveTerrain() cuts the channel, the basin and the plunge pool into your own height function, so the ground and the water always agree.

Follow the quick start or see how rivers are built.

The demo valley under the golden preset: a brook fills the upper lake, the outlet runs to the lip, and the cascade drops 3 m into the plunge pool.
body types: river, lake, waterfall
3
presets, one file each
9
quality tiers, low to ultra
4
display cap on high, Apple M5, 1280×720
120 fps

#What's in the box

#Nine looks, ready to load

Each preset is one file in src/config/presets/ with a water block and a light block. Switch with loadPreset(), which eases the change in, or edit single values with setParam().

ClearclearClear mountain stream at noon: turquoise over pebbles, strong caustics.
Golden hourgoldenLong light and warm glints on the ripples.
Glacial meltglacialMilky turquoise rock-flour water, faster and foamier.
Muddy spatemuddyBrown, opaque and fast, with heavy foam and almost no caustics.
SwampswampTannin-dark, slow, glassy water under a greenish haze.
NightnightMoonlit: stars, dim moon glints and dark water.

See all nine presets

#A river, a lake and a waterfall in one screen of code

main.js
import * as THREE from 'three';
import { RiverSystem } from 'naturegl-river';

const water = await RiverSystem.create({ renderer, scene, camera, preset: 'clear' });
water.addLake({ center: new THREE.Vector3(0, 3, -24), radius: 9 });
water.addWaterfall({ top: new THREE.Vector3(0, 3, -11), bottom: new THREE.Vector3(0, 0, -9.8), width: 5 });
water.addRiver({
  path: [-9.8, -2, 6, 14, 24].map((z, i) => new THREE.Vector3(Math.sin(i * 1.3) * 4, 0, z)),
  width: 7, depth: 1.6, flowSpeed: 1.6,
});
const height = water.carveTerrain((x, z) => 0.6 + Math.max(0, Math.abs(x) - 5) * 0.2);

renderer.setAnimationLoop(() => {
  water.update(timer.getDelta());
  water.render();                  // replaces renderer.render(scene, camera)
});

#Light that reaches the bed

The clear preset at noon, close to the bank. Caustics focus with depth and animate faster where the water runs faster. The wet band on the stones laps with the ripples.

#Part of the NatureGL series

NatureGL River takes its sun, reflections and cloud shadows from any sky-like object through setSky(), including NatureGL Sky's SkySystem. Its height and water queries are plain functions, so NatureGL Grass can grow along the banks and stop at the water.