Water core concepts

This chapter covers the ideas that every Water workflow shares: body types, overlap arbitration, the shared clock, and how queries stay aligned with rendering in large worlds.

Body family

WaterBodyComponentBase
    ├── WaterBodyRiverComponent   presets: Stream / River / GreatRiver
    ├── WaterBodyLakeComponent
    └── WaterBodyOceanComponent
TypeGeometryTypical scaleDefault priority
StreamSpline strip0.5? m wide160 (river family)
RiverSpline strip + width/depth/flow curves3?0 m160
GreatRiverWide spline strip50?000 m160
LakeClosed spline or polygon fillup to ~4 km² detailed; larger uses far LOD128
OceanCamera-centered CDLOD gridunbounded or finite region64

Stream / River / GreatRiver share one component; Preset only resets curve defaults. Field details: Authoring.

One registry, one query surface

All bodies register with WaterBodyRegistry. Gameplay, buoyancy, camera underwater checks, and SurfaceData go through WaterSurfaceRequestBus against that registry—not ad-hoc heightfields.

WaterSurfaceSample fields:

FieldMeaning
m_surfaceHeightAbsolute world Z of the (possibly wave-displaced) surface
m_depthStill-water depth (surface ?bed / terrain), meters
m_flowVelocityHorizontal flow, m/s
m_inWaterBodyXYQuery XY inside a body’s projection
m_entityIdWinning body’s EntityId (invalid on miss)

Sample mode flags (WaterSampleFlags): Default (full Gerstner inverse), HeightOnly, StillWater, plus independent IgnoreFlow.

Overlap arbitration and blend

When several bodies cover the same XY:

  1. Higher m_queryPriority wins (defaults above).
  2. Ties resolve toward the higher surface.
  3. If the winner’s Blend Band (m_blendPriorityBand) is > 0 and the sample is within that distance of the winner’s boundary, height / depth / flow smoothstep toward the best lower-priority body covering the same XY. 0 keeps winner-takes-all.

Estuaries usually combine:

  • River Mouth Fade Length ?zeros river waves toward the mouth and damps ocean waves in a disc around the mouth;
  • River Blend Band ?soft height/depth/flow transition into the ocean.

See Recipes#estuary.

Shared water clock

waterTime drives CPU queries, buoyancy, and GPU wave constants. It wraps every 3600 s (GetWaterTime / SetWaterTime on WaterSystemRequestBus). Pinning time makes screenshots and CI phase-stable.

Optional C++-only SetTimeSource / ClearTimeSource injects an external monotonic clock (replay / network). While a time source is installed, its per-tick value wins over a direct SetWaterTime.

CPU / GPU consistency

Wave math lives in AzCore-only core (WaveEvaluator, spectrum helpers). The GPU Gerstner path uses the same formulas with large-world UV folding; golden tests pin ?1 cm disagreement at 100 km. Spectrum oceans render via GPU FFT; buoyancy samples a ?6-component CPU approximation of the same spectrum (statistical alignment, not texel-identical).

Large-world rules

  • Query inputs are absolute AZ::Vector3d world positions (same contract as terrain GetHeightD).
  • GPU positions are render-origin-relative; origin shifts must not slide waves—keep the shared clock and do not reinvent per-body time.
  • Oceans in World Streaming levels should use WorldStreamingMemberComponent with AlwaysLoaded (not spatially unloaded). Long rivers may be split across cells; use Align To Adjacent Segments / River Network to keep endpoints matched.
  • At most one unbounded ocean per level. Multiple finite oceans are allowed via Region Entities.
SystemRelationship
PolyTerrainEditor-time river-bed carve only; no runtime PolyTerrain height bus for water depth
SurfaceDataOptional water / underwater / riverbank tags when Emits Surface Tags is on
Navigation3DActive bodies can register underwater regions for hybrid routing
OpenParticleSystemOptional WaterParticleBridgeComponent for splash / bubbles / marine snow

Next steps


Copyright © 2026 DawnEngine. All rights reserved.

DawnEngine is a commercial 3D engine distributed under the DawnEngine end-user license agreement. Engine binaries and source are proprietary and are not covered by the licenses below.

Documentation only: the prose and templates on this site are a derivative work of Open 3D Engine (O3DE) documentation by the O3DE Contributors, used under CC BY 4.0 (documentation content), Apache 2.0 (site code), and the MIT license (inline code samples).

The open-source 3D engine that DawnEngine is built on top of is Open 3D Engine . DawnEngine is not affiliated with, endorsed by, or sponsored by The Linux Foundation or the O3DE project. “O3DE” and “Open 3D Engine” are trademarks of The Linux Foundation.