Photoreal maps freeze the sea.
Photogrammetry captures the ocean as a single still photograph. Put moving, breaking water at the waterline instead, driven by the forecast for that spot.
The water engine behind the Open Waves game, packaged for your Three.js app. Breaking waves, foam, spray, sky, weather and live wind and swell, set among photorealistic 3D scenery of real coastlines built from satellite and aerial imagery. Drop in your own GLB models: they float, pitch with the swell and leave a wake.
$ npm install --save-exact ./openwaves-water-VERSION.tgz [email protected]
Delivered as a private, licensed package from your software portal, with a SHA-256 checksum for every release.
Why it exists
Real-world 3D maps and WebGL scenes both stop at the waterline. This is the part that moves.
Photogrammetry captures the ocean as a single still photograph. Put moving, breaking water at the waterline instead, driven by the forecast for that spot.
The stock Three.js water is a reflective plane with scrolling normals. This ocean shoals over the seabed, steepens, throws a lip and breaks into foam and spray.
Water, sky, sun, weather, underwater light and wakes all have to agree with each other. Here they already do, because they ship together in a playable game.
Real places, real water
A runabout off Galešnjak in Croatia and a dinghy below the Golden Gate, both on simulated water. The same water renderer is in your package.


Every capture on this page comes from the Open Waves game, which runs this water engine. In your app, Google scenery streams through your own Google Maps Platform account, and coastline blending uses shore data you supply.
Who it's for
If your product, place or story lives by the sea, show it there: in the browser, at the real location, in today's conditions.
Show a hull on moving water at a real marina instead of a studio turntable. Your GLB floats with the swell, tilts and leaves a wake while buyers change trims and colours.
FloatingAsset · registerHull · reflections
Place a villa, hotel or marina development beside its actual coastline, then show it at sunset, in a storm, or under this weekend's forecast swell.
3D Tiles · setTime · setWeather
Present a pier, seawall, breakwater or promenade in context, with waves breaking over your own bathymetry. Made for concept renders and stakeholder reviews, not engineering.
createBathymetryGrid · 3D Tiles
Give a harbour, terminal or offshore wind site a living sea state for visual dashboards and digital-twin scenes, fed by forecast wind and swell.
createForecastProvider · applyEnvironment
Surf, sailing, fishing, naval or open-world games on the web. You get water from a live game; you bring the controls, characters and gameplay.
sample() · height() · addImpact
Launch a board, jet ski, kayak or outboard on a recognisable coastline inside an interactive web page, not a pre-rendered video.
loadEmbeddedGLB · FloatingAsset
Maritime, search-and-rescue and drone training mock-ups that need believable sea states and weather at a real place. Visual only, never a navigation tool.
setSwell · setWeather · sample()
Block out a shot at a real beach, build an interactive campaign, or show students how swell shoals and breaks on a reef.
setSwell · setTime · weather presets
From an empty scene to an ocean
Your app keeps its own scene, camera, renderer and loop. The SDK adds the sea, the sky and everything in between.
One simulation, one renderer. Set the swell, wind, weather and hour, then advance it in your own loop.
import * as THREE from 'three';
import { OceanSimulation } from '@openwaves/water';
import { FullWaterRenderer } from '@openwaves/water/full-water';
const ocean = new OceanSimulation(); // seabed, swell and wind defaults
const water = new FullWaterRenderer(renderer, scene, ocean, {
quality: 'high', // or 'medium' / 'low'
});
ocean.setSwell({ amplitude: 1.6, period: 13, direction: 10 });
ocean.setWind(6, 200);
water.setWeather('partly-cloudy');
water.setTime(17.5); // golden hour
const clock = new THREE.Clock();
const focus = new THREE.Vector3(0, 1, -345);
renderer.setAnimationLoop(() => {
const dt = Math.min(0.1, clock.getDelta());
ocean.advance(dt);
water.update(dt, camera, { focus });
renderer.render(scene, camera);
});
Stream Google Photorealistic 3D Tiles around your water at any latitude and longitude, through your own Google Maps Platform key.
import { TilesRenderer } from '3d-tiles-renderer/three';
import { ReorientationPlugin } from '3d-tiles-renderer/three/plugins';
import { GoogleCloudAuthPlugin } from '3d-tiles-renderer/core/plugins';
import { createGoogleTilesOverlay } from '@openwaves/water/google-tiles';
const harbour = { latitude: -33.857, longitude: 151.215, bearing: 0 };
const maps = createGoogleTilesOverlay({
TilesRenderer, ReorientationPlugin, GoogleCloudAuthPlugin,
scene, camera, renderer, ...harbour,
height: SEA_LEVEL_ELLIPSOID_HEIGHT, // puts still water at Y = 0
apiKey: YOUR_GOOGLE_MAPS_KEY,
attributionContainer: document.querySelector('#credits'),
googleMapsLogoURL: GOOGLE_MAPS_LOGO_URL,
});
water.setLocation(harbour); // the real sun path for this spot
// every frame, after the camera moves:
maps.update();
Fetch the forecast on your server, then apply wind, swell and weather to the running ocean in one call. Free data, no API keys.
import {
createForecastProvider, applyEnvironment,
} from '@openwaves/water/environment';
// On your server: free MET Norway and NOAA data, no API key.
const forecast = createForecastProvider({
userAgent: 'YourApp/1.0 https://your-site.example/contact',
});
const snapshot = await forecast.fetch({
latitude: -33.857, longitude: 151.215,
});
// In the browser: wind, swell and weather in one call.
const applied = applyEnvironment(ocean, snapshot, {
onWeather: weather => water.setWeather(weather),
});
showCredits(snapshot.attributions); // keep source credits visible
console.log(applied.issues); // anything stale or out of range
Load a GLB and it heaves, tilts and drifts on the sampled waves. Register it as a hull and it pushes a real wake into the sea.
import { loadEmbeddedGLB, FloatingAsset } from '@openwaves/water';
const file = await fetch('/models/tender.glb');
const model = await loadEmbeddedGLB(await file.blob());
const boat = new FloatingAsset({
object: model, simulation: ocean,
position: { x: 0, z: -340 }, heading: Math.PI / 4,
preset: { draft: 0.35, massKg: 900 },
});
scene.add(boat.group);
water.reflectionObjects.push(boat.group); // mirrored in the sea
const hull = water.registerHull({ // pushes a wake into the water
object: boat.group, velocity: boat.velocity,
length: boat.dimensions.length, width: boat.dimensions.width,
draft: boat.draft, massKg: boat.massKg,
});
boat.simulation = water.createWaterSampler({ owner: hull.owner });
// every frame, after ocean.advance(dt):
boat.update(dt);
What's in the box
Small surface, deep engine. Every release is pinned to the exact game build it came from and lists its modules in a build manifest.
| Call | What it does |
|---|---|
| new OceanSimulation() | Shore-oriented wave solver: crests travel, shoal, refract and break over the seabed |
| ocean.setSwell() | Amplitude 0–10 m, period 1–60 s, direction ±80° |
| ocean.setWind() | 0–50 m/s, with gusts in the visual wind field |
| ocean.sample(x, z) | Height, normal, velocity, foam, breaking and crest data at any point |
| new FullWaterRenderer() | Water, sky, foam, spray, reflections, refraction, caustics and underwater shading |
| water.setWeather() | Clear, partly cloudy, overcast, rain or storm |
| water.setTime() · setLocation() | Sun, light and sky for any hour at a real latitude and longitude |
| water.registerHull() · createWake() | Hull waves and foam wakes from your moving objects |
| water.addRipple() · splatFoam() · addImpact() | Contact ripples, foam patches and landing waves |
| new FloatingAsset() | Passive floating for your GLB: heave, tilt and drag on the waves |
| createGoogleTilesOverlay() | Google Photorealistic 3D Tiles placed around your water, with attribution |
| createForecastProvider() | Free forecast with no key: MET Norway weather and wind, NOAA wave models |
| applyEnvironment() | Forecast wind, swell and weather applied to the running ocean |
| createBathymetryGrid() | Your depth grid, with source, license and datum recorded |
package/
├─ dist/
│ ├─ index.js simulation, floating, GLB
│ ├─ full-water.js FullWaterRenderer
│ ├─ google-tiles.js 3D Tiles adapter
│ ├─ environment.js forecasts, depth grids
│ └─ build-manifest.json pinned game build
├─ *.d.ts TypeScript types
├─ examples/ full scene, drop-in GLBs
├─ tools/asset-manifest.mjs
├─ README.md
├─ LICENSE
└─ THIRD_PARTY_NOTICES.txt
One-time or subscription · USD
Choose personal use or one commercial application, then choose a one-time purchase or a subscription with continuous updates. Subscribers keep using their last downloaded version after their subscription ends.
Purchased version · no recurring fee
$100 USD / one-time
For one person learning, experimenting and building noncommercial projects.
Paid, ad-supported, sponsored, client and business uses require a commercial license.
Purchased version · no recurring fee
$200 USD / one-time
For one named commercial application, developed by you or your business.
Covers the purchased SDK version; no future SDK updates. Separate applications need separate licenses.
Continuous updates
$100 USD / first month
Then $20/month for updates
Annual: $280 for the first year, then $180/year.
For one individual’s personal, noncommercial projects, with ongoing access to released SDK updates.
Commercial and client projects require a Commercial license. Future update access ends when your paid subscription ends.
Continuous updates · per application
$200 USD / month
Or $150/month equivalent
$1,800 billed annually, paid upfront.
For one named commercial application, with continuous SDK updates for your development team.
Each separate application needs its own license. Future update access ends when your paid subscription ends.
Developer preview: license inquiries are open. Checkout and delivery details will be confirmed before any payment.
Prices are in US dollars; any applicable taxes are shown before payment. No plan permits reselling or sharing the SDK as a standalone library, template or competing asset package. Read the software license terms.
Developer FAQ
You can try, and AI coding assistants are great helpers. But a believable ocean is not one prompt. Getting an environment like this right may cost hundreds in API subscriptions and weeks of work, with painstaking back-and-forth with the chatbot: waves that shoal and break over the seabed, foam, spray and wakes that agree with each other, a sky and weather that match, live forecasts, and real places that line up with the water, with every change tested in a running game. And perfect is never finished, so the engine keeps receiving fixes and improvements, which subscribers get as released updates. A license costs less than those subscriptions alone, and you start from a working ocean on day one. Copying the Open Waves game’s code is not a shortcut either: it is protected by copyright, and the game’s Terms of Service forbid copying, scraping, reverse engineering or decompiling it. Using it without a license is copyright infringement.
Yes. Load a self-contained GLB and the SDK’s FloatingAsset makes it heave, tilt and drift with the sampled waves, with configurable draft, mass and damping. Register it as a hull to push wakes into the water, and add it to the reflection pass so the sea mirrors it. Steering and propulsion stay in your own application code.
Yes. The included adapter places Google Photorealistic 3D Tiles around your water at a latitude, longitude and bearing, and keeps Google’s attribution visible. You use your own Google Maps Platform account, key and billing. The sky follows that location’s real sun path for the hour you choose. Depth and coastline blending at that place come from data you supply; nothing is extracted from Google’s tiles.
It is plain ES modules with TypeScript declarations, tested with three 0.170.0. Anything that gives you the WebGLRenderer, scene, camera and render loop can host it, and React Three Fiber exposes those through its hooks. Use your usual ES-module bundler and a WebGL2 browser.
It is a real-time, shore-oriented wave solver built for believable visuals: crests travel, shoal and refract over the seabed, then break with wind-dependent lips, barrels and foam. It is not a volumetric fluid (CFD) solver, and it is not a validated engineering, forecasting or navigation model.
It needs a WebGL2 browser. Low, medium and high quality presets scale the water grid, foam, particles, shadows and pixel budget. The full renderer makes several GPU passes per frame, so start at medium and choose per device.
The Open Waves game is the live showcase of this engine; beta play requires an invite, which you can request. The documentation covers the full API, and you can ask an integration question before you buy.
No. The license covers proprietary Open Waves code, including the adapter. Google supplies and licenses its own content. You provide your own enabled Google Maps project and authorized API access, pay Google’s usage charges, and comply with its attribution and usage requirements. Open Waves is independent of Google.
Google Photorealistic 3D Tiles are currently unavailable for new integrations associated with EEA billing accounts. The water simulation works independently of Google. See Google’s EEA eligibility guidance.
See Map Tiles API policies and the Google Maps Platform terms.
Forecasts, yes, at no cost: the forecast connector reads MET Norway for weather and wind and NOAA’s WAVEWATCH III wave models for swell. Both are free to use in commercial products with credit and need no account or API key. Keep their credits visible and their fair-use limits (identify your app to MET Norway, cache on your server). On a server the waves cover the open ocean, the Mediterranean and the Baltic; the Black Sea, Caspian Sea and Great Lakes have no wave data. Bathymetry is not included: supply depth data you have permission to use. Google Tiles are scenery and are not used to extract bathymetry.
Yes. The simulation is separate from the optional Google adapter. You can supply your own independently created scene and bathymetry. Google’s service terms still apply whenever you enable Google content.
No. Open Waves remains a separate game and demonstrates the broader technology. Your SDK license covers only the files in your delivered package. The water and environmental rendering modules are included. Game assets, foiling controls, player accounts, multiplayer services and game access are not part of the purchase. Your application supplies its own camera controls and models.
One named product or client application, including its staging environment, updates and versions for other platforms under the same product identity. Separate products and separately branded client projects each need another commercial license. Redistributing the SDK to other developers requires separate written permission.
One-time purchases cover the purchased SDK version, with no future SDK updates. Subscriptions include access to released updates during the paid term. If your subscription ends, you keep using your last downloaded version under the same personal or commercial scope; access to new updates ends. No particular release schedule is promised, and custom integration or ongoing support is not included unless stated on your order.
Personal is $280 for the first year, then $180 paid upfront each year. Personal Monthly is $100 for the first month, then $20 each month. Commercial is $1,800 paid upfront each year per application, or $200 monthly. Subscriptions renew at their selected interval until cancelled; applicable taxes and cancellation details are shown before payment.
Yes, within your license tier. You may ship the included runtime as an embedded part of your finished application, including normal browser delivery. You may not distribute reusable SDK source, a standalone SDK or an asset pack. Third-party open-source components retain their own licenses.
Your scene, on the water
Pick a license and download today, or tell us what you’re building first.