Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions docs/api-guide/engine/anari-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,13 @@ const renderer = anariDevice.newRenderer('raytrace', {
samplesPerPixel: 1,
maxBounces: 1,
progressive: true,
shadows: true
shadows: true,
resolutionScale: 0.5,
minimumResolutionScale: 0.25,
adaptiveResolution: true,
targetFrameTimeMilliseconds: 33.3,
temporalReprojection: true,
shadowSamplesPerFrame: 1
});

frame.setParameter('renderer', renderer).commitParameters();
Expand All @@ -231,6 +237,17 @@ evaluates direct lights, progressively accumulates unchanged primary-ray samples
when the canvas is configured for it. Generated quads, cylinders, and cones use their existing
triangle geometry.

Ray tracing starts at half the display width and height, reducing its initial pixel workload to one
quarter of full resolution. Adaptive quality can lower that scale to `0.25`, interleave sampled
pixels across animation frames, and rotate one shadowed direct light per frame to approach the
default `33.3` millisecond frame budget. The fullscreen resolve upsamples the retained HDR image.
Temporal reprojection follows camera and stable instance motion while rejecting incompatible depth,
normal, and color history; camera cuts, topology changes, light-count changes, and resolution
changes reset invalid history. Set `shadowSamplesPerFrame: 0` to evaluate every direct light in
one frame. Adaptive timing uses smoothed animation-frame intervals and does not require GPU timestamp
queries. The acceleration graph runs only when retained transforms or geometry change, so camera-only
and lighting-only frames do not rebuild the BVH.

The BVH indexes objects and instances: triangles within a surviving mesh are still tested linearly.
Its deterministic source-order topology is not Morton-sorted, and no separate per-mesh triangle BVH
is built. The ray-tracing pass uses five storage buffers; the BVH builder uses eight, fitting the
Expand Down Expand Up @@ -667,12 +684,17 @@ console.log({
distinctSurfaces: statistics.surfaceCount,
visiblePlacements: statistics.instanceCount,
drawCalls: statistics.drawCount,
renderedTriangles: statistics.triangleCount
renderedTriangles: statistics.triangleCount,
rayTracing: statistics.rayTracing
});
```

Use these numbers to verify batching behavior. If `instanceCount` is high but `drawCount` is similarly high, check whether each placement accidentally creates its own surface instead of reusing a retained surface.

Ray-traced frames additionally report their internal resolution and effective scale, sampled-pixel
coverage, smoothed frame time, and accumulated sample count. Other renderer subtypes omit
`statistics.rayTracing`.

The renderer also supports capability discovery:

```ts
Expand Down Expand Up @@ -732,8 +754,9 @@ for the runtime contract and ownership details.
| T0: renderer and graph foundation | Lazy subtype registration, retained-scene adapters, the shared experimental `RayTracingSceneRenderer`, explicit WebGPU command-graph resources, and application-owned submission. | Implemented. |
| T1: direct rays and shadows | Transformed analytic spheres, mesh triangles, tessellated analytic shapes, perspective/orthographic cameras, direct lights, hard shadow rays, progressive primary-ray sampling, and HDR presentation. | Implemented with WebGPU compute rather than hardware ray tracing. |
| T2a: GPU object acceleration | World-space instance bounds, graph-owned complete-binary `GPUBVH` construction and refitting, nearest-hit object traversal, early-exit shadow rays, and default-CORE storage limits. | Implemented; surviving mesh triangles remain linear. |
| T2b: large-scene acceleration | Measured Morton/radix spatial ordering, shared per-mesh triangle BVHs, dirty-only hierarchy updates, and explicit traversal/build diagnostics. | Planned. |
| T2c: dynamic scene extraction | Skeletal/morph geometry extraction, bounded deforming-mesh updates, and shared animated instance acceleration. | Planned. |
| T2b: interactive frame budgeting | Half-resolution defaults, bounded adaptive quality, interleaved pixel coverage, retained-identity temporal reprojection, rotating shadow samples, and dirty-only object acceleration. | Implemented; frame pacing uses CPU animation intervals. |
| T2c: large-scene acceleration | Measured Morton/radix spatial ordering, shared per-mesh triangle BVHs, and explicit traversal/build diagnostics. | Planned. |
| T2d: dynamic scene extraction | Skeletal/morph geometry extraction, bounded deforming-mesh updates, and shared animated instance acceleration. | Planned. |
| T3: indirect transport and denoising | Advanced PBR texture, alpha, and transmission parity; multi-bounce material transport/path tracing, convergence controls, and denoising; primary-ray progressive accumulation already exists in T1. | Planned. |
| T4: ray marching and volumes | Signed-distance-field ray marching, retained spatial fields, 3D textures, transfer functions, and ANARI volume objects. | Planned. |
| T5: hybrid composition and diagnostics | Raster/ray composition, reusable graph timings, renderer capability reporting, and debug visualization channels. | Planned. |
Expand Down Expand Up @@ -928,7 +951,9 @@ Object subtypes match the private package: `triangle`, `sphere`, `cylinder`, `co
geometry; `matte` and `physicallyBased` materials; `ambient`, `directional`, `point`, and `spot`
lights; `perspective` and `orthographic` cameras; and optional renderer presets for `default`,
`deferred`, `raytrace`, `debugNormals`, and `debugDepth`. Ray-tracing presets additionally accept
`samplesPerPixel`, `maxBounces`, `progressive`, and `shadows`.
`samplesPerPixel`, `maxBounces`, `progressive`, `shadows`, `resolutionScale`,
`minimumResolutionScale`, `adaptiveResolution`, `targetFrameTimeMilliseconds`,
`temporalReprojection`, and `shadowSamplesPerFrame`.

### Generate compact triangle meshes and starfields

Expand Down
55 changes: 46 additions & 9 deletions docs/api-reference/anari/anari-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ type ANARIRendererParameters = {
maxBounces?: number;
progressive?: boolean;
shadows?: boolean;
resolutionScale?: number;
minimumResolutionScale?: number;
adaptiveResolution?: boolean;
targetFrameTimeMilliseconds?: number;
temporalReprojection?: boolean;
shadowSamplesPerFrame?: number;
bloomIntensity?: number;
bloomThreshold?: number;
bloomRadius?: number;
Expand All @@ -120,6 +126,12 @@ type ANARIRendererParameters = {
| `maxBounces` | Not applied | Reserved ray-tracing bounce limit; the current implementation evaluates direct lighting only. |
| `progressive` | `true` | Accumulate ray-traced samples across unchanged frames. |
| `shadows` | `true` | Trace hard shadow rays toward direct lights in the `raytrace` renderer. |
| `resolutionScale` | `0.5` | Initial ray-tracing width and height as a fraction of the display resolution. |
| `minimumResolutionScale` | `0.25` | Lowest internal resolution scale available to adaptive ray tracing. |
| `adaptiveResolution` | `true` | Adjust internal resolution and sampled-pixel coverage toward the target frame budget. |
| `targetFrameTimeMilliseconds` | `33.3` | Target animation-frame interval used by adaptive ray-tracing quality. |
| `temporalReprojection` | `true` | Reuse compatible retained history while the camera or stable scene instances move. |
| `shadowSamplesPerFrame` | `1` | Maximum rotating direct-light shadow samples evaluated per pixel in one frame; `0` evaluates all direct lights. |
| `bloomIntensity` | `0` | Bloom amount; positive values allocate and run the bloom postprocessing path. |
| `bloomThreshold` | `0.62` | Brightness threshold for bloom extraction. |
| `bloomRadius` | `7` | Bloom blur radius. |
Expand Down Expand Up @@ -171,7 +183,13 @@ const renderer = anariDevice.newRenderer('raytrace', {
samplesPerPixel: 1,
maxBounces: 1,
progressive: true,
shadows: true
shadows: true,
resolutionScale: 0.5,
minimumResolutionScale: 0.25,
adaptiveResolution: true,
targetFrameTimeMilliseconds: 33.3,
temporalReprojection: true,
shadowSamplesPerFrame: 1
});

frame.setParameter('renderer', renderer).commitParameters();
Expand All @@ -186,14 +204,24 @@ point, and spot lights; and presents the result through a fullscreen pass. An `r
preserves HDR radiance. The trace pass uses five storage buffers and the BVH builder uses eight,
remaining within default WebGPU CORE limits.

When `progressive` is enabled, unchanged frames accumulate additional primary-ray samples. Camera,
scene, light, material, renderer, and frame-size changes reset the accumulation history. The
source-order BVH accelerates object and instance selection; triangles within an intersected mesh
are still tested linearly. Hardware ray tracing, Morton-sorted hierarchy construction, and per-mesh
triangle BVHs are not implemented. Skeletal skinning, morph-target displacement, material textures,
alpha/transmission, and advanced PBR shading remain on the forward/deferred renderer paths. Indirect
multi-bounce path tracing, denoising, and volumes are also unsupported. `maxBounces` is accepted for
forward compatibility but does not enable indirect bounces.
The default half-resolution internal target traces one quarter as many pixels as the output canvas.
When adaptive quality is enabled, the renderer can reduce scale to `0.25`, spread interleaved pixel
coverage across frames, and rotate one shadowed direct light per frame. It approaches the configured
frame budget using smoothed animation-frame intervals; no GPU timestamp feature is required. The
fullscreen presentation pass upsamples the internal HDR result.

Progressive history is reprojected through previous camera matrices and stable ANARI instance/group/
surface identities. Depth and normal validation plus bounded neighborhood color clamping reject
incompatible history; camera cuts, changed topology/materials, changed light counts, and target
resizing invalidate it. GPU acceleration updates are encoded only for changed geometry or transforms,
while camera-only and lighting-only frames reuse the retained BVH.

The source-order BVH accelerates object and instance selection; triangles within an intersected
mesh are still tested linearly. Hardware ray tracing, Morton-sorted hierarchy construction, and
per-mesh triangle BVHs are not implemented. Skeletal skinning, morph-target displacement, material
textures, alpha/transmission, and advanced PBR shading remain on the forward/deferred renderer
paths. Indirect multi-bounce path tracing, denoising, and volumes are also unsupported.
`maxBounces` is accepted for forward compatibility but does not enable indirect bounces.

Applications can also
[register custom renderer runtimes](/docs/api-reference/anari/anari-device#registering-renderer-runtimes).
Expand Down Expand Up @@ -281,6 +309,14 @@ type ANARIFrameStatistics = {
instanceCount: number;
drawCount: number;
triangleCount: number;
rayTracing?: {
internalWidth: number;
internalHeight: number;
resolutionScale: number;
sampledPixelCoverage: number;
frameTimeMilliseconds: number;
accumulatedSamples: number;
};
};
```

Expand All @@ -290,6 +326,7 @@ type ANARIFrameStatistics = {
| `instanceCount` | Number of direct and instanced surface placements. |
| `drawCount` | Number of successful model draws, normally one per distinct raster surface or one ray-tracing presentation draw. |
| `triangleCount` | Sum of mesh triangles across all placements; analytic ray-traced spheres contribute zero. |
| `rayTracing` | Optional internal resolution, effective scale, sampled-pixel coverage, smoothed frame time, and accumulated samples; present only for the `raytrace` renderer. |

`frame.statistics` is initialized with zeroes and updated by each `frame.render()` call.

Expand Down
13 changes: 9 additions & 4 deletions docs/api-reference/experimental/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ forward renderer.
passes derive world-space instance bounds, build and refit the existing
[`GPUBVH`](/docs/api-reference/experimental/gpu-primitives/gpu-bvh), and traverse its complete
binary hierarchy for nearest-hit rays and early-exit shadows. `RayTracingSceneRenderOptions` add
analytic sphere metadata, perspective/orthographic camera selection, progressive primary-ray
accumulation, and HDR presentation. The ray pass uses five storage buffers and the existing BVH
builder uses eight, fitting default WebGPU CORE limits. Applications retain command-submission
ownership.
analytic sphere metadata, perspective/orthographic camera selection, adaptive half-resolution
rendering, interleaved pixel phases, retained-identity temporal reprojection, bounded rotating
shadow samples, progressive accumulation, and upsampled HDR presentation. The default `0.5`
resolution scale can decrease to `0.25` toward a `33.3` millisecond smoothed animation-frame
budget; GPU timestamp queries are not required. Acceleration passes run only when geometry or
instance transforms change. Shared scene statistics optionally expose internal dimensions,
effective scale, sampled-pixel coverage, frame timing, and accumulated samples. The ray pass uses
five storage buffers and the existing BVH builder uses eight, fitting default WebGPU CORE limits.
Applications retain command-submission ownership.

The source-order BVH accelerates objects and instances, not individual mesh triangles. Hardware ray
tracing, spatial sorting, per-mesh BVHs, indirect path tracing, denoising, and volume rendering are
Expand Down
4 changes: 2 additions & 2 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ Target Release Date: Q3, 2026
**@luma.gl/anari (Experimental)**

- **[Retained physically based rendering](/docs/api-guide/engine/anari-rendering)** - The private ANARI-inspired workspace maps committed handles, staged parameters, instances, cameras, lights, and 17 material texture slots onto shared forward and WebGPU deferred scene renderers, including automatic opaque-scene capture for transmissive materials.
- **Pluggable GPU-compute ray tracing** - `ANARIDevice.registerRenderer()` registers lazy custom runtimes, while the WebGPU-only `raytrace` subtype adapts committed scenes to the shared experimental `RayTracingSceneRenderer` for GPU-built object/instance BVHs, accelerated analytic sphere/mesh selection, early-exit direct-light shadows, progressive sampling, and HDR presentation within default WebGPU CORE limits.
- **Pluggable interactive GPU-compute ray tracing** - `ANARIDevice.registerRenderer()` registers lazy custom runtimes, while the WebGPU-only `raytrace` subtype adapts committed scenes to the shared experimental `RayTracingSceneRenderer` for GPU-built object/instance BVHs, adaptive half-resolution rendering, interleaved pixel phases, stable-instance temporal reprojection, bounded rotating shadows, progressive sampling, and upsampled HDR presentation within default WebGPU CORE limits.
- **[Optional glTF animation integration](/docs/api-reference/anari/anari-animation)** - The isolated `@luma.gl/anari/gltf` entry point binds imported node hierarchies, material and sampler pointers, and morph-weight tracks to retained objects while committing each changed object at most once per frame.
- **Source-faithful retained assets** - JSON scenes preserve indexed geometry, both UV sets, tangents, RGBA vertex colors, joint attributes, morph targets, authored samplers, punctual lights, and `OPAQUE`/`MASK`/`BLEND` modes; programmatic renderer parameters can additionally supply caller-owned image-based-lighting textures.

**@luma.gl/experimental**

- **[Shared physical scene rendering](/docs/api-reference/experimental/scene-renderer)** - `SceneRenderer` renders format-independent physically based surfaces on WebGL and WebGPU with reusable instanced geometry, staged material updates, explicit joint palettes, morph deformation, punctual lights, and caller-provided image-based-lighting textures.
- **[Deferred physical scene rendering](/docs/api-reference/experimental/deferred-scene-renderer)** - `DeferredSceneRenderer` reuses the same scene descriptors through a four-target HDR G-buffer and lighting resolve that fits the default 32-byte WebGPU CORE limit, automatically falling back to the shared forward renderer for unsupported scenes.
- **Shared GPU-accelerated software ray tracing** - `RayTracingSceneRenderer` composes world-space instance bounds, existing `GPUBVH` construction/refitting, nearest-hit traversal, early-exit shadow rays, progressive accumulation, and HDR presentation through one WebGPU compute/command graph. The tracing pass uses five storage buffers, the BVH builder uses eight, mesh triangles remain linearly refined, and command submission stays application-owned.
- **Shared interactive GPU-accelerated ray tracing** - `RayTracingSceneRenderer` composes world-space instance bounds, dirty-only `GPUBVH` construction/refitting, nearest-hit traversal, bounded direct-light shadows, adaptive internal resolution, interleaved frame-budget coverage, stable-identity temporal reprojection, progressive accumulation, and upsampled HDR presentation through WebGPU compute/command graphs. Frame pacing uses ordinary animation intervals, the tracing pass uses five storage buffers, the BVH builder uses eight, mesh triangles remain linearly refined, and command submission stays application-owned.
- **[Generated physical lighting environments](/docs/api-reference/experimental/pbr-environment)** - `PBREnvironmentGenerator` and `preparePBREnvironment()` integrate equirectangular source textures into GGX-prefiltered specular cubemap mip chains, diffuse irradiance cubemaps, and split-sum BRDF lookup textures on both WebGL and WebGPU.
- **Scene-color transmission and volume attenuation** - The shared forward renderer captures opaque scene color automatically for transmissive surfaces, then applies screen-space refraction, roughness, Fresnel response, index of refraction, thickness, and Beer-Lambert attenuation while preserving physically opaque output.
- **`HTMLTexture`** - Experimental copied texture binding source copies HTML-in-Canvas DOM subtrees into GPU textures while the browser API is still experimental.
Expand Down
33 changes: 31 additions & 2 deletions examples/showcase/anari/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ const DEFAULT_RENDERER_PARAMETERS: ANARIRendererParameters = {
fogColor: [0.018, 0.025, 0.065],
fogDensity: 0.00024
};
const DEFAULT_RAY_TRACING_PARAMETERS: ANARIRendererParameters = {
resolutionScale: 0.5,
minimumResolutionScale: 0.25,
adaptiveResolution: true,
targetFrameTimeMilliseconds: 33.3,
temporalReprojection: true,
shadowSamplesPerFrame: 1,
progressive: true,
shadows: true
};

export default class ANARIShowcase extends AnimationLoopTemplate {
static info = '';
Expand Down Expand Up @@ -94,7 +104,7 @@ export default class ANARIShowcase extends AnimationLoopTemplate {
raytrace: this.anari.newRenderer('raytrace', {
...DEFAULT_RENDERER_PARAMETERS,
bloomIntensity: 0,
shadows: true
...DEFAULT_RAY_TRACING_PARAMETERS
}),
debugNormals: this.anari.newRenderer('debugNormals', {
background: [0.027, 0.033, 0.06, 1]
Expand Down Expand Up @@ -167,6 +177,25 @@ export default class ANARIShowcase extends AnimationLoopTemplate {
if (elapsedSeconds - this.lastStatisticsUpdate > 0.3) {
setElementText('instance-count', statistics.instanceCount.toLocaleString());
setElementText('draw-count', statistics.drawCount.toLocaleString());
const rayTracing = statistics.rayTracing;
const resolutionTelemetry = document.getElementById('ray-tracing-resolution-telemetry');
const frameTelemetry = document.getElementById('ray-tracing-frame-telemetry');
if (resolutionTelemetry) {
resolutionTelemetry.hidden = !rayTracing;
}
if (frameTelemetry) {
frameTelemetry.hidden = !rayTracing;
}
if (rayTracing) {
setElementText(
'ray-tracing-resolution',
`${rayTracing.internalWidth} × ${rayTracing.internalHeight} · ${Math.round(rayTracing.resolutionScale * 100)}%`
);
setElementText(
'ray-tracing-frame',
`${rayTracing.frameTimeMilliseconds.toFixed(1)} ms · ${Math.round(rayTracing.sampledPixelCoverage * 100)}% · ${rayTracing.accumulatedSamples} spp`
);
}
this.lastStatisticsUpdate = elapsedSeconds;
}
}
Expand Down Expand Up @@ -291,7 +320,7 @@ export default class ANARIShowcase extends AnimationLoopTemplate {
...DEFAULT_RENDERER_PARAMETERS,
...rendererParameters,
bloomIntensity: 0,
shadows: true
...DEFAULT_RAY_TRACING_PARAMETERS
})
.commitParameters();
this.frame.setParameter('world', scene.world).commitParameters();
Expand Down
Loading
Loading