NatureGL Riverv1.0.0

Guides

Waterfalls

A waterfall joins an upper body of water to a lower one. You give it a lip, a landing point and a width. It builds the falling sheet, the spray and mist, the plunge-pool churn, and a clip that stops the upstream water exactly at the lip.

The demo cascade: a 3 m drop from the outlet at y = 3 onto the main run. Spray droplets and mist are soft particles against the scene depth, and the churn and foam plume come from the plunge in the river shader.

#Add one

js
water.addWaterfall({
  top: new THREE.Vector3(0, 3, -11),       // centre of the lip; y = the upstream water level
  bottom: new THREE.Vector3(0, 0, -9.8),   // where the curtain meets the pool; y = the pool level
  width: 5,
  flow: 1,                                  // streak speed, spray power, plunge foam
});

The horizontal distance from top to bottom is the throw, and the fall direction is bottom − top in xz. For a drop that is almost vertical, where top and bottom share an x and z, pass direction as a Vector2 to say which way the water falls.

#What gets built

PartWhat you see
SheetA ballistic curtain in time of flight from the lip. It starts as glassy, refracting water and becomes an aerated curtain whose streaks speed up as they fall. It widens by 12 % on the way down
VeilA second, slightly wider layer pushed out from the sheet, with ragged edges
SprayAdditive droplets thrown from the plunge, spray: true by default
MistBillowing puffs above the pool, mist: true by default
PlungeDense boiling foam, a foam plume carried downstream, and ripple rings in the pool (drawn by the river or lake surface below)
Lip clipWith clipUpstream: true, water of any body at top.y beyond the lip line is discarded, so the upper river never overhangs the edge
Splash zoneMaterials passed to patchMaterial() get wet in a zone around the plunge

Particle counts come from the quality tier: from 180 spray droplets and 10 mist puffs on low to 1100 and 36 on ultra.

#Line up the bodies

A waterfall doesn't create water above or below it. Put a river or lake at each end.

js
const lip = new THREE.Vector3(0, 3, -11);
const pool = new THREE.Vector3(0, 0, -9.8);

// upstream: stop the outlet exactly at the lip
water.addRiver({ path: [new THREE.Vector3(0, 3, -17), lip], width: 6, extend: [0, 0] });
water.addWaterfall({ top: lip, bottom: pool, width: 5 });
// downstream: start the main river at the landing point
water.addRiver({ path: [pool, new THREE.Vector3(3, 0, 4), new THREE.Vector3(-2, 0, 20)], width: 7 });
  • Use extend: [0, 0] on the upstream river. The lip clip hides any overshoot, but a river that stops short leaves a gap.
  • Start the downstream body at bottom or slightly upstream of it, so the plunge churn lands on water.
  • Make the waterfall's width about the width of the river feeding it. The demo uses 1.7 × the outlet's half width.

#The plunge pool

carveTerrain() digs a bowl at the landing point:

OptionDefault
plungeDepthmin(2.2, 0.6 + 0.3 × drop)Depth below the pool level
plungeRadius0.55 × widthBowl radius. It also sets the size of the churn and the foam plume

A 3 m drop gives a 1.5 m deep pool. The foam strength grows with flow and with the drop, up to 2 m.

The plunge pool from the main run: the churn where the curtain lands, and the foam plume trailing downstream.

#Limits

  • At most 4 waterfalls feed lip clips, plunge foam, ripple rings and splash zones. You can add more, but the fifth one and after only draw their sheet and particles.
  • The sheet is a fixed 28 × 36 grid laid out on a parabolic, ballistic profile. It is shaded to look like falling water, not simulated.
  • flow scales the look, not the physics. There is no mass flow linking a waterfall to the rivers around it.