Repository navigation
Aura3D 5.3.0
Pre-release
Pre-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=webgl2opts out in any of them; Ion Circuit's exhaust and spore sprites draw as quads whenever it requests WebGPU. Default vs?backend=webgl2captures 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 indocs/upgrade-5.0.0/README.md. - Lab flags (
apps/showcase-port-shared/lab-flags.ts):?backend=webgl2is an accepted value meaning "force WebGL2";labAppOptions(flags, { backend: "auto", createWorker })takes a per-game default backend (the oldlabAppOptions(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=webgl2no 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
endFrameso 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,endFrameordisposesubmits the batch first, so queue order is unchanged. On by default for a real browserGPUDevice(WebGPUDeviceOptions.nativeDrawBatching;globalThis.__AURA3D_WEBGPU_DRAW_BATCHING__ = falseopts 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.renderProbeFaceshares 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.
- 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
- 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=1renders 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/createGameApprender in a worker whencreateWorkeris given; worker apps getapp.nodespatches, 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 typedAuraWorkerError. - Display-P3 output stays opt-in (
?gamut=p3in 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=standardopts 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, customcolor3uniforms, every material preset); invalid values throwCOLOR_INVALIDnaming 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-environmentspreset logsENV_PRESET_MISSINGonce 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=0orA3D_PLAIN_LOOK=0opts 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.framePoseandmeasureFrameFill;lights.keycasts 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 usecamera.auto. Ten games compared against the live site were unchanged. - N5 starters: five new
create-aura3dtemplates,starter-product,starter-outdoor,starter-interior,starter-gameandstarter-presentation, each built with Vite, passingcheckDeployand captured on a real GPU. - N6 agent tools:
aura3d info(installed API surface,--namemembers and suggestions),aura3d examples(offline search over recipes and templates),aura3d validate(lint, colour grammar, unknown names, framing, lighting, nothing-to-reflect) andaura3d render(screenshot plus luma, saturation and subject fill). - N7 guessed names:
handle.setColor,setIntensity,setOpacityandsetEmissive(unsupported kinds throwHANDLE_METHOD_UNSUPPORTED),material.standard(=material.pbr), and tone-mapping spellings ("aces-filmic",ACESFilmicToneMapping,AgX, ...) mapping to the operator; unknown names throwTONE_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 validateandaura3d verifynow reportLINT_TOP_LEVEL_AWAIT_READYas an error and also catchreadyStrict(),readiness(),precompile(),game.ready(),warmPrograms(app)and those calls inside chained orPromise.alloperands; a new warningLINT_TOP_LEVEL_AWAIT_ENGINEflags a module-level await on other engine work. The docs,llms.txt, skills, recipes, examples and theproduction-product-viewertemplate no longer use a top-level await on engine work. Ifapp.ready()is still pending after 15 s of visible time with no asset activity, the engine logs oneAURA_READY_STALLEDconsole hint (it never rejects or delaysready()).
Three.js asset bridge (prototype)
aura3d import-threeruns 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