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

Surface detail and wave detail

The close-up detail layer: one shared baked wave patch, replayed as a flipbook, turned into a detail normal map and advected along the local flow.


Close to the camera, any wave field runs out of resolution. A patch that reads perfectly at fifty metres becomes a smooth plastic sheet at two. The detail layer exists to fill that gap: a small, fast tiling wave patch whose only job is to add fine structure to the surface, plus the machinery that keeps it animating, advecting with the flow, and correctly sloped without an artist tuning it into place.

A shared baked patch, not a second simulation

The detail patch is configured once in the plugin's runtime settings and shared by the whole world. It is deliberately not derived from any water body's own waves, and the source comments are explicit about why: binding it to a body's waves would make the detail vanish the moment someone picked a non-spectral wave type, would tie a shared layer to one body's lifetime, and would put a live spectral simulation on the critical path of every frame. Replaying a bake costs one small pass instead. The patch is a flipbook: a columns-by-rows atlas of displacement frames played over a loop duration, wrapping seamlessly, with a patch length that converts texel spacing into world distance.

The detail normal pass

  • A tickable world subsystem drives the pass. It runs in editor worlds as well as in Play, and keeps ticking while paused, because the water has to show its detail while a level is being authored.
  • It keeps its own clock rather than using world time, so the patch animates identically in the editor, in Play, and during a paused frame step.
  • Consumers register weakly. The atlas is streamed in and the compute pass runs only while at least one live water renderer needs the result, and registrations are discarded automatically when their owner is destroyed.
  • The compute shader blends four atlas frames with a Catmull-Rom curve, so frames cannot pop, then takes forward differences between neighbouring texels.
  • Fetches use texel loads, never filtered samples: a filtered fetch would blur the very differences the pass is measuring.
  • Neighbour lookups wrap modulo the frame resolution rather than clamping, because clamping would flatten one texel row of every tile into a seam repeated across the whole surface.
  • Output is a unit normal in RGB and vertical displacement in alpha, which differs from the wave gradient map in both respects: that one carries an unnormalised normal and foam in alpha.

Riding the flow

In the shallow-water surface shader the detail flipbook is not sampled on static UVs. Two staggered phases advect the sampling position along the local velocity, and a cyclic blend hides each phase reset, the same technique the interaction foam's flow mapping uses. Velocity is converted into UV space through the patch length, so the drift is physically scaled with no artistic multiplier on top. Per-cycle pseudo-random offsets break up repetition between phases. The baked vertical displacement rides on the solver surface and the baked horizontal displacement sharpens crests, exactly as the ocean's baked path does. Three independent low-velocity gates, one each for the wave normal, the world position offset and foam, fade the whole layer out in still water, because slow water should not be carrying fast-water detail.

Detail that is not the patch

Two other mechanisms share the same job. The water material carries a tiling normal-and-height texture with separate near and far strengths, near and far scales, a far displacement term, a Fresnel power on the distant normal, and distant normal length and offset controls, so the tiling normal can be strong underfoot and restrained at the horizon. On the FFT ocean, an anti-tiling blend fades the pure patch into a mix of four neighbouring tiles, each offset by a hash of its tile coordinates, using a quintic smoothstep so no inflection is visible at a tile boundary. Near the camera the pure patch is kept intact; the blend only takes over with distance.

Against deriving detail from each body's waves

BeforeOceanology Pro
Wave-type couplingDetail disappears if the body uses a wave type that cannot produce itSurvives any wave type, because it is a separate bake
Frame costA live spectral simulation on the critical pathOne small compute pass, and only while a consumer is registered
LifetimeTied to one water bodyOne shared layer per world
Editor and paused behaviourDepends on whatever the body is doingOwn clock, ticks in editor and while paused, animates identically everywhere
Atlas layout1 to 16 columns and rows, default 8 by 8
FramesDefault 64; must not exceed columns times rows or the patch is rejected
Loop durationDefault 16 seconds, minimum 0.01
Patch lengthDefault 2000 cm, minimum 1; sets the slope of every detail normal
Slope Scale0.01 to 10, default 1, where 1 means normals are consistent with the patch they came from
Cell size fed to the shaderPatch length divided by frame resolution, divided by Slope Scale
Output targetRGBA16f render target at the atlas frame resolution, 8 by 8 thread groups
Frame blendFour-frame Catmull-Rom, frames chosen from the subsystem's own clock
FFT anti-tiling rangePure patch to 10000 cm, fully blended by 50000 cm

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