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

Foam

How foam is produced across the plugin: Jacobian whitecaps from the wave field, shoreline bands from the breaking-wave profile, foam carried by the shallow-water solver, and foam left behind by objects.


Foam is not one system in Oceanology Pro. Four independent producers write into the same foam channel, each answering a different question: is this crest folding, is this a shoreline, is this water moving, and did something just hit the surface. They compose in the material, which then shades the combined coverage. Knowing which producer owns the foam you are looking at is usually the difference between a five-minute fix and an afternoon of tuning the wrong slider.

Whitecaps from the wave field

Every wave system derives whitecaps from the Jacobian determinant of the horizontal displacement field. Where the determinant goes negative the surface is folding onto itself, and foam is the negated determinant plus a bias, scaled by a gain. The FFT path computes this in a dedicated compute stage that also keeps history: the previous frame's foam is decayed exponentially by the decay rate and the new instantaneous value is taken as the maximum of the two, which is what gives streaks that trail behind crests instead of blinking on and off. The Gerstner and Spectral Gerstner runtime paths evaluate the same determinant analytically in the material, with no history, so their foam is instantaneous. Baking either of them restores the history, because the bake shader carries a previous-gradient input and applies the same decay.

Shoreline foam

Shoreline foam comes from the breaking-wave profile. The band width is the breaker's physical footprint, 100 centimetres per unit of Breaker Strength, multiplied by Coast Foam Width Profile, and the shader floors that at one WaterInfo capture texel so the band does not thin out or shimmer when you change capture resolution. Inside the band, foam is a smoothstep on the signed distance to shore, masked to the water side, added on top of the foam authored in the blue channel of the wave profile texture. Note that the shoreline optical mask is a separate thing entirely: it is documented as independent from every foam source, and it tints shallow water rather than foaming it.

Foam the water carries

In the shallow-water 2D solver, foam is a conserved scalar rather than a shader effect. The state texture stores depth, two momentum components and depth times foam concentration, and foam is transported through exactly the same Rusanov fluxes as mass and momentum, so it moves with the water instead of sliding over it. It decays exponentially, and it is generated from velocity divergence, from shallow depth, and from an optional resting gain. That last one exists because the shallow term is otherwise scaled by flow speed, so a still lake shore produces no foam however shallow it gets; raising it gives still shorelines a resting foam line, and rivers are unaffected either way because moving water already reaches full gain. A separate open-boundary weight stops the artificial compression at the domain edge from being read as a breaking wave.

Foam from things in the water

The water interaction subsystem runs a fixed 60 Hz solver over a moving window, rotating height buffers, momentum buffers and two foam buffers. Foam there is advected along the momentum field, retained with a half-life, and generated from three signals: surface slope past a threshold, crest curvature past a threshold, and the rate of height change. Impacts add their own foam on top. The result is exposed alongside signed normal, height and a velocity output, which is what the material's flow mapping uses to advect the packed foam texture: three phases offset by a third of a cycle, cosine weights that sum to one, and travel centred on zero so no phase reset produces a visible directional jump.

Runtime foam against baked foam, for Gerstner and Spectral Gerstner

BeforeOceanology Pro
Foam historyRuntime: the instantaneous Jacobian onlyBaked: the previous frame decayed exponentially, then taken as a maximum with the new value
Streaking behind crestsNone; foam appears and disappears with the foldPresent, with the decay rate controlling how long trails persist
Per-frame costThe full component loop, every pixel, every frameTwo flipbook fetches and a blend
Cost of changing windFree, liveRequires a re-bake
FFT whitecapsFoam Decay Rate 2.0, Foam Bias 0.85, Foam Gain 1.5
Gerstner and Spectral Gerstner, runtimeFoam Bias 0.3, Foam Gain 1.0
Wave bakeFoam Decay Rate 2.4, Foam Bias 0.3, Foam Gain 1.0
Shoreline bandCoast Foam Width Profile 0.25 of the breaker footprint, floored at one capture texel
Shallow-water solverDecay 0.55, Compression Gain 1.25, Compression Scale 12, Shallow Depth 150 cm, Shallow Gain 0.08, Shore Rest Gain 0
Interaction foamHalf-life 2 s, Advection 1.0, Slope 0.08 at gain 6, Curvature 0.001 at gain 100, full generation at 120 cm/s, Generation Rate 6, Impact Gain 1.5
Material shadingFoam Opacity, Roughness, Emissive, Scattering and Scattering Color, Mask Fit and Mask Power, a Support Foam static switch and a cubic mask interpolation switch
Per-region foam texturesEight foam texture slots, matched by eight baked simulation normal slots

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