slavingia/surfing: the ocean engine that turns water into infrastructure

A Three.js system that simulates swells once, reuses the same wave field for rendering and buoyancy, and falls back cleanly when WebGPU is absent.

9 min read • View on GitHub • More from slavingia

A wide editorial scene of an ocean drawn like machinery. Surface swells feed two visible branches, one shaping a surfboard and the waterline, the other driving a floating object below the surface. The image explains the article's core idea that the ocean is a shared simulation, not a decorative skin.
The same wave field can power appearance and physics at once.
Key Takeaways

The ocean is not a material, it is a pipeline

Most water demos stop at shimmer. surfing goes further and treats the ocean like shared infrastructure, where one simulation feeds the visible surface, the motion of floating objects, and the effects that happen when the camera goes underwater.

That shift sounds small until you feel the consequences. When the same source of truth powers both look and motion, you stop patching over mismatches with hand-tuned hacks.

Why this exists

A WSJ-style hedcut portrait of Sahil Lavingia based on his verified GitHub avatar. The portrait grounds the article in a real maintainer while keeping the focus on the repository rather than a staged studio photo.

The repo layout reads like a system meant to be embedded. Waves live in one folder, surface rendering in another, buoyancy in a third, and environment pieces like sky, floor, and passes sit beside them. That separation is the clue: this is not a one-off scene, it is a library that expects to be composed.

The demo side reinforces that bias. It is built around a spectator-first experience, which makes sense for an ocean engine. Before a developer asks it to be interactive, they need to trust that it can already hold the scene together.

One ocean, two consumers

The most interesting part of the architecture is not that it simulates waves. It is that the same wave field is reused by the renderer and the buoyancy system, instead of being recomputed or approximated in separate places.

One simulation feeds both the look of the sea and the physics of what rides on it.

That reuse is what turns a pretty ocean into a coherent one. The surface can show a wave, the sampler can measure the same wave, and the floating object can react to that measurement without the two systems drifting apart.

A close-up of stacked wave bands layered by scale. Fine ripples sit on top of broader swells, with each layer drawn as a separate band of motion. It shows how the engine builds complex water from multiple frequency ranges instead of one flat wave texture.
A cascade lets small motion ride on top of larger motion.

Inside the wave stack

The simulation is built around a cascade approach, which means the engine does not pretend one frequency range can describe the whole sea. Large swells, medium waves, and small ripples are layered together so the motion stays believable at multiple scales.

Under the hood, the wave model is seeded by a JONSWAP spectrum and then pushed through FFT compute work on the GPU. The interesting optimization is the combined shader path, which processes displacement components together instead of dispatching them one by one, cutting work and keeping the pipeline tighter.

That matters because the outputs are not just aesthetic. The engine wants displacement and normals ready for rendering, sampling, and downstream environment effects, all without turning the browser into a math lab.

Why the geometry matters

The mesh has to do the same job the simulation does: spend detail where the viewer can notice it, and stop wasting effort where they cannot. That is where clipmaps and nested grids come in.

Near the camera, the water surface is dense enough to hold up under scrutiny. Far away, the geometry gets leaner, which keeps the horizon feeling endless without throwing triangles at empty distance.

A camera skimming over concentric mesh rings, dense near the lens and increasingly sparse farther out. The structure makes the water feel infinite without spending triangles where the viewer cannot tell. It explains why geometry layout is part of the illusion.
Clipmaps spend detail where the eye can actually measure it.

WebGPU-first, but not WebGPU-only

WebGPU is the fast path, and it is clearly the path this engine wants. Compute shaders handle the heavy lifting, the data stays on the GPU, and the simulation can move with far less friction than a CPU-bound approach.

But the fallback is the bigger product decision. A WebGL path keeps the system usable on more browsers and more machines, which matters more than benchmark glory when the goal is to ship a real experience.

A split editorial scene. On the left, a water surface is only a visible effect, with no connection to floating objects or scene systems. On the right, the same wave field feeds both the surface and the objects riding on it, showing the difference between a shader and an engine.
Integration changes the contract, not just the look.

What the rest of the world usually does

Most water implementations fall into one of three buckets. They are either visual tricks, a GPU-only showcase that excludes older browsers, or a buoyancy layer bolted onto a surface that was never designed to inform physics.

surfing is trying to be the opposite of that. It is a reusable subsystem with simulation, rendering, buoyancy, and environment handling tied to one shared model, which is why it reads more like engine code than a scene setup.

DimensionVisual-only waterslavingia/surfingWebGPU-only ocean engine
SimulationNo shared wave fieldShared GPU wave pipelineShared wave pipeline
BuoyancyUsually hacked on separatelyGPU sampler reads the same data as the surfaceOften integrated, but tied to the newest runtime
Render fidelityGood at a glance, brittle up closeClipmaps, normals, and cascades stay coherentHigh, but platform reach can narrow
Browser reachBroadBroad with WebGPU fallbackNarrower
Environment systemsExtra code on the sideUnderwater, caustics, and floor systems are part of the stackVaries by implementation
Developer ergonomicsEasy to start, hard to extendOne model, many consumersPowerful but easier to fragment

The point of the project

The win here is not prettier water. It is a cleaner contract between simulation and scene, where the ocean stops being a special case and starts behaving like infrastructure.

That is why this repo stands out. It is not just drawing a surface. It is organizing a world where the same wave data can carry the look, the motion, and the transitions that make the scene feel real.