#Your scene, with water in it
WaterSystem adds one ocean mesh and a sky dome to your scene and draws it with your camera. update(dt) advances the waves, foam, buoyancy and wakes. render() draws your scene into an HDR target with depth, puts the water over it, and tone-maps to the canvas.
Follow the quick start or see how it composes with NatureGL Sky.
- presets, one file each
- 7
- quality tiers, low to ultra
- 4
- high tier, Apple M5, 1280×720 uncapped
- ~140 fps
- hulls with wakes at once
- 8
#What's in the box
- Two wave sources
A GPU FFT ocean (Tessendorf, JONSWAP spectrum, 2–3 cascades) on high and ultra, a 24–40 wave Gerstner sum on low and medium. Both are driven by the same wind, wavelength and direction.
- Water with real depth
Beer–Lambert absorption by true thickness, in-scatter, refraction with a depth blur, screen-space reflections, GGX sun glitter and crest subsurface scattering.
- Shorelines from any terrain
Bake a height function once. Waves shoal over the shelf, breakers roll up the beach and break by depth, and swash foam runs up the sand.
- Foam that lingers
Whitecaps collect in a persistent foam field and break up into lace after the crest passes. Hulls leave trails behind them.
- Buoyancy and wakes
sampleHeightreads the same wave field the GPU draws. Objects bob or pitch and roll, and moving hulls get contact foam and a Kelvin wake. - Underwater
Fog and absorption, light shafts, Snell's window with the refracted scene, total internal reflection, and a waterline with a meniscus.
#Seven seas, ready to load
Every preset is a plain params object in src/config/presets/. Load one with loadPreset, change a few values with setParams, or save your own with getParams().
tropicalClear afternoon over a turquoise reef shelf.sunsetLow sun, a long glitter path and warm haze.stormGale-force wind, long swell and breaking whitecaps under a dark deck.foggyCalm grey morning, visibility a few hundred metres.moonlitNight sea lit by the moon and stars.arcticCold, steel-blue water and a fresh breeze.#A floating raft in thirty lines
import * as THREE from 'three';
import { WaterSystem } from 'naturegl-water';
const renderer = new THREE.WebGLRenderer(); // leave toneMapping at NoToneMapping
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(55, innerWidth / innerHeight, 0.3, 12000);
camera.position.set(0, 7, 26);
const water = await WaterSystem.create({ renderer, scene, camera, preset: 'tropical' });
const sun = new THREE.DirectionalLight(), hemi = new THREE.HemisphereLight();
scene.add(sun, sun.target, hemi);
const raft = new THREE.Mesh(
new THREE.BoxGeometry(3, 1, 5),
new THREE.MeshStandardMaterial({ color: 0xf0ad4e }),
);
scene.add(raft);
water.buoyancy.addObject(raft, { size: { length: 5, beam: 3 }, draft: 0.2 });
const timer = new THREE.Timer();
renderer.setAnimationLoop(t => {
timer.update(t);
water.update(timer.getDelta()); // waves, sky, buoyancy, wakes, foam
water.bindLights(sun, hemi); // your lights follow the sky
water.render(); // scene -> HDR + depth -> water -> bloom -> ACES
});#Weather that changes while you watch
tropical to storm in twelve seconds by easing wind, wavelength, clouds and the water optics. Significant wave height goes from 0.85 m to about 6 m.#Part of the NatureGL series
NatureGL Water reads its light from a sky. It has its own built-in sky, and setSky() plugs in NatureGL Sky's SkySystem or any object with a sun, an environment map and a fog colour. NatureGL Island builds its sea on it.