
3d Ultra Realistic Water
Build an ultra-realistic open ocean in Three.js with a deep-water Gerstner spectrum...
Install
npx skills add MengTo/Skills --skill 3d-ultra-realistic-water -g -a claude-code -y- Repository
- MengTo/Skills7.2k
- Category
- Media
- Updated
- 3d ago
- License
- MIT
- Context cost
- Mediumabout 2,510 tokens
- Runs scripts
- Yes, review before use
What it does
Build an ultra-realistic open ocean in Three.js with a deep-water Gerstner spectrum shaded per pixel from analytic derivatives, each wave faded at its own pixel footprint, plus Fresnel sky-cube and planar reflections, subsurface light through the crests, HDR sun glitter, Jacobian lace foam, a Kelvin wake, hull foam, buoyancy queries and aerial perspective into the sky's horizon haze. Use for seas, oceans, sunset or daylight water, sun glitter paths, ship or boat scenes, wakes, coastal flyovers and any 3D scene with a moving camera and a water horizon. Includes the approved water from Pirate Ship Sunset as a reusable module and demo.
3D Ultra-Realistic Water
Use this for an open sea seen by a moving camera, with a horizon and a sun. Reach for something else in these cases:
- Mirror-flat water seen from the waterline with no mesh: a full-screen analytic water plane is cheaper.
- Ripples that follow the cursor on a UI surface: use
shaders-cursor-ripples. - A small pool that reacts to touch: use a ping-pong height field.
Source: extracted from Pirate Ship Sunset, a single-file Three.js r169 scene in which a three-masted ship sails a rolling sea at sunset under an auto-cycling camera. The water had to stay convincing from 2 m above the waves out to a 12 km horizon.
The mechanism
Shade the sea per pixel from the analytic derivatives of a deep-water Gerstner sum, and fade each wave out once its wavelength falls below the pixel footprint. The per-pixel derivatives keep the glitter and foam sharp on a mesh whose triangles are 30 m wide at the horizon. The footprint fade stops the far sea from boiling into moiré.
Reuse the working effect
Copy assets/ocean.mjs. You pass in the project's own THREE, and the module does not import a second copy. Before you integrate it, read references/ocean.md, which covers the full constants, render order, buoyancy and post. The demo runs this same module inside the original scene. demo/build.mjs rebuilds it from the reference page.
import { createWaves, bakeOceanDetail, createOcean, createWake, createPlanarReflection } from './ocean.mjs';


