Double-precision large world coordinates and rendering

Dawn Engine provides engine-level large world coordinates (double-precision world positions). Absolute world state is stored in double precision on the CPU; before GPU submission, positions are converted to single-precision coordinates relative to a stable render origin. GPU shaders continue to use float by default, so you do not pay a default GPU fp64 cost for large worlds.

Maturity: Delivered. Enabled by default; small-world projects can turn it off.

What problem this solves

Most real-time engines, including open source O3DE, store world coordinates as single-precision floats. Far from the origin, mantissa bits are consumed by the large magnitude: around 100 km, position error can reach centimeters. Symptoms include mesh and camera jitter, unstable shadows and TAA, physics drift, and inaccurate editor picking and placement.

Large world coordinates address numeric range, not every GPU calculation. Depth fighting and poorly chosen near/far planes are separate issues and are not fixed by this feature alone.

How it works

Dawn Engine uses high-precision world state with origin-relative rendering:

  1. CPU absolute world: authoritative entity translation, camera position, bounds, and editor interaction data use double types such as Vector3d and TransformD.
  2. Scene-level render origin: each frame, the main camera position is quantized onto a grid of cells (default edge length 1024 m) to produce a stable renderOriginD.
  3. GPU relative submit: object matrices, camera, and visibility data subtract the current render origin before upload, so the GPU sees single-precision relative coordinates.
  4. History consistency: TAA, motion vectors, and similar paths track both the current and previous render origin so origin switches do not flash the frame.

This is not per-frame camera-relative rendering. Dawn Engine uses a cell-quantized render origin with hysteresis so the origin does not chatter at cell boundaries.

Enable and disable

Default settings ship in Registry/LargeWorld.setreg under /O3DE/Atom/LargeWorld/.

KeyDefaultDescription
EnabledtrueMaster switch. When false, the render origin stays at (0,0,0) and behavior matches the pre-migration small-world path
OriginCellSize1024.0Render-origin cell edge length in meters
OriginSwitchDistance0.0Hysteresis distance before an origin switch; 0 means 0.6 × OriginCellSize
PhysxOriginShiftEnabledtrueOn origin switch, translate PhysX actors so internal poses stay within a safe float range
MultiplayerUseTranslationDtrueReplicate an extra double translation field translationD over the network
LegacyFloatInputPolicySilentPolicy for legacy float APIs used without an explicit space declaration in large-world mode: Silent / Warn / Error

Example project override (disable large-world path):

{
 "O3DE": {
 "Atom": {
 "LargeWorld": {
 "Enabled": false
 }
 }
 }
}

Disable Enabled only for small-world projects that need bit-identical pre-migration behavior. Keep it enabled for open worlds, digital twins, or any content that moves far from the origin.

Authoring and scripting at large coordinates

Double precision is an engine-level capability; you do not enable a separate Gem. Prefer the high-precision path when authoring and scripting:

  • Editor: use the double-precision translation inspector controls and the D-aware entity create / Prefab instantiate paths. Placement, picking, and grid snap far from the origin use the double path.
  • Scripts and gameplay: prefer HighPrecisionTransformBus and *D transform get/set APIs (for example world translation *D events). Legacy TransformBus / AZ::Vector3 APIs remain available but can silently lose precision far from the origin.
  • Migrating old content: “upgrading” an old Prefab float translation to double does not restore precision that was already lost. Re-place content at large coordinates, or re-import from a source that still has high-precision data.

While porting custom code, temporarily set LegacyFloatInputPolicy to Warn or Error to surface call sites that still pass absolute-world floats.

API reference

HighPrecisionTransformBus (absolute entity world transform)

Header AzCore/Component/HighPrecisionTransformBus.h, addressed by EntityId. In large-world mode every entity serves two transform buses with a clear split of duties:

BusPayloadPurpose
TransformBus (legacy)Render-origin-relative single-precision AZ::TransformCompatibility layer; the only required interface for small-world projects
HighPrecisionTransformBusAbsolute-world double-precision AZ::TransformDEverything that needs absolute-world precision: gameplay, picking, physics adapters, feature processors

Interface events:

EventDescription
GetWorldTransformD / SetWorldTransformDAbsolute world transform (TransformD)
GetLocalTransformD / SetLocalTransformDLocal transform relative to the parent entity
GetWorldTranslationD / SetWorldTranslationDWorld translation (Vector3d); the most common gizmo / inspector write-back path
GetLocalTranslationD / SetLocalTranslationDLocal translation

Change notifications arrive on HighPrecisionTransformNotificationBus via OnWorldTransformDChanged(localD, worldD). The legacy TransformNotificationBus still fires, but its payload in large-world mode is render-origin-relative single precision — listeners that need absolute world coordinates must switch to the high-precision notification.

AZ::LargeWorld precision-boundary helpers (custom C++ code)

Header AzCore/Math/LargeWorld.h. Every “absolute double → relative float” demotion should go through these helpers rather than a hand-written subtraction:

APIDescription
ToRelativeFloat(posD, renderOrigin)Subtract the render origin and demote to Vector3; the primary entry point at the Atom submit boundary
ToRelativeTransform / ToRelativeMatrix3x4 / ToRelativeAabbThe TransformD / matrix / bounds variants of the same
ToFloatChecked(v)Demote without subtracting an origin; asserts on NaN / Inf / out-of-warning-range values in debug builds
SplitOriginHighLow(origin, outHigh, outLow)Exact split of a render origin into a (high, low) float pair matching the wire format of the shader helper AbsoluteWorldPositionDemote.azsli — use it when a custom material consumes absolute world positions
LargeWorld::GetLegacyFloatInputPolicy() / ReportLegacyFloatInput(symbol)Migration policy and reporting for legacy float entry points (backed by the LegacyFloatInputPolicy registry key)

The double-precision math types (Vector3d, TransformD, AabbD, FrustumD, and others) live under AzCore/Math/.

RenderOriginService (scene-level render origin, Atom RPI)

Header Atom/RPI.Public/LargeWorld/RenderOriginService.h. It is not a component; it is a service on the Atom scene driven once per frame by Scene::PrepareRender:

APIDescription
GetCurrentRenderOriginD() / GetPreviousRenderOriginD()Current / previous frame render origin (history buffers are generated against the previous origin)
DidOriginSwitchThisFrame()Whether the origin switched this frame
ConnectRenderOriginChangedHandler(handler)Subscribe to the RenderOriginChanged event (fires exactly once per switch); handlers must mark all origin-relative GPU data dirty for re-upload
GetStats()Diagnostics: max view / object distance from origin, switch count, and more

Custom feature processors that upload origin-relative data should listen to this event; ordinary gameplay code never needs to touch the render origin — use the absolute coordinates from HighPrecisionTransformBus instead. Render-origin switches also do not change World Streaming cell desired states (streaming resolves on absolute world distance).

Script Canvas

The math library provides double-precision nodes such as TransformD. When interacting with entities, prefer the high-precision transform events (world translation Get/Set *D) so values never pass through Vector3 and silently lose precision far from the origin.

Runtime behavior

When enabled, the Render Origin Service:

  • derives a cell index from the main camera: cellIndex ≈ round(camera / OriginCellSize), with origin candidate cellIndex × OriginCellSize;
  • switches origin only when the camera is farther from the current origin than the hysteresis threshold;
  • shares one render origin across views that use the same scene object buffer;
  • notifies migrated subsystems (view matrices, object transforms, lights and shadows, ray-tracing TLAS, PhysX origin shift, and others) when the origin changes.

Inside a default 1024 m cell, relative-coordinate float ULP typically stays at sub-millimeter scale. At about 100 km from the origin, migrated paths keep sub-millimeter position precision; the absolute single-precision path at the same location is about 1.2 cm ULP.

Content and material caveats

  • Custom materials / shaders that treat worldPosition as absolute geographic space need an explicit migration (for example a render-origin high/low split, a feature origin, or CPU-side precomputation). The default shader contract is render-origin-relative world, not absolute world.
  • A single oversized object (for example one planet-scale mesh) can still exceed the relative-coordinate safety budget; tile it or use a specialized pass.
  • Far reflection or tool views: views beyond the view-to-origin safety thresholds may be unsupported or use a deferred / split pipeline. Do not assume each viewport has its own render origin.
  • Depth and near/far: double precision does not replace sensible near/far settings; an oversized far plane still hurts depth precision.

Safe to rely on:

  • CPU double world state plus render-origin-relative GPU submission;
  • migrated editor placement / picking, core rendering, culling, PhysX origin shift, and multiplayer translationD;
  • no default GPU fp64; with Enabled = false, small-world behavior matches the pre-migration engine.

Do not assume:

  • GPU double / fp64 materials and post by default;
  • drop-in compatibility with another engine’s large-world coordinate API;
  • that every third-party Gem or custom shader is large-world safe without audit.

Geospatial and water capabilities built on this coordinate contract ship separately; see Cesium 3D Tiles and Water.

World Streaming addresses load and memory scale for large worlds; double precision addresses accuracy at large coordinates. Open-world projects usually need both.

Troubleshooting

SymptomLikely causeWhat to try
Objects jitter far from originStill on an absolute-world float path, or Enabled is offConfirm /O3DE/Atom/LargeWorld/Enabled is true; switch scripts to *D APIs; set LegacyFloatInputPolicy to Warn while porting
Brief flash on origin switchCustom post that ignores previous render originAudit history-dependent materials / post for current and previous origin
Physics tunnels or unstable contacts at large coordsPhysX origin shift disabledConfirm PhysxOriginShiftEnabled is true when Enabled is true
Multiplayer clients drift in positiontranslationD not replicatedConfirm MultiplayerUseTranslationD is true and clients understand the D field
Depth flicker / z-fightingnear/far too large, not coordinate precisionTighten camera near/far; do not rely on double precision alone

Next steps

  • For Dawn Engine capabilities and how they differ from O3DE, see Introduction.
  • For large-world load and memory scale, see World Streaming; plan it together with double-precision coordinates for open-world projects.

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.