§ Examples

What ships in the kit

Every still below is a frame from the regression rig — the same frames the test suite checks on WebGPU and WebGL2 — so what you see is what the code renders. The demo scenes are one zip-open away (demo/index.html); the example pages live in examples/ and import ../src directly, no build. Each card names the handbook section that explains it.

Scenes in the live demo

Breaking waves rolling onto a sand beach

Beach — shallow water & breaking surf

A depth field fades the swell as the bed rises; an analytical shore train shoals, breaks at H/h = 0.78 and washes up a wet-sand band. The boat grounds.

shallow.setDepthFunction((x, z) => 0.018 * (z + 150) + 0.4).bake();
new OceanFFT({ ..., shallowWater: shallow });
open in demo§ coast
A breaker from the beach, foam lip and swash

The break zone

Green's-law shoaling, a steepening face, the foam lip, the bore and the swash — all from one setWave call, in the shader and in the CPU mirror the hulls read.

shallow.setWave({ period: 7, amplitude: 1.15, steepness: 0.85, trainReach: 3.2 });
debug views 19–21§ shore train
A fishing trawler under way among channel buoys

Harbour — drop-in boats

The trawler is a CC0 glTF through attachHull: measured, seated, buoyant, masked, with bow + stern wake and spray, on a waypoint patrol. The yacht is the anchored kind.

const hull = attachHull(gltf.scene, { ocean, buoyancy, waterMask, wakeField, scene, length: 26, kind: "dynamic" });
hull.setInput({ throttle: 0.55, steer });
open in demo§ drop-in boats
Dock lamps glinting on dark water at night

Night harbour — lights on the water

Buoy lamps and dock posts glint in the surface shader (six slots, point or spot, lights or descriptors) plus a moon path; Hurricane flashes lightning through the same slots.

ocean.setLights(harbour.getLights(night));
ocean.setMoon(moonDir, 0xa9bfe8, 0.55 * night);
open in demo§ lights
A river channel with a current carrying the boat

River — flow maps

A current field advects ripple normals and foam streaks and drifts every floater downstream; the banks come from the same depth field as the beach.

flow.setFlowFunction((x, z) => riverFlowAt(x, z)).bake();
buoyancy.setFlow(flow, 1);
open in demo§ flow maps
Crates dropped into the sea, splashing and drifting

Crates — anything touches water

Press F: a crate drops, splashes (ripple ring + spray burst), bobs, rides the current and stamps a wake when it moves.

interaction.add(crate, { radius: 0.8, depth: 0.4 });
interaction.update(dt, ocean.simTime);
F in the demo§ interaction
Caustics on the sea floor, dark under the hull

Occluded caustics

A light-space depth map of hulls, dock and sea stacks; seabed caustics, prop caustics and the light shafts go dark beneath them.

const occ = createSunOcclusion(renderer, scene, { size: 512, extent: 200 });
setCausticOcclusion(occ); occ.add(boat);
dive with Q§ occluded caustics
A school of fish over the reef

Underwater — schools, shafts, scatter

Boid fish schools that part around the boat, sun in-scatter in the fog, light shafts faded by the water, prop-wash bubbles behind a driven hull.

underwater.update(t, dt, camera, { sun, threat: boat.position, motion: boat.getMotionState() });
open in demo§ underwater
Bubble trail behind a speeding hull seen from below

Prop wash from below

The hull's motion state drives a bubble plume at the stern; the same state feeds the spray, the wake generators and the water mask.

hull.getMotionState(); // { x, y, z, heading, speed, slam, halfLen, halfWid }
W then Q in the demo§ drop-in boats
A storm sea under a lightning flash

Hurricane — lightning

The storm mode schedules strikes; each one is a light descriptor in slot 5 plus a sky flash, so the sea answers with a glint path like any lamp.

ocean.setLights([...lamps.slice(0, 5), { position: strike, color: 0xd6e4ff, intensity: 9e4 * flash }]);
open in demo§ lights

Example pages in examples/

An island with a raised lake beside the open sea

multi-body.html — several water bodies

Open sea plus a hill lake at +6 m and a rock pool at +9 m, each its own OceanFFT with its own spectrum, colours and bed, sharing one sky.

const lake = new OceanFFT({ geometry: "plane", size: 216, reflector: false, ... });
lake.position.y = 6;  sea.setReflectionLayers(camera, [3, 7]);
examples/multi-body.html§ multiple bodies
A sunset sea rendered through React Three Fiber

r3f.html — React Three Fiber

<Tidewater> and <Ocean> from r3f/, run straight off esm.sh with no build; mode buttons, a time slider, crates that ride the exact CPU height mirror.

<Canvas gl={createTidewaterRenderer}><Tidewater mode="sunset"><Ocean /></Tidewater></Canvas>
examples/r3f.html§ react three fiber
A calm sea in the water-canvas element

water-canvas — one HTML tag

The custom element for non-Three.js pages: mode, time, controls, quality, dynamic resolution and the deterministic clock as attributes.

<water-canvas mode="reef" time="14:00" controls="orbit" dynamic-resolution="60"></water-canvas>
live page§ web component
Two clients rendering the same deterministic sea

multiplayer.html — two clients, one sea

Same seed, same tick, same wave on every client; add latency and jitter, knock one out of step and watch NetClock slew it back.

el.netClock = new NetClock({ ... }); el.syncToTick(host.tick);
live page§ multiplayer sync