Skip to main content
← Roadmap
🌊 Oceanology ProIn Progress6.0.0

Spectral Gerstner waves

A wind-driven ocean synthesised from up to 128 Gerstner components, steered by a single Beaufort dial, with Jacobian foam and a matching CPU evaluator for physics.


Spectral Gerstner is the wave source you pick when you want an ocean that answers to weather instead of to a list of hand-typed waves. It sits on the water actor as one of three selectable Water Waves Sources, alongside classic Gerstner and FFT, and synthesises a whole sea state from a wind vector and a Beaufort number. The same synthesis runs three times over: in the material for every water body, in a compute shader when you bake it to a flipbook, and in C++ for buoyancy and water queries. All three share one set of constants, so what floats matches what you see.

How the spectrum is built

  • The loop runs min(Wave Component Count x Wave Spectrum Resolution, Wave Component Count) times, up to 128 components, each one a complete Gerstner wave.
  • Each component takes a normalised position in the set; that position raised to the Wave Energy Distribution exponent decides where the component lands between the longest and shortest wavelength, and between the tallest and smallest amplitude.
  • Small Wave Threshold pulls the high-energy tail toward the minimum wavelength, and the threshold itself tightens as the wind rises.
  • Direction is the wind vector rotated by a random offset whose width is Directional Variance, so components crowd near the wind and thin out toward the edge of the fan.
  • Frequency follows the deep-water dispersion relation, omega equals the square root of g times k, with gravity at 981 centimetres per second squared. Long swells outrun short chop with no extra authoring.
  • Every component carries a second band at five times its frequency and a tenth of its amplitude, boosted by up to 1.6 times in light wind. That band is what stops calm water reading as bare rolling swell.
  • Randomness comes from a fixed integer LCG seeded at 10007 and 802709: the same sea every launch, on every machine, and identical between the GPU and CPU evaluators.

One dial for the sea state

Beaufort is normalised to a 0 to 1 value and drives two factors: a height factor of 1.85b plus 0.15 that scales the whole amplitude range, and a length factor of 1.10b plus 0.40 that scales the whole wavelength range. The same value widens the small-wave cutoff and fades out the low-wind detail boost. Dragging Beaufort from 0 to 12 is therefore a full weather sweep rather than one isolated slider. A Blueprint helper interpolates every field of the settings struct between two configurations, and the effective settings are a push-model replicated property that only the authority can set, so a server-driven storm arrives at clients intact.

Normals and foam

Normals are the cross product of the tangent and binormal built from the derivatives of the full displacement field, not from height alone, so horizontal chop shows up in the shading. Foam comes from the Jacobian determinant of the horizontal displacement: where the determinant goes negative the surface is folding, and foam is the negated determinant plus Foam Bias, scaled by Foam Gain. This is the same formula the FFT path uses, which is why foam reads consistently if you swap wave sources on an existing water body.

Runtime, baked and CPU

Wave Mode on the water actor selects None, Runtime or Baked. Runtime evaluates the loop in the material every frame. Baked replaces it with a flipbook atlas pair, displacement plus gradient and folding, produced by a GPU baker that also rounds temporal and spatial frequencies to whole cycles so the loop is seamless. The bake computes normals by finite difference, five evaluations per texel, and adds temporal foam decay that the runtime path does not have. On the CPU, the same synthesis backs wave height queries and the physics snapshot, and can apply the same bake quantisation so physics tracks the baked surface exactly. Maximum wave height is estimated analytically as four times the standard deviation of the spectrum.

Against the classic Gerstner source

BeforeOceanology Pro
Wave countA base offset plus four optional wave sets, each expanded into four sub-waves: twenty components at mostUp to 128 components, count set by one slider
Sea-state authoringAmplitude, steepness, speed, wavelength and direction typed per wave setOne Beaufort dial rescales every component's amplitude and wavelength range
Directional spreadA direction scalar per wave set plus shared direction offsetsRandom spread around a wind vector, width set by Directional Variance
Spectrum shapeImplicit in whatever numbers were typedEnergy Distribution and Small Wave Threshold reshape falloff across the whole set
High-frequency detailOnly what the four wave sets carryA second band per component at five times frequency, boosted in calm air
Wave Component Count4 to 128, default 128
Beaufort Scaleup to 12, default 5
Directional Variance3 to 90, default 30
Wave Energy Distributionup to 10, default 1
Wave Spectrum Resolution0.5 to 1.0, default 1.0
Wavelength rangeMin 128 cm, Max 13312 cm by default, both scaled by Beaufort
Amplitude rangeMin 0.25, Max 13.7 by default, doubled and scaled by Beaufort
Foam Bias / Foam Gaindefault 0.3 and 1.0; ranges -1 to 2 and 0 to 5
Detail band5x frequency, 0.1x amplitude, boost 1.6 at calm falling to 1.0 at force 12
Bake atlas16 to 256 frames, 256 to 2048 per frame, 4 to 60 second loop, patch 1024 to 131072 cm

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