Making water visible. Waterscape is an umbrella for explorable visual representations of real water systems. Public data supplies the evidence; scientific state and explicit visual bindings connect that evidence to landscapes, charts, animation and interaction.
A curated Waterscape resource library tracks useful web graphics, simulation, rendering and visual-development references, including the upstream licence status for each resource.
| Experience | What it shows | Status |
|---|---|---|
| Reservoirs | Calaveras, San Antonio, Crystal Springs, San Andreas and Hetch Hetchy (with O'Shaughnessy Dam): lidar landscapes, sourced context, modeled water optics and aerial maps | Live journey and WebGPU explorer |
| River Pulse | A living river atlas: California relief and six rivers, each with a start, a scenic middle and an end, real USGS data where it exists, and authored 3D places | Live prototype; illustrative water and authored settings, no local hydrodynamic model |
Explore River Pulse → or go straight to the reference river: Hacienda Bridge and Jenner Estuary.
Water systems are hard to understand because their most important processes are invisible. Waterscape's guiding principle is to make them visible: real data provides the backbone, science determines the relationships, and visual interpretation makes those relationships visible. Every visual binding is one of four kinds: exact (directly presents a scientific quantity), derived (a defined visual transformation of scientific state), illustrative (emphasis of a supported concept without claiming literal physical accuracy) or setting (the grass, trees and sky that make people want to look, kept plausible for the place but carrying no scientific claim). Binding class describes the presentation; provenance and modeling status stay with the underlying state. Exaggeration is allowed when it clarifies, and every scientific claim must trace to a source, calculation or clearly identified illustrative interpretation. The full principle is in docs/making-water-visible.md.
- Land — the water body's USGS 3DEP lidar is a triangle mesh drawn by three.js on the page's WebGPU device.
- Water — a CUDA program (
renderer/water.cu), compiled to WebGPU by cuda-webshader, simulates FFT waves and click ripples, then traces refraction, caustics and reflections. It reads each pixel's distance to the land from the three.js pass, so land and water meet exactly. - Light — three hand-tuned presets (Morning, Midday, Golden hour) set the sun, a Preetham sky with drifting clouds, fill light and haze.
- Quality — the renderer picks a tier from the GPU and adapts tier and resolution to hold ~30 fps; a chip shows the GPU in use and how to switch a laptop to its faster one.
- Everyone else — browsers without WebGPU get the flyover video and the same facts.
River Pulse follows one template for every river: a river map view and three or four 3D scenes (a start, a scenic middle and an end), each with a few fixed views. Unbuilt slots are shown as honest "planned" placeholders. The Russian River is the reference.
| River | Start | Middle | End |
|---|---|---|---|
| Russian | East Fork | Hacienda Bridge | Jenner Estuary |
| Sacramento | Headwaters Park (planned) | Freeport | Delta confluence (planned) |
| Eel | Lake Pillsbury (planned) | Scotia Bluffs | Estuary (planned) |
| Tuolumne | Upper Tuolumne (planned) | Poopenaut Valley | San Joaquin confluence (planned) |
| San Joaquin, American | planned | planned | planned |
Start with the River Pulse documentation: the structure guide, the style and data
guides, how to make a river, and how to work on it with an AI partner. The code map is in
river-pulse/README.md. Local run: npm ci && npm start, then open http://localhost:5173/river-pulse/.
Any US lake, reservoir or pond with 3DEP lidar coverage can become a stop:
python pipeline/locate.py "<NHD lake name>" <biome>draftsdata/<id>/source.json— name, biome, a lon/lat box around the water and an on-water anchor point.python pipeline/build.py <id>— downloads the lidar and aerial photograph and writes the terrain, cameras and map inset.- Write
data/<id>/story.json(facts, each with an https source) anddata/<id>/land.json(the look: light presets, season, grass, trees, fog, water colour). node pipeline/render-flyover.mjs <id>— renders the flyover video and poster.- Add the stop to a tour in
data/tours/, runnpm test, and publish with GitHub Pages.
The full guide, with field references and examples, is docs/make-a-waterscape.md.
Requires Node.js 20+ and Chrome or Edge. On Windows, double-click START.bat; otherwise:
npm ci
npm start
Open http://localhost:5173/ for the journey, or
http://localhost:5173/renderer/explore.html?reservoir=calaveras for reservoir 3D,
or http://localhost:5173/river-pulse/ for the River Pulse prototype.
Jenner is at http://localhost:5173/river-pulse/renderer/jenner.html after npm run build.
Both experiences share one install and server. Hacienda terrain and river centerlines are committed, so starting River Pulse does not require a fresh geometry download. Live gauge/history requests need network access and explicitly show unavailable data when a source fails.
In reservoir live 3D: drag or arrow keys to look; W/A/S/D to fly, E/Q up and down; scroll sets speed, Shift boosts (speed also grows with height above the ground). Click water for ripples, Space pauses, H hides the controls. The panel sets wave energy, basin depth, exposure, season, light, resolution and lens glare; PNG saves the frame.
URL options: ?reservoir=<id>, ?preset=morning|midday|golden, ?quality=low|medium|high
(pins a tier), ?t=<seconds> (fixed wave time); the journey takes ?tour=<tour>.
| Path | What it is |
|---|---|
river-pulse/ |
River-specific adapters, scientific state, visual bindings, renderer and place packages |
resources/ |
Curated web graphics, simulation, rendering and workflow references with upstream licence status |
docs/making-water-visible.md |
Shared principles: binding class is separate from scientific provenance |
docs/river-pulse/ |
River-specific implementation contract, reuse audit and roadmap notes |
index.html, site/ |
The journey page (videos, facts, "Explore in 3D") |
renderer/explore.* |
The live 3D page: controls, input and readouts |
renderer/engine/ |
The engine: waterscape.js (runtime, kernels, frame), body.js, camera.js, quality.js, presets.js |
renderer/land/ |
three.js land pass: terrain mesh, depth → distance pack |
renderer/water.cu |
All water simulation and image formation (CUDA, shared with the native host) |
data/<id>/ |
One folder per water body: source.json (inputs), terrain, cameras, story, land profile, flyover, poster |
data/biomes/<biome>/ |
Reusable assets per landscape type (diablo-oak today) |
data/tours/<tour>.json |
Journeys: ordered stops |
pipeline/ |
Builds and checks water bodies: build.py, render-flyover.mjs, validate-bundles.mjs |
vendor/ |
cuda-webshader and three.js, vendored (the site loads nothing from CDNs) |
Native/ |
Optional native Windows CUDA host (developer tool) |
docs/ |
Architecture, make a waterscape, design history; see also the roadmap |
npm run test:unit
npm run validate
npm run test:build
npm test
The first three checks cover both experiences without launching a GPU browser. Python pipeline
checks (including river terrain and registry generation) require numpy scipy Pillow pytest:
python -m pytest pipeline/tests -q. CI runs these checks plus shader compilation. The full
npm test additionally launches Edge for the reservoir browser suite; Windows Chrome/Edge
are the primary live-3D targets.
Serves itself, compiles all 20 CUDA kernels, validates every water body, biome and tour, and
drives Edge through Playwright: FFT correctness, optics, zero readbacks in the frame loop,
ripples, viewpoints, presets, resizing, quality tiers and the journey. Pipeline tests:
python -m pytest pipeline/tests -q.
The reservoir renderer models still water only — one water level inside a shoreline. Landforms and shorelines come from lidar (~10 m); everything finer is procedural or from shared biome assets. Lidar flattens water, so the bed is modelled as banks falling about 1:3 to the chosen basin depth, and the water level is the level at survey time. Outside the lidar crop the land falls away under painted far ridges.
River Pulse keeps absolute river elevation, spatial gauge state, source quality and explicit time-selection policies separate from that reservoir model. It reuses utilities where the contracts already match; reservoir waves and synthetic beds are not river hydrodynamics. See repository architecture and the River Pulse guide. Future water-system experiences can add their own state and visual bindings under the same umbrella without a speculative shared framework.
- Water optics: Clearwater by Aurélien / Lumaris (MIT) and its CUDA reimplementation SamG-Coder/clearwater (MIT).
- cuda-webshader (MIT) and
three.js r186 (MIT), vendored under
vendor/. - Terrain: USGS 3D Elevation Program, public domain. Facts: public records cited per fact.
- References: Tessendorf (FFT water), Evan Wallace (caustics), Preetham et al. (sky), Inigo Quilez (texture repetition), Olano & Baker (LEAN mapping).
MIT licence (LICENSE); third-party notices in THIRD_PARTY_NOTICES.md.




