Skip to content

Aura3D 5.3.0

Pre-release
Pre-release

Choose a tag to compare

@gchahal1982 gchahal1982 released this 09 Nov 10:27
· 242 commits to main since this release

Superseded. This version is deprecated. Upgrade to Aura3D 5.5.1; see the 4.x to 5.0 migration guide.

A minor release: WebGPU renders all 25 original showcase games correctly and is the default in 15 games where it keeps up with WebGL2, the WebGPU draw path is much cheaper per draw, worker rendering and Display-P3 output are opt-in in more games, reversed depth is the default in all 30 games, and the agent-authoring baseline (N1 to N7) makes a bare or guessed scene render well. It contains everything in 5.2.1. Unless stated otherwise, measurements are single-machine (Apple M4 Max, headless Chrome, ANGLE Metal for WebGL2, Dawn for WebGPU) and are not public performance claims.

WebGPU parity

  • Native WebGPU SSAO/GTAO, screen-space reflections, depth of field (combining with AO, SSR, god rays, motion blur, pre-DoF passes and a LUT in the WebGL2 v2 order), god rays, motion blur and volumetric light; WGSL twins for the sky, environment background, light beams, particles, ribbons, fog, sprites and wind; the v2 bloom and S10 grade on WebGPU; rgba16f shadow depth; generated WebGPU PBR fixes (instance colour targets, IOR/specular defaults, alpha-to-coverage, emissive-strength bits). Unclipped point casters draw as one-pixel point lists in WebGPU depth and shadow passes (WebGL2 parity).
  • All 25 original showcase games render correctly with ?backend=webgpu (reduced-motion WebGL2 vs WebGPU capture of every game: 0 errors, static diff 0.1 to 7.2). The five new games draw on WebGPU too: every runner-kit and scenery GLSL material has a hand-ported WGSL twin (WebGL2 still draws the untouched GLSL).
  • WebGPU backend fallback is announced and chosen before a WebGPU context is taken; WebGPU mounts with probe capture switch to asynchronous frames instead of failing.
  • WebGPU is the default backend (backend: "auto", WebGL2 stays the automatic fallback) in the 15 games where it rendered the same frame as WebGL2 and ran at >= 0.9x WebGL2's frame rate: Chroma Roll, Dot Dash 3D (Glint Courier), Cumulus Dash, Cross Hop, Aura Hoops 3D, Aura FC 3D, Iron Crown, Ion Circuit, Aura Diamond 3D, Saltwind Highway, Top Tennis (Aura Slam 3D), Bunker Zero, Serpentine Sky Run, The Bellkeeper's Walk and Splat Turf. ?backend=webgl2 opts out in any of them; Ion Circuit's exhaust and spore sprites draw as quads whenever it requests WebGPU. Default vs ?backend=webgl2 captures of each match (0 errors). Every other game stays on WebGL2 by default because WebGPU is still below 0.9x there: Slingshot Siege and Duneglide (0.90 in the first sweep, 0.89 over 5 paired runs in review), Gridlock Courier 0.89, Roadster Rush (Apex Overdrive) 0.88, Teleoperator (Grid Dispatch) 0.83, Aura Links 3D 0.81, Thermal Drift 0.79, Craterline GP 0.77, Pip's Big Leap 0.76, Lamplight Line 0.75, Shadowstep Gauntlet 0.75; of the new games, Beat Hopper (0.88 median on pairs below the 60 fps cap), Shape Shift Sprint (0.86), Polarity Orbs (0.86) and Number Surge (0.71). Ratios are paired title-screen runs (in play for the new games), headless and on a loaded machine; per-game table in docs/upgrade-5.0.0/README.md.
  • Lab flags (apps/showcase-port-shared/lab-flags.ts): ?backend=webgl2 is an accepted value meaning "force WebGL2"; labAppOptions(flags, { backend: "auto", createWorker }) takes a per-game default backend (the old labAppOptions(flags, createWorker) form still works); resolveLabBackend(flags, default) gives the requested backend for code that switches on it (point-sprite quads, async frames), so ?backend=webgl2 no longer turns those WebGPU paths on.

WebGPU draw overhead

  • Profiled with Chrome CPU profiles and a WebGPU call census (Craterline GP, Aura Hoops, Pip's Big Leap, Lamplight Line). Every WebGPU draw created, wrote, submitted and fence-retired its own uniform buffer, created a sampler and a bind group, rescanned its whole index buffer, and opened its own command encoder, render pass and queue submission; retiring the buffers cost O(N^2) in the resource-interop settlement scan. All of that is fixed in packages/rendering:
    • Per-draw uniform buffers come from a device pool (each draw's own submit precedes the next queue write, so a buffer is reused at once); batched draws return theirs at endFrame so a draw keeps its buffer from frame to frame, and an unchanged buffer skips its write.
    • One sampler per descriptor, bind group layouts cached per pipeline, bind groups cached by layout and resource identity, largest-index scans cached per index-buffer contents revision, render pipelines keyed by attachment formats rather than by the target object.
    • Draw batching (RenderDevice.beginDrawBatch() / endDrawBatch(), WebGPU only): the forward item loop and the shadow caster loop record into one command encoder, sharing a render pass while the attachments match. Any other device operation, a retirement, a texture upload the recorded draws read, another submission, endFrame or dispose submits the batch first, so queue order is unchanged. On by default for a real browser GPUDevice (WebGPUDeviceOptions.nativeDrawBatching; globalThis.__AURA3D_WEBGPU_DRAW_BATCHING__ = false opts out for diagnosis). WebGL2 has no batch window and is unchanged.
    • Portable uniform blocks derive their layout once and float-only blocks are written directly (createUniformDataWriter; invalid values still take the validating writer and report the same error); prepared shadow plans validate materials through the parameter-snapshot identity; Bloom v2 keeps its intermediate targets across frames.
    • Renderer.renderProbeFace shares one lean shader library across faces, so a probe capture no longer recompiles its sky, weather and particle programs (and re-creates their pipelines) for every face; Lamplight Line's async frames went from about 400 ms with 4 to 7 s stalls to about 235 ms.
  • Craterline GP went from about 225 encoders, passes and queue submissions per frame to about 40 (mostly post-processing passes). Paired WebGPU/WebGL2 ratios (median of 3, title screen, headless M4 Max, loaded machine) moved from 0.28-0.88x to 0.75-1.12x; per-game table in docs/upgrade-5.0.0/README.md.

Worker rendering, Display-P3 and reversed depth

  • Worker rendering stays opt-in: ?worker=1 renders in a worker in 13 games: Aura Hoops 3D, Dot Dash 3D (Glint Courier), Aura Diamond 3D, Aura FC 3D, Aura Links 3D, Bunker Zero, Cumulus Dash, Cross Hop, Thermal Drift, Pip's Big Leap, Roadster Rush (Apex Overdrive), Slingshot Siege and Teleoperator (Grid Dispatch). createGame / createGameApp render in a worker when createWorker is given; worker apps get app.nodes patches, host frame callbacks, step/advance and host-side picking; worker patches replay dynamic geometry (setGeometry, updateAttribute) and animation poses, live canvas textures cross the worker boundary, patches have backpressure (one in flight, the rest coalesce) and wait for queued scene replacements; the render worker records the authored post context and loads the lane registrations. Node methods whose effect cannot be replayed in a worker throw a typed AuraWorkerError.
  • Display-P3 output stays opt-in (?gamut=p3 in the games that read the lab flag): P3 output admits the colour grade, FXAA, vignette, film grain, SMAA and a user LUT; a P3-only request on a post chain without an OutputPass route falls back to sRGB (with a fallback reason naming the blocker) instead of failing to mount.
  • Reversed depth is the default in all 30 showcase games (?depth=standard opts out; 5.2.1 had 24); the five new games' title frames match standard depth (static diff 0.0 to 0.3). Generated-program fog reads standard window depth under reversed depth.

Agent-authoring baseline

  • N1 colours: every CSS colour form (hex, rgb(), hsl(), names, ...) parses wherever colours are accepted (fog, skies, particle ramps, toon ink, custom color3 uniforms, every material preset); invalid values throw COLOR_INVALID naming the value and option.
  • N2 environment: bare scenes and missing environments use the structured studio room generated in code (embedded softbox probe, no fetch) instead of the uniform neutral floor; a missing /aura-environments preset logs ENV_PRESET_MISSING once and degrades to the room (studio family) or a procedural probe; a late-bound environment probe schedules a frame.
  • N3 plain look: a lit scene with no authored look, output, lighting or post effect renders through the PBR Neutral output, and environments.neutral() next to a hemisphere or ambient light yields its diffuse fill to that light. looks.preset("plain") asks for it explicitly; createAuraApp({ plainLook: false }), ?a3d-plain-look=0 or A3D_PLAIN_LOOK=0 opts out. Integration: a bare scene (geometry only) now gets the cold-start hero stage over the N2 room and the same plain neutral output; it renders closer to the authored colours but darker than the 5.2 ACES cold-start frame.
  • N4 framing and shadows: camera.auto({ subject, angle, fill }), camera.framePose and measureFrameFill; lights.key casts a shadow by default with an acne-free bias and primitives receive shadows by default; the custom-scene and procedural-scene templates and the cheat sheet use camera.auto. Ten games compared against the live site were unchanged.
  • N5 starters: five new create-aura3d templates, starter-product, starter-outdoor, starter-interior, starter-game and starter-presentation, each built with Vite, passing checkDeploy and captured on a real GPU.
  • N6 agent tools: aura3d info (installed API surface, --name members and suggestions), aura3d examples (offline search over recipes and templates), aura3d validate (lint, colour grammar, unknown names, framing, lighting, nothing-to-reflect) and aura3d render (screenshot plus luma, saturation and subject fill).
  • N7 guessed names: handle.setColor, setIntensity, setOpacity and setEmissive (unsupported kinds throw HANDLE_METHOD_UNSUPPORTED), material.standard (= material.pbr), and tone-mapping spellings ("aces-filmic", ACESFilmicToneMapping, AgX, ...) mapping to the operator; unknown names throw TONE_MAPPING_UNKNOWN. "filmic" and "uncharted2" throw because they are postprocess-only curves. Games pass canonical names and are unaffected: Pip's Big Leap, Aura Diamond, Teleoperator, Bunker Zero, Aura Links and Aura Hoops were paired against the live site and the pre-lane build after integration with no change attributable to it (evidence/guessed-names-n7/integration/).
  • Top-level await: a module-level await app.ready() deadlocks a default Vite production build (the lazily loaded engine chunks import the entry chunk back, so the page stays black). aura3d validate and aura3d verify now report LINT_TOP_LEVEL_AWAIT_READY as an error and also catch readyStrict(), readiness(), precompile(), game.ready(), warmPrograms(app) and those calls inside chained or Promise.all operands; a new warning LINT_TOP_LEVEL_AWAIT_ENGINE flags a module-level await on other engine work. The docs, llms.txt, skills, recipes, examples and the production-product-viewer template no longer use a top-level await on engine work. If app.ready() is still pending after 15 s of visible time with no asset activity, the engine logs one AURA_READY_STALLED console hint (it never rejects or delays ready()).

Three.js asset bridge (prototype)

  • aura3d import-three runs a structured three.js scene factory headless at build time, exports it through GLTFExporter, admits the GLB and emits a regenerated bridge file plus a write-once native scene with a supported / approximated / unsupported report (hidden lights and light/camera subtrees handled, --params, regenerate command). It is a prototype; no Aura3D package depends on three.

Benchmark harness

  • C1 fixed comparison harness (tools/agent-eval/c1): three arms (Aura3D, three.js, Aura3D + bridge), eight frozen tasks with follow-up edits, billed cost, tool time, real-GPU load / fps / size, functional probes and blind pairs, per-run worker threads. Only a stub-model dry run has been recorded; there are no comparison results yet and nothing here is a claim.

Showcase games

  • Five new games: Shape Shift Sprint, Number Surge, Splat Turf, Polarity Orbs and Beat Hopper, each with a How to play panel; Beat Hopper hops on Space, ArrowUp or W keydown.
  • Shape Shift Sprint: a confetti trail chip whose life reached exactly zero was placed at scale 0, which wrote NaN normals and made the autopilot throw attribute "normal" update must contain finite values (2 of 14 runs, both backends); such chips are now retired before drawing.
  • Multiple scattering on the plain look path: the direct-light broad multiple-scattering lobe was coloured by the mean Fresnel once, right for metals but about 25x too much for a 0.04 dielectric. Apps on the plain look path now colour it with Kulla-Conty (and the image-based term with Fdez-Aguera, as three.js does); every app with an authored look or output, so every game, keeps the old math.

Known limits

  • The plain-path multiple-scattering switch is chosen at mount; an app that boots on the plain path and later setScenes to an authored look keeps it.
  • Dot Dash 3D re-captures its update: "once" reflection probe (all six faces plus a CPU prefilter) on every WebGL2 frame, which dominates its frame time; the likely cause is that every scene change publishes a new atmosphere snapshot and the probe host disposes its probes when the snapshot identity changes. Lamplight Line does the same on both backends (on WebGPU each face is an asynchronous readback), and its first WebGPU frames can still stall for 15 s or more while Metal compiles pipelines. Thermal Drift and Pip's Big Leap are also very slow headless (2 to 5 fps) for reasons not yet profiled.
  • The WebGPU/WebGL2 ratio of the fastest games (Craterline GP, Shadowstep Gauntlet, Roadster Rush) is lower on an idle machine than under load: the remaining WebGPU cost is fixed per draw (render-state resolution, uniform packing, about 25 post-processing error scopes per frame).
  • WebGPU defaults, worker rendering and P3 were checked on one Apple GPU (Apple M4 Max) only; frame-rate ratios are headless and noisy, and capped (60 fps) runs overstate the WebGPU ratio.
  • The bare-scene plain neutral output renders closer to the authored colours but darker than the 5.2 ACES cold-start frame.
  • The three.js asset bridge is a prototype and the C1 harness has no recorded comparison yet.

Upgrade notes: https://aura3d.auraone.ai/docs/migration/4-to-5