ReadonlyctxReadonlysceneReadonlycacheActive camera. Defaults to the first Camera found on a root GameObject when the first frame runs; can be set explicitly.
Asset resolver supplying things the runtime can't build itself — glTF meshes, material/assembly references — for instantiateAssembly and friends. A game sets this once (e.g. a manifest/fetch resolver). Left null, only assemblies of primitive meshes + inline materials build fully.
When true (default), _bucketScene frustum-culls the opaque and
transparent draw lists against the active camera so off-screen meshes are
never submitted to the lit/geometry passes. Shadow casters are kept
complete here and culled per-cascade inside the shadow pass instead.
Number of mesh renderers culled from the visible lists on the most recent frame (diagnostic; resets each frame).
Active WebXR session, or null for ordinary single-view rendering. Set via
enterXR; cleared when the session ends. While set, the engine's
frame loop is driven by the headset compositor, not window.
The XRFrame currently being rendered, valid only during a WebXR frame
(set at the top of frameXR, cleared after). Read it from a
beforeFrame hook to drive XrControllers.update or query poses.
Simulation clock, advanced each frame before scene.update. Set
engine.time.scale to pause (0) or slow/speed up gameplay. Shorthand for
Scene.time.
The most recently built RenderGraph. Useful for the graph-viz overlay; do not mutate.
The most recently compiled graph. Useful for the graph-viz overlay.
The shared audio engine for this engine instance, created on first access (so a project that never plays sound never spins up a Web Audio context). AudioSource/AudioListener components resolve their engine through here, and the scene-runtime component factory builds them against it.
Instantiate an AssemblyDoc into the scene (synchronously) and return
the live instance root. Adds the root to scene unless opts.parent
is given (then it's parented there instead). Use
instantiateAssemblyAsync for assemblies that reference other
assemblies — those links need the async path to resolve.
Async instantiateAssembly that resolves nested / referenced assemblies through assetResolver (and any asset-backed components).
Async loadScene that resolves scene-node / nested assembly links.
StaticcreateCreate and bootstrap an engine. Awaits the RenderContext, the
render preset (which typically registers built-in features), and setup() on
every registered feature.
Add a RenderFeature. Runs its setup immediately (sync features
complete here; async ones are awaited before the next frame builds). The
cached graph is invalidated since the feature roster changed.
Returns the result of feature.setup: a Promise when the feature's setup
is async, otherwise undefined. Callers that need the feature's owned passes
before the next frame (e.g. to configure them synchronously) should
await engine.addFeature(...); otherwise the return value can be ignored.
Like addFeature, but inserts the feature immediately before the
already-registered feature named beforeName (instead of appending). Use
this to splice a feature into a preset-built pipeline at the right slot —
e.g. adding an anti-aliasing resolve just before TonemapFeature. Falls
back to appending when beforeName isn't registered.
Remove a feature by name (no-op if not present). Disposes the feature.
Lookup a feature by name. Returns null if not registered.
Lookup a feature by name and throw if not found.
Iterate the registered features in registration order.
Toggle whether a feature contributes to the frame. Invalidates the cached graph so the next frame rebuilds without the disabled feature.
Find a registered pass by its Function.name. Walks features and returns the first matching pass found. Convenience for the common case of tweaking pass parameters without reaching into a feature explicitly.
Run a callback at the top of each frame, before features update.
Run a callback at the bottom of each frame, after graph execute.
Run a callback while a fresh graph is being built — between feature
addPasses and the final compile. Use this for one-off inline passes
that don't warrant a full feature class. Callback runs only on graph
(re)builds; when the cached graph is reused, the callback does NOT run,
so any inline pass must follow the same "execute closure reads mutable
state" pattern as a regular pass.
To make an inline pass appear/disappear per frame, wrap it in a feature
and toggle enabled via setFeatureEnabled instead.
Kept for API compatibility; the graph is rebuilt every frame, so explicit invalidation is unnecessary. No-op.
Begin the requestAnimationFrame loop. No-op if already running. Frames
after the first wait for any in-flight feature setup before kicking off
the next tick, so an async preset applied just before run() finishes
setting up before any frame work runs.
Stop whichever frame loop is running (window or XR).
Switch the engine into stereo WebXR rendering driven by xr. The frame
loop is handed off from window.requestAnimationFrame to the headset
compositor (xrSession.requestAnimationFrame), and each frame renders the
scene once per eye into the projection-layer texture. Temporal AA / motion
blur are disabled (no per-eye jitter+history yet — see
TODO/webxr-integration.md). Call inside the same user gesture that created
the XrSession. When the session ends (user exit / headset removed),
the engine automatically reverts to the window loop if still running.
Request the active XR session to end (no-op if not in XR). Cleanup runs
via the session's end event → _onXrEnded.
Stereo WebXR frame. Simulates the scene once, buckets it against the combined two-eye frustum, then renders the full pipeline per eye into that eye's viewport of the shared projection-layer texture. The camera GameObject's world transform acts as the player rig: XR eye poses are relative to it, so moving/turning the camera object is locomotion.
Tear down every feature and release the physical resource cache.
Top-level orchestration object: owns the RenderContext, Scene, the active Camera, the PhysicalResourceCache, the registered RenderFeatures, and the per-frame loop.
Per frame the engine:
ctx.update()(canvas resize detection, frame timing).scene.update(dt)) and refreshes the camera matrices.beforeFramecallbacks.feature.update(frame)on every enabled feature.feature.addPassesand then anybeforeRendercallbacks.afterFramecallbacks.The compiled graph is cached and reused as long as:
invalidate().Because passes follow the "execute closure reads mutable pass state" pattern (e.g.
pass._drawItems,pass._cameraScratch), the cached graph picks up fresh per-frame uniforms via theupdatehook without any rewiring.