# The ocean

> How the sea is made. FFT waves in four cascades, shore waves that bend around headlands, surf foam, caustics and the view under water.

The sea around every island is the engine's most involved system. It is several
layers, each one doing what it is good at, summed into one surface:
`engine/ocean/`.

## The open sea: FFT waves

Far from the coast, the sea is a sum of thousands of waves with a realistic
spectrum (the JONSWAP spectrum, after Tessendorf's classic method). Adding that
many waves directly would be far too slow, so the engine does it in the
frequency domain: it evolves the spectrum in time, then turns it into a height
field with an inverse **Fast Fourier Transform**
(OceanFFT.js (`engine/ocean/OceanFFT.js`)).

*Figure: Four cascades of FFT tiles, from 733 m down to 7.1 m, summed into one surface*

- **Four cascades**: tiles of 733 m, 157 m, 33.3 m and 7.1 m, each covering one
  band of the spectrum. The ratios between them are not whole numbers, so their
  repetition never lines up.
- **Two dispatches a frame** for all of them: a row pass evolves the spectrum
  and runs a 256-point FFT per row in workgroup memory, then a column pass
  finishes the transform.
- **Choppy waves**: besides height, the FFT gives a sideways displacement, which
  sharpens the crests, and the surface's derivatives, for normals without extra
  samples.
- **Foam from the Jacobian**: where the displacement folds the surface on
  itself, a wave is breaking. Its Jacobian marks those places, and foam
  accumulates there and decays over time.

## The coast: shore waves

The FFT tiles know nothing about the island. Near the coast, waves slow down in
shallow water, bend around headlands, grow, and break.
ShoreWaves.js (`engine/ocean/ShoreWaves.js`) models that wave by wave:

- **Where waves go**: a travel-time field, solved once per island with the Fast
  Marching Method (ShoreField.js (`engine/terrain/ShoreField.js`)), gives
  each point when a wave front reaches it. Fronts bend around headlands and line
  up with the depth, like real swell. It is built in a worker, with the rest of
  the land.
- **Shoaling and breaking**: a wave grows as the water gets shallower, until it
  is too tall for its depth. Then it plunges: the face turns into a wall, the
  lip is thrown (Breakers.js (`engine/ocean/Breakers.js`)), and the wave
  runs on as a turbulent bore.
- **The swash**: the last of the wave runs up the beach as a thin sheet and
  drains back down.

## Surf and foam

ShoreSim.js (`engine/ocean/ShoreSim.js`) keeps a simulation of the surf zone
on the GPU, every frame: foam carried by the water (advected with the flow,
thinned where it spreads), sand wetness that dries over half a minute, and foam
stranded on the sand when the water drains.
SurfFoam.js (`engine/ocean/SurfFoam.js`) shades it: dense white mats that
tear into lace, then into thin bubble strands.

## Light through the water

- **Refraction**: everything under the water is drawn into its own image, at
  half resolution, just before the water
  (RefractionPass.js (`engine/ocean/RefractionPass.js`)). The water follows
  its refracted view ray into it, so a wading unit's legs show through the
  surface.
- **Caustics**: the bright nets on the seabed come from photon splatting
  (Caustics.js (`engine/ocean/Caustics.js`)): a fine grid on the real wave
  surface is refracted down to the floor, and where the rays focus the grid's
  cells shrink and add up to bright light.
- **Under water**: when the camera dives, sunlight fades along its path through
  the water, the view fills with murk and marine snow, and the lens splits at
  the waterline
  (UnderwaterLighting.js (`engine/ocean/UnderwaterLighting.js`)).

## Asking the sea

The game needs to know where the water is: to float a unit, to splash, to put
the camera under. WaterQuery.js (`engine/ocean/WaterQuery.js`) evaluates the
full surface on the GPU for a few points and reads the results back a frame or
two later. The FFT moves points sideways, so the query solves for the point that
lands where it asks, in a few iterations.

## On the lower presets

The surf simulation and caustics are among the first systems the lower graphics
presets switch off. The FFT always runs: the sea is part of every World.
