Skip to main content

๐ŸŒŠ Three Wave Systems - FFT, Gerstner & Spectral in Oceanology Pro 2.0

ยท 6 min read
Galidar
Founder, Galidar Studio

Oceanology Pro 2.0 ships with three complete wave systems โ€” FFT, Gerstner, and Spectral Gerstner โ€” all usable in the same project. Each wave body can independently select its wave system via the WaveSystemSelector, so you can combine cinematic FFT oceans with performant Gerstner lakes in a single level.

๐ŸŽ›๏ธ Wave System Overviewโ€‹

SystemBest ForGPU CostRealismControl
FFTCinematic oceans, film-quality waterHigh (RTX 3080+)โญโญโญโญโญPhysics-based
GerstnerGames, wide hardware supportLow (GTX 1080+)โญโญโญFully manual
Spectral GerstnerBalanced quality/performanceMediumโญโญโญโญBeaufort-driven

All three systems output the same interface (Displacement, Normal, Foam), so downstream features โ€” buoyancy, breaking waves, foam, caustics โ€” work identically regardless of which wave system you choose.


๐ŸŒŠ FFT Waves (Fast Fourier Transform)โ€‹

The most physically accurate option. FFT simulates the full ocean spectrum using GPU compute shaders.

How It Worksโ€‹

  1. Spectrum Generation โ€” A Phillips or JONSWAP energy spectrum is generated based on wind parameters
  2. Inverse FFT โ€” GPU compute shaders transform the frequency-domain spectrum to spatial-domain displacement via horizontal and vertical IFFT passes
  3. Gradient Folding โ€” A second pass computes normals and Jacobian-based foam from the displacement map

Key Featuresโ€‹

  • GPU Compute Pipeline โ€” Dedicated compute shaders for spectrum update, IFFT, and gradient computation
  • Displacement + Gradient Render Targets โ€” XYZ displacement and folding maps updated every frame
  • Wave Baking โ€” Bake FFT output into flipbook atlases for zero-cost playback in shipped games
  • Configurable Resolution โ€” From 64ร—64 (fast) to 512ร—512 (cinematic)

When to Use FFTโ€‹

  • Film/cinematic sequences where quality is paramount
  • ArchViz projects requiring photorealistic water
  • High-end PC/console games with RTX 3080+ minimum spec
  • Any project that needs wave baking for performance

โš™๏ธ Gerstner Waves (Legacy)โ€‹

The proven, performance-first approach. Manually stack 4-8 analytical Gerstner waves with full parameter control.

How It Worksโ€‹

Each wave is defined by amplitude, wavelength, direction, and steepness. The CPU-friendly analytical formula produces displacement and normals without GPU compute.

Key Featuresโ€‹

  • Manual Control โ€” Tune each individual wave for exact artistic direction
  • Lowest GPU Cost โ€” Runs efficiently on GTX 1080 and up
  • Preset System โ€” One-click ocean configurations for common scenarios
  • Wave Baking โ€” Bake Gerstner output into flipbook atlases too

When to Use Gerstnerโ€‹

  • Mobile or low-spec hardware targets
  • Stylized water that needs precise artistic control
  • Projects where every millisecond of GPU budget matters
  • Simple lake or pool simulations

๐Ÿ”ฌ Spectral Gerstner Wavesโ€‹

Real ocean surfaces are the result of wind energy distributed across a spectrum of frequencies. Our Spectral Gerstner system simulates this by:

  1. Generating many wave components (up to 128) across the frequency spectrum
  2. Distributing energy according to oceanographic models
  3. Aligning waves around the wind direction with natural spreading
  4. Using proper dispersion for physically correct wave speeds

The Beaufort Scaleโ€‹

Instead of abstract parameters, you now control the ocean using the Beaufort Wind Force Scale (0-12):

BeaufortDescriptionWave HeightSea State
0Calm0 mMirror-like
3Gentle Breeze0.6 mLarge wavelets
5Fresh Breeze2.0 mModerate waves
7Near Gale4.0 mSea heaps up
9Strong Gale7.0 mHigh waves
12Hurricane14+ mAir filled with foam

Simply set BeaufortScale = 5 and the entire wave spectrum adjusts accordingly!

๐Ÿ“ Technical Implementationโ€‹

Deep Water Dispersionโ€‹

Our waves follow the deep water dispersion relation:

ฯ‰ = โˆš(g ร— k)

Where:

  • ฯ‰ = angular frequency (wave speed)
  • g = gravity (981 cm/sยฒ)
  • k = wave number (2ฯ€/ฮป)

This ensures longer waves travel faster than shorter waves - exactly like real oceans.

Energy Distributionโ€‹

Wave amplitudes follow an exponential energy distribution:

const float energy = pow(waveT, WaveEnergyDistribution);
float lambda = lerp(adjMaxL, adjMinL, energy);
const float A = lerp(adjMaxH, adjMinH, energy);

This creates the characteristic ocean spectrum with dominant swells and diminishing high-frequency components.

Directional Spreadingโ€‹

Waves spread naturally around the wind direction:

const float spreadAngle = DirectionalVariance * HALF_PI;
const float angOff = sign(rand.x - 0.5) * pow(rand.y, 0.8) * spreadAngle;

Set DirectionalVariance = 30 for realistic spreading, or increase for more chaotic seas.

Detail Bandโ€‹

To capture high-frequency ripples without excessive wave count, we add a detail band at 5x the base frequency:

#define DETAIL_FACTOR 5.0f    // frequency multiplier
#define AMPLITUDE_SCALE 0.1f // relative amplitude

This adds realistic surface texture without additional computational cost.

โš™๏ธ Parameters Referenceโ€‹

USTRUCT(BlueprintType)
struct FOceanologySpectralGerstner
{
// Master enable
bool SpectralGerstnerWaves = true;

// Wind conditions
float BeaufortScale = 5.0; // 0-12 wind force
float DirectionalVariance = 30.0; // 3-90 degrees
FVector2D WindDirection = (1, 1); // Normalized direction

// Wave spectrum
float WaveComponentCount = 128.0; // 4-128 waves
float WaveSpectrumResolution = 1.0; // 0.5-1.0 quality
float WaveEnergyDistribution = 1.0; // Energy falloff

// Wave bounds
float MaxWaveHeight = 13.7; // Tallest swell (cm)
float MinWaveHeight = 0.25; // Smallest ripple (cm)
float MaxWaveLength = 13312.0; // Longest wave (cm)
float MinWaveLength = 128.0; // Shortest wave (cm)

// Foam generation
float FoamThresholdLow = -0.2; // Calm foam bias
float FoamThresholdHigh = -0.525; // Storm foam bias
float SmallWaveThreshold = 0.25; // Capillary cutoff
};

๐ŸŽจ Artistic Controlโ€‹

While physically-based, the system offers full artistic control:

For Realistic Oceansโ€‹

BeaufortScale: 4-6
DirectionalVariance: 25-35
WaveComponentCount: 64-128

For Stylized Waterโ€‹

BeaufortScale: 2-3
DirectionalVariance: 10-20
WaveComponentCount: 16-32
WaveEnergyDistribution: 2.0 (more uniform)

For Stormy Seasโ€‹

BeaufortScale: 8-10
DirectionalVariance: 45-60
FoamThresholdHigh: -0.7

๐Ÿ“Š Performance Considerationsโ€‹

The spectral system is highly optimized:

  • Loop unrolling where beneficial
  • SIMD-friendly operations (sincos pairs)
  • RCP intrinsics for divisions
  • Early Beaufort scaling to reduce per-wave work

Benchmark (RTX 4070, 1080p):

  • 32 waves: ~0.3ms
  • 64 waves: ~0.5ms
  • 128 waves: ~0.9ms

For most projects, 64 waves provides excellent quality with minimal overhead.

๐Ÿ”€ Combining with Breaking Wavesโ€‹

Spectral waves blend seamlessly with the new Breaking Wave system:

// Ocean provides base motion
OutDisplacement = SpectralWaves.WPO;
OutNormal = SpectralWaves.Normal;

// Breaking waves override near shore
OutNormal = lerp(BreakingNormal, OceanNormal, OceanBlend);
OutFoam = lerp(ShoreFoam, OceanFoam, OceanBlend);

The OceanBlend factor ensures smooth transitions from deep water to surf zone.

๐Ÿš€ Choosing Your Wave Systemโ€‹

ScenarioRecommended System
Open ocean, cinematicFFT
Open ocean, game-optimizedSpectral Gerstner
Lake, pool, stylizedGerstner
Mixed projectFFT for hero ocean + Gerstner for background lakes

Quick Setupโ€‹

  1. Select your water body in the editor
  2. Set WaveSystemSelector to your chosen system
  3. Configure system-specific parameters:
    • FFT: Resolution, wind speed, spectrum type
    • Gerstner: Individual wave amplitude, wavelength, direction
    • Spectral: BeaufortScale, WindDirection, DirectionalVariance

All three systems support Wave Baking for shipped games โ€” bake once, play back with near-zero GPU cost.

๐Ÿ“š Further Readingโ€‹


Questions about wave systems? Join our Discord and ask!