Skip to main content
← Roadmap
💧 Oceanology LitePlanned6.0.0

Ocean with Gerstner waves

Performance-friendly ocean simulation tuned for games that need consistent frame rates on mid-range hardware. Wave presets and wave baking included.


Lite ships the Gerstner wave system from the Pro core, unchanged. It is a summed-sinusoid displacement field with five layers, foam derived from the folding of the surface, normals derived from the same derivatives, a CPU mirror for physics, and an optional bake to a flipbook atlas. The parameter names are the ones Legacy owners already know, because Pro kept them. What is underneath them is not the Legacy code.

How the field is built

A master toggle switches the whole system on. Above the layers sits a Global Displacement block: Size in metres (default 8), Overall Length, Global Amplitude, Global Speed, Choppiness (default 3) and Global Wave Direction. Size drives a patch scale of Size times 0.05, and that patch scale multiplies into the global amplitude, speed and length before any layer is evaluated, so Size is the single control that rescales the whole sea. Below it sits the Base Offset, the swell that is always on, and then four optional wave layers that can each be toggled off individually.

Every layer is really four waves

Each layer is expanded by the summarize routine into four sub-waves using fixed multiplier tables: wavelength and amplitude both scale by 1.0, 0.8, 0.7 and 0.6, and the direction is fanned by 0, 0.1249, 0.24845 and 0.52148 times the layer's direction offset. Five groups of four gives a maximum of twenty sub-waves, evaluated in one unrolled loop. No dispatch, no render target, no readback.

  • Base Offset, always on: amplitude 80, steepness 1.0, speed 1500, wavelength 16384, direction 0.4, plus two direction offsets of 0.5 and 0.75 that the other layers borrow.
  • Wave 1: amplitude 50, speed 1000, wavelength 8192, direction 0.425. Uses the first direction offset.
  • Wave 2: amplitude 20, speed 1000, wavelength 4096, direction 0.45.
  • Wave 3: amplitude 10, speed 500, wavelength 2048, direction 0.475.
  • Wave 4: amplitude 5, speed 250, wavelength 1024, direction 0.5. Waves 2 through 4 use the second direction offset.

The wavelengths halve down the stack, so the defaults are already a coarse-to-fine cascade. The four optional layers are also modulated by the swell: a term derived from the Base Offset's local height, clamped between 0.7 and 1.0, scales both the amplitude and the steepness of Waves 1 through 4. Chop rides the swell rather than sitting flat on top of it. Choppiness multiplies the steepness of those four layers only; the swell keeps its own.

Foam and normals from the same derivatives

While the layers accumulate, the shader also accumulates the four partial derivatives of horizontal displacement and the two height derivatives. Foam is the folding determinant: J equals one plus dDx/dx times one plus dDy/dy, minus the cross terms. Where J goes negative the surface is folding onto itself, and foam is the saturated negation of J offset by Foam Bias and scaled by Foam Gain. Foam Bias defaults to 0.3 in a range of -1.0 to 2.0, and lower values produce more foam. Foam Gain defaults to 1.0 in a range of 0.0 to 5.0. Normals come from the cross product of a tangent and binormal built from the same Jacobian and height derivatives, which is the identical construction the FFT path uses. Foam and lighting therefore agree with where the surface actually is, instead of being painted on independently.

Runtime or baked

The wave mode is None, Runtime or Baked. Runtime evaluates the twenty sub-waves per sample. Baked runs a GPU compute baker that writes a displacement atlas and a gradient-and-folding atlas as a flipbook, after which the shader costs two texture samples. The baker takes 16 to 256 frames (default 64) into an 8 by 8 grid, a loop duration of 4 to 60 seconds (default 16) and a patch length from 1024 to 131072 (default 16384). The CPU side can apply the same loop and patch quantization so physics matches the baked loop exactly.

When Gerstner is the right instrument

  • Art-directed seas. You are moving five named layers, not a spectrum. A brief like one large swell from the north-west with finer chop crossing it maps directly onto Base Offset plus Wave 1 and their direction offsets, and it stays where you put it.
  • Stylized water. A hand-tuned sinusoid stack is the correct tool for a look that is meant to read as designed rather than as measured ocean physics.
  • Lakes and enclosed water. A small controlled surface wants a small controlled wave set.
  • Lower-end targets. Runtime mode is arithmetic with no GPU resources attached. Baked mode is two samples per pixel, which is about as cheap as an animated ocean gets.
  • Networked and deterministic gameplay. The CPU mirror evaluates the same function the shader does, and the effective wave set is a push-model replicated property, so server and client agree on where the water is.
  • Analytic wave height. Significant height is estimated as four sigma from the layer amplitudes, using a per-group variance factor of 2.49, so collision bounds and buoyancy get a wave height without sampling the GPU.

Gerstner in Lite versus Gerstner in Oceanology Legacy

Oceanology LegacyOceanology Lite
Authoring parametersSix global displacement fields, base offset, four layersThe same fields with the same defaults
Sub-waves per layerA four-to-twenty selector whose plumbing is commented out in the solverA fixed four per group, twenty in total, always live
FoamNo Jacobian term and no foam bias or gain anywhere in the sourceFolding-determinant foam with Foam Bias and Foam Gain
NormalsNot derived in the wave codeCross product of the displacement derivatives, same method as FFT
BakingNoneGPU compute baker to a displacement and gradient atlas pair
Parameter deliveryMaterial parametersPer-body GPU data blocks decoded in the shader
Wave groups1 base offset plus 4 optional layers
Sub-waves per group4, fixed
Maximum sub-waves20
Wavelength and amplitude multipliers1.0, 0.8, 0.7, 0.6
Direction offset multipliers0, 0.1249, 0.24845, 0.52148
Foam Biasdefault 0.3, range -1.0 to 2.0
Foam Gaindefault 1.0, range 0.0 to 5.0
Choppinessdefault 3.0, applies to Waves 1 to 4
Swell modulation clamp0.7 to 1.0
Bake frames16 to 256, default 64
Bake loop duration4 to 60 seconds, default 16
Bake patch length1024 to 131072, default 16384
Significant wave heightfour sigma, per-group variance factor 2.49

This is one entry on the Galidar roadmap. For what already shipped in each release, see the Changelog.