Skip to content
Back to skills

Threejs Webgl Waterfall Effect

ASecurity

Builds a stylised-realistic waterfall in three.js WebGL that pours off a heightfield cliff's true lip into a carved plunge basin — layered parabolic sheets (glassy at the lip, aerated and streaky below, tearing into spray), side threads, a wet ledged rock face, rising spray billboards with a 42° rainbow, ballistic droplets, rings and froth on the pool, and boulders at the foot. Use when the user wants a waterfall, cascade, spring, plunge pool, spray/mist with a rainbow, or water falling off t...

  • 2 stars
  • 0 votes
  • 0 copies
  • 7 views
  • Added September 27, 2026
ai-agentsgonodespringaws

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 27, 2026

npx -y skills add nicksonthc/ghibli-threejs --skill threejs-webgl-waterfall-effect --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Threejs Webgl Waterfall Effect?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Threejs Webgl Waterfall Effect
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nicksonthc-threejs-webgl-waterfall-effect/badge)](https://www.skillsdirectory.com/skills/nicksonthc-threejs-webgl-waterfall-effect)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: threejs-webgl-waterfall-effect
description: Builds a stylised-realistic waterfall in three.js WebGL that pours off a heightfield cliff's true lip into a carved plunge basin — layered parabolic sheets (glassy at the lip, aerated and streaky below, tearing into spray), side threads, a wet ledged rock face, rising spray billboards with a 42° rainbow, ballistic droplets, rings and froth on the pool, and boulders at the foot. Use when the user wants a waterfall, cascade, spring, plunge pool, spray/mist with a rainbow, or water falling off terrain in a three.js / R3F scene.
---

# Waterfall: lip, basin, sheets, spray, rainbow

A waterfall that reads from far away and close up: water tipping glassy over an overhanging lip,
turning white and streaky as it accelerates, tearing into spray where it strikes a plunge basin
it has dug into the cliff's foot; a dark wet rock face behind it; spray puffs boiling up with a
faint rainbow when the sun is behind you; droplets thrown out; rings and froth running across the
pool. Everything is procedural geometry + `ShaderMaterial`/patched `MeshStandardMaterial` in a
three.js `WebGLRenderer` scene with a terrain height function and a water SDF (see
`threejs-open-world-streaming`) and water from `threejs-webgl-realistic-water`.

## When to use
- The terrain has (or can have) a cliff and you want water to fall from it into a pool.
- You need spray/mist that doesn't show a hard line at the water plane, or a physically placed rainbow.

## Paste-ready prompt

> A waterfall in `{{scene}}` that pours off the cliff's true lip into a plunge basin cut into its foot:
> - a wet rock face behind it;
> - three sheet layers on a parabola, glassy at the lip, white and aerated below, tearing into spray at the foot;
> - thin side threads;
> - rising spray puffs that fade at the water, with a rainbow at 42° from the antisolar point;
> - ballistic droplets;
> - rings and froth on the water;
> - boulders at the foot.
>
> **Check the geometry numerically before shading:** print a height grid round the site, find the
> real lip, and confirm the sheet's foot lands in water. Syntax-check the module with `node --check`
> before every reload.

## Implementation

### 1. Site geometry first
- **Plunge basin:** smooth-union a small ellipse into the river's signed distance
  (`d = smin(d, hypot((x − px)·0.8, z − pz) − r, 1.5)`), and multiply the cliff term in
  `terrainHeight` by `smooth(−0.3, 2.4, dPlunge)` so the cliff is notched steeply round it. The water
  plane already exists everywhere under the terrain, so carving the terrain is enough.
- **Find the lip where the cliff actually is:** from the basin, walk back up the notch wall in 10 cm
  steps until the ground is above a threshold (≥ 4 m here) *and* levels off
  (`h(z − .4) − h(z) ≤ .12`). The first version sampled the lower slope: the fall came out 3.6 m
  tall, started in mid-air, and its foam disc was buried under the terrain.

### 2. Wet rock face over a heightfield cliff
For each (angle a ∈ ±1.8 rad, height y) bisect along a ray from the basin centre to where the ground
reaches that height (24 steps); if it never does, tuck the vertex underground. Then pull the vertex
out by relief (`.16 + .42n + .16n2 + .26·ledge`, ledges `fract(y·.62 + n)³`, seams), add an
overhanging roll just under the lip (`.55·exp(−(a/.3)²)`), and push it back into the turf at the sides
and top so it emerges rather than ending in a hard panel. Vertex COLOR_0 with moss in alpha.
Reuse the rocks' shader (`threejs-stylized-rock-material`) and inject extra wetness by
string-replacing its rain term: `uRain*.85)` → `max(uRain*.85, cliffWet(vWPos)))`; soaked rock goes
dark `×(.5, .58, .56)`, dry rock gets long vertical stains.

### 3. Sheets (three layers + threads)
Grid 10 × 44 (+3 rows of "tongue" sliding to the lip along the ground). Row v ∈ 0..1:
`y = top − v·(top − yBot)`, `z = lip.z + zOff + throw·√v + bow·(1 − (2u−1)²)·(.25 + .75v)`
(out ∝ √drop — a parabola), width widening `× (1 + v·spread)`.
Layers `[width×, zOff, spread, bow, [speed, alpha, streak density, seed]]`:
back `[1.14, −.22, .36, .12]`, main `[1, 0, .28, .24]`, front `[.78, .15, .2, .3]`. Two thin threads
either side at `±(W/2 + 1.1)` falling onto catch-stones.

Fragment: **streak coordinate `f = √v·k − t·speed`** so streaks stretch as the water accelerates;
`aer = smoothstep(0, .2, v)` (glassy → aerated); frayed edges that widen with aeration; alpha tears
into spray over the last 22%; a bright roll at v ≈ 0.012
(`.45·exp(−((v − .012)/.014)²)`); colour teal-glass → white. `transparent`, `depthWrite: false`,
`DoubleSide`, fog on. See `references/waterfall-sheet.js`.

### 4. Spray + rainbow
30 instanced view-facing puffs born at the strike, swelling (`.8 + 3ph`) and rising (`ph²·5.5`) as they
drift out, fading in/out over their life.
- **Mist billboards:** fade alpha by the *corner's* world height — for a view-space quad,
  `world y = c.y + (viewMatrix[1][0]·x + viewMatrix[1][1]·y)·size`. This removes the hard line where a
  puff crosses the water plane.
- **Rainbow:** `θ = acos(dot(viewDir, −sunDir))`, band 40.7–42.4° (k = (θ − .706)/.036), hue violet
  (inner) → red (outer), only by day and with the sun above the horizon. **Let it raise the puff's
  alpha as well as its colour** (`a·(.17 + .3·bow)`), or it vanishes at spray opacities.
  Test by setting a low sun behind the camera for one frame.

### 5. Droplets, rings, froth, boulders
- 900 ballistic points: `p = origin + v0·t − (0, 4.2t², 0)`, life 0.7–1.5 s, sized in metres
  (`gl_PointSize = size·uPx/−mv.z`, `uPx = drawingBufferHeight/(2·tan(fov/2))`), culled below water.
- Water shader: a `uFall = (x, z, halfWidth, on)` uniform; rings run out from the strike *line*
  (`sin(L·6.5 − t·5.2 + noise)·exp(−L·.3)`), churn noise `exp(−L²·.9)`, froth
  `smoothstep(.3, .85, (exp(−L·.6) + .4·churn)·(.4 + .95n))·.9`.
- Boulders: two big ones flanking the strike, catch-stones under the threads, a few breaking the
  surface in front, a ring round the basin — instanced from the rock GLBs with caustics.
- Put spray and droplets on layer 1 (refraction pass skips them); cull them past ~160 m.

## Pitfalls
- **Transparent sheets, foam, mist and spray print as dark panels** because the AO pass draws them
  as solid — put them in the AO/pre-pass hidden list.
- Sampling the lip on the lower slope → a short fall starting in mid-air, landing on a dry shelf.
- `Math.exp(-(a/.3)**2)` is a **SyntaxError** (a unary minus before `**`) and the whole module fails
  — write `Math.exp(-((a/.3)**2))`. Run `node --check` on the extracted module before every reload.
- A rainbow that only tints colour disappears at spray alpha (~0.17).
- A `// comment` dropped mid-line in a one-line function silently comments out the rest.

## Verify
- Print a height grid round the site; confirm lip height, basin depth, and that the sheet foot is in water.
- Screenshot from the pool, from the side (parabola), and from above.
- Low sun behind the camera for one frame → the bow appears at ~42°.
- Look along the waterline for hard puff edges or dark sheets (AO).

## Related skills
`threejs-webgl-realistic-water` · `threejs-stylized-rock-material` · `threejs-open-world-streaming`
· `threejs-postprocessing-anime-grade` · `threejs-headless-visual-verification` · `threejs-day-cycle-lighting`

Files in this skill

  • SKILL.md7.3 KB
  • references/waterfall-sheet.js7.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.