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.
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 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.
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.
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.
| Before | Oceanology Pro | |
|---|---|---|
| Foam history | Runtime: the instantaneous Jacobian only | Baked: the previous frame decayed exponentially, then taken as a maximum with the new value |
| Streaking behind crests | None; foam appears and disappears with the fold | Present, with the decay rate controlling how long trails persist |
| Per-frame cost | The full component loop, every pixel, every frame | Two flipbook fetches and a blend |
| Cost of changing wind | Free, live | Requires a re-bake |
| FFT whitecaps | Foam Decay Rate 2.0, Foam Bias 0.85, Foam Gain 1.5 |
| Gerstner and Spectral Gerstner, runtime | Foam Bias 0.3, Foam Gain 1.0 |
| Wave bake | Foam Decay Rate 2.4, Foam Bias 0.3, Foam Gain 1.0 |
| Shoreline band | Coast Foam Width Profile 0.25 of the breaker footprint, floored at one capture texel |
| Shallow-water solver | Decay 0.55, Compression Gain 1.25, Compression Scale 12, Shallow Depth 150 cm, Shallow Gain 0.08, Shore Rest Gain 0 |
| Interaction foam | Half-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 shading | Foam 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 textures | Eight 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.