
These are the main real-time 3D submission and render-control surfaces.
Primary 3D drawing/control methods:
drawMesh(meshHandle, materialHandle, transformOrNode)billboard(textureHandleOrSource, options)drawSkybox(textureHandleOrSpec)setEnvironmentMap(pathOrCubeCameraOrNull)clear3d(color)setFog(fogSpec)clearFog()setOcclusionCulling(enabledOrOptions)addDecal(options)createCubeCamera(options?)updateCubeCamera(cubeCameraHandle)destroyCubeCamera(cubeCameraHandle)createRenderTarget(width, height, options?)setRenderTarget(renderTargetHandleOrNull, captureCamera?)destroyRenderTarget(renderTargetHandle)createLine(options)createLineSegments(options)updateLine(lineHandle, patch)destroyLine(lineHandle)clearStencil(value?)PostFX lives here today, not in a separate namespace:
setPostFXPass(name, options)setPostFXEnabled(name, enabled)removePostFXPass(name)getPostFXState()registerPostFXShader(name, wgslSource)Stage 180 landed stock named postFX presets on top of this same seam rather than creating a separate post-processing namespace.
The retained fog seam still starts at setFog(...), and Atmosphere V1 layers
onto that same entry point instead of introducing a second namespace.
Example:
aura.draw3d.setFog({
mode: 'exp2',
color: { r: 0.08, g: 0.12, b: 0.18 },
density: 0.045,
atmosphere: {
baseY: 1.5,
falloff: 14.0,
rayStrength: 0.35,
rayDecay: 0.92,
rayExposure: 0.26,
},
});
Truthful boundaries:
clearFog() clears both the retained fog state and the coupled Atmosphere V1
overlay.
Stage 191 closes one bounded live cube-camera capture lane on top of the existing command surface.
Public seam:
createCubeCamera({ position?, near?, far?, resolution?, facesPerFrame? })updateCubeCamera(cubeCamera)destroyCubeCamera(cubeCamera)setEnvironmentMap(cubeCamera) to use the captured cubemap as the shared
live IBL sourceRuntime and cost truth:
updateCubeCamera(...) or position changes
mark all six faces dirty againfacesPerFrame clamps to 1..6 and defaults to 6facesPerFrame: 2 settles over
three frames instead of forcing all six faces in one frameCurrent explicit boundaries:
aura.material.setCubeMapTexture(...) is still a later per-material consumer
lane; the current shipped live path is setEnvironmentMap(cubeCamera)Example:
const cubeCam = aura.draw3d.createCubeCamera({
position: { x: 0, y: 2.5, z: 0 },
resolution: 256,
facesPerFrame: 2,
});
aura.draw3d.setEnvironmentMap(cubeCam);
// Refresh the shared live IBL source after moving the probe.
aura.draw3d.updateCubeCamera(cubeCam);
Custom WGSL postFX now has one explicit truthful input contract:
@binding(0) input_texture: texture_2d<f32>
current scene color immediately before this custom pass@binding(1) input_sampler: sampler
shared filtering sampler for scene-color reads@binding(2) u_postfx
resolution, texel size, stock params, time, 8 custom param slots, camera
near/far, projection mode, and step/input-contract flags@binding(3) depth_sampler: sampler_comparison
comparison sampler for depth-aware reads@binding(4) depth_texture: texture_depth_2d
scene depth from the current swapchain 3D pass@binding(5) original_scene_texture: texture_2d<f32>
stable scene-color copy from before the postfx chain startedTruthful boundaries:
aura.draw3d.getPostFXState() now also reports:
resolvedSteps for the deterministic runtime execution ordercustomShaderBindings for the public binding mapcustomShaderContract for the supported input semantics and remaining
limitsStage 191 adds one stock global outline lane on top of the existing postFX composer seam:
aura.draw3d.setPostFXPass('outline', {
strength: 0.82,
radius: 1.5,
threshold: 0.35,
customParams: {
depthThreshold: 0.018,
lumaThreshold: 0.08,
outlineR: 0.08,
outlineG: 0.95,
outlineB: 1.0,
},
});
Truthful boundaries:
original_scene_texture copy to keep edge detection from drifting after
earlier postFXstrength, radius, threshold,
depthThreshold, lumaThreshold, and outlineR/G/Baura.particles3d.draw() currently renders through the same billboard/material
submission seam described below rather than through a separate GPU-simulated
particle pipeline.
Current truthful runtime behavior:
create/destroy/emit/burst/pause/resume/stop/getStateburst(options) emitters auto-clean after their particles emptydraw() submits billboard-backed particle draws into the main swapchain 3D
scene pathaura.debug.inspectorStats() now includes scene3dRuntime.particles3d so
particle counts, draw calls, and lifecycle state do not stay opaqueCurrent postfx truth:
draw3d plus
particles3d seamaura.draw3d.billboard(...) is the lightweight camera-facing quad path for
actors, effect cards, and simple in-world screens.
Truthful texture-source inputs today:
{ dataTextureHandle } bridge object for procedural billboards backed by
aura.material.createDataTexture(...)The bridge object exists because data textures and materials do not share one safe public handle namespace. Use the bridge form for procedural/no-asset billboards instead of guessing that a bare overlapping numeric handle will resolve the way you intended.
aura.particles3d.draw() currently uses aura.draw3d.billboard(...) on the
shared scene3d runtime path.
Focused truth after Stage 187:
emit, pause, resume, stop,
draw, and getStateaura.draw3d.addDecal(options) is currently a narrow detail-overlay seam.
The shipped renderer path submits oriented decal quads / decal plane batches
that you place explicitly in the world.
Use it for authored surface detail such as signage overlays, puddle-edge accents, grime cards, scorch marks, or graffiti planes.
Accepted authored albedo sources today:
texture: 'path/to/decal.png'textureHandle: aura.material.createDataTexture(...)color: { r, g, b, a? } for a flat-color fallback or tintYou can combine color with either texture source as a tint, but not with
both texture and textureHandle at the same time.
Current geometry truth:
size.x / size.z define the visible overlay footprintsize.y stays part of the authored payload for future projected-volume
compatibility, but it does not currently widen the live overlay mesh into a
true receiver-projected decal volumeIt does not currently guarantee true projected decals onto arbitrary scene geometry. In particular, it is not a mesh-conforming deferred decal pass that automatically wraps across mixed receiver topology.
aura.draw3d.createRenderTarget(...) plus
aura.draw3d.setRenderTarget(renderTargetHandleOrNull, captureCamera?) is the
explicit offscreen full-scene 3D capture lane.
Current truthful modes:
setRenderTarget(handle) redirects the current frame's full 3D scene pass
into that render target using the current camera statesetRenderTarget(handle, { position, target, up?, fovDegrees?, near?, far? })
redirects that full 3D scene pass into the target from an alternate
perspective camerasetRenderTarget(null) restores rendering to the swapchainCurrent explicit boundaries:
Projection, transform, and control helpers:
perspective(fov, near, far)orthographic(sizeOrBounds, near, far)setProjectionMode(mode)setOrthoSize(size)getProjectionMode()lookAt(x, y, z)setPosition(x, y, z)setTarget(x, y, z)setFOV(fov)getViewMatrix()getProjectionMatrix()setControlProfile(profile, options)updateControls(dt, inputState)getControlState()Use cases:
Light creation and updates:
ambient(color, intensity?)hemisphere(skyColor, groundColor, intensity?, upDirection?)directional(direction, color, intensity?)point(position, color, intensity?, range?)spot(position, direction, color, intensity?, range?, angle?)update(lightHandle, patch)remove(lightHandle)Shadow control also lives here today:
configureDirectionalShadows(options)configureShadow(lightHandle, options)getShadowState()getShadowStats()setShadowCasting(nodeOrHandle, enabled)setShadowQuality(levelOrOptions)setShadowBudget(options)Important note:
aura.shadow namespace today.aura.light.If you are planning "AAA next steps", do not treat the following as missing engine features in native AuraJS:
outline postFX pass now ships on the same seamStage 180 also closed the previously drifting seams:
The remaining frontier is broader renderer breadth, especially true projected decals and wider render-path coverage, not rediscovering the shipped quick wins above.
Stage 180 surfaced the shipped quick wins with copyable snippets and example coverage.
Quick-win starter snippet:
aura.draw3d.setEnvironmentMap('env/cyberpunk.hdr');
aura.draw3d.setOcclusionCulling({ enabled: true, conservative: true });
aura.light.spot(
{ x: 8, y: 6, z: 8 },
{ x: -0.45, y: -1.0, z: -0.25 },
{ r: 0.45, g: 0.78, b: 1.0 },
1.35,
28,
0.72,
);
Material-side follow-up lives on the next page:
aura.material.setEmissive(handle, color, strength?)aura.material.setClearcoat(handle, clearcoat, roughness)aura.mesh.createPlane(width, depth, widthSegments, depthSegments)aura.material.create({ sheenColor, sheenRoughness })aura.material.setTextureTransform(...)aura.material.createDataTexture(...)aura.material.setStencil(...)Current truthful boundary:
createPlane(...) API with extra
optional segment countsaura.postfx namespace today.aura.shadow namespace today.aura.scene3d handles hierarchy, imported-scene metadata, clip helpers, and render binding; it does not replace aura.draw3d.drawMesh(...) ownership.For scene graph, meshes, materials, glTF import, and skinned meshes, continue to: