Skip to content
Draft
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
13 changes: 7 additions & 6 deletions docs/api-guide/engine/anari-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -702,12 +702,13 @@ WebGPU/WebGL selection, a renderer selector for frame presentation, automatic HD
available, orbit controls, validation feedback, and live instance, draw-call, and triangle
statistics.

Use **GLTF ↓** or **USD ↓** to download the currently valid retained scene. Export bakes procedural
geometry, starfield distributions, and retained instances into a static snapshot; transfers mesh
positions, normals, UVs, vertex colors, materials, texture images, camera, and supported lights;
and emits standalone JSON glTF with embedded buffers/images or ASCII `.usda`. ANARI animation
declarations, optional renderer presets, bloom, fog, and renderer-only HDR controls remain
ANARI-specific and are not exported.
Use **GLTF ↓** or **USD ↓** to download the currently valid retained scene. Both paths bake
procedural geometry, starfield distributions, and retained instances; transfer mesh positions,
normals, UVs, vertex colors, materials, texture images, cameras, and supported lights; and emit
standalone JSON glTF with embedded resources or ASCII `.usda`. glTF additionally preserves
compatible source hierarchies, skeletal skins, morph targets, transform and morph animations, and
supported material animation pointers. ASCII USD export remains static. Renderer presets, bloom,
fog, and renderer-only HDR controls remain ANARI-specific.

:::caution[Experimental playground format]
The JSON format and its optional schema exports are experimental. They are not part of the ANARI C
Expand Down
4 changes: 2 additions & 2 deletions docs/api-reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ If you are looking for `Model`, start with [`@luma.gl/engine`][engine]. The `Mod
| [`@luma.gl/text`][text] | Experimental / Private | `TextRenderer` facade and caller-owned GPU text data. |
| [`@luma.gl/splats`][splats] | Experimental / Private | Gaussian splat rendering and caller-owned prepared GPU splat data. |
| [`@luma.gl/experimental`][experimental] | Experimental / Private | Experimental v10 APIs, including WebGPU/WebGL WebXR and WebGL raw camera helpers. |
| [`@luma.gl/gltf`][gltf] | Optional | Standards-first glTF assets, physical materials, character animation, and lossless interchange. |
| [`@luma.gl/gltf`][gltf] | Optional | Standards-native glTF/GLB assets, physical materials, character animation, and source-faithful interchange. |
| [`@luma.gl/test-utils`][test-utils] | Optional | Test setups, in particular support for rendering and comparing images. |

\* At least one backend, either WebGL or WebGPU, must be installed to enable GPU resource creation.
Expand All @@ -40,7 +40,7 @@ If you are looking for `Model`, start with [`@luma.gl/engine`][engine]. The `Mod
- [`@luma.gl/text`][text] for `TextRenderer` and GPU text data; use [`@luma.gl/arrow`][arrow] for Arrow conversion.
- [`@luma.gl/splats`][splats] for experimental Gaussian splat rendering and caller-owned prepared GPU data.
- [`@luma.gl/experimental`][experimental] for v10 work-in-progress APIs, including experimental WebXR frame, view, and raw camera helpers.
- [`@luma.gl/gltf`][gltf] for standards-first glTF assets, physical materials, character animation, native extensions, and source-faithful `.gltf`/`.glb` interchange.
- [`@luma.gl/gltf`][gltf] for standards-native glTF/GLB scenegraphs, physical materials, automatic skeletal/morph animation, material variants, instancing, visibility, and source-faithful descriptor interchange.
- [`@luma.gl/webgl`][webgl] and [`@luma.gl/webgpu`][webgpu] for backend adapters used by `@luma.gl/core`.
- [`@luma.gl/webgl/constants`](/docs/api-reference/webgl/constants) when you need raw numeric WebGL enums.

Expand Down
11 changes: 7 additions & 4 deletions docs/api-reference/anari/anari-animation.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ The showcase importer preserves morph `POSITION`, `NORMAL`, and `TANGENT` deltas
node/mesh weights, and node-local geometry identities. Retained node weight animation updates the
existing mesh vertex data without rebuilding its model.

Source `JOINTS_0` and `WEIGHTS_0` attributes are also preserved, and programmatic surfaces can
use `skin: {jointMatrices}`. The showcase importer does not currently create or animate that joint
palette automatically; complete imported skeletal playback requires application-provided palette
integration. See [ANARI arrays and geometry](/docs/api-reference/anari/anari-geometry).
Source `JOINTS_0` and `WEIGHTS_0` attributes, authored joint-node hierarchies, and optional inverse
bind matrices are preserved. The showcase importer automatically creates mesh-local retained joint
palettes and updates them after source skeletal clips advance; each changed surface is committed at
most once per frame. Applications can also supply an explicit `skin: {jointMatrices}` descriptor
when they own a programmatic palette. Skinning remains in the existing shared shader and generic
engine deformation helpers, not in a separate ANARI implementation. See
[ANARI arrays and geometry](/docs/api-reference/anari/anari-geometry).

## Validation

Expand Down
8 changes: 5 additions & 3 deletions docs/api-reference/anari/anari-geometry.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,11 @@ const surface = anariDevice.newSurface({

`jointMatrices` is a `Float32Array` or numeric array containing column-major joint matrices. The
existing shared skinning module currently supports up to 64 joints. The glTF showcase importer
preserves source joint indices and converts normalized integer `WEIGHTS_0` values to floats, but
does not automatically create or animate the surface joint palette; applications must supply and
update that palette explicitly.
preserves source joint indices, converts normalized integer `WEIGHTS_0` values to floats, and
automatically creates mesh-local joint palettes from source joints and inverse bind matrices.
Imported skeletal clips refresh those palettes after each animation frame. Explicit
`skin: {jointMatrices}` remains available for programmatic surfaces whose application supplies and
updates its own palette.

### Morph targets

Expand Down
109 changes: 102 additions & 7 deletions docs/api-reference/gltf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {GLTFExample} from '@site/src/examples';
<GltfDocsTabs active="overview" />

`@luma.gl/gltf` is a standards-first asset runtime for physically based materials, animated
characters, morph deformation, native animation pointers, and source-faithful `.gltf` / `.glb`
interchange across WebGPU and WebGL. It turns postprocessed glTF assets into ordinary luma.gl
scenegraphs and exports generic scene descriptors without depending on a particular renderer.
characters, automatic skeletal deformation, morph targets, material variants, GPU instancing,
recursive node visibility, and typed animation pointers across WebGPU and WebGL. It turns
postprocessed glTF assets into ordinary luma.gl scenegraphs and exports source-faithful `.gltf` /
`.glb` scene descriptors without taking ownership of a renderer.

File loading, decompression, and glTF postprocessing belong to `@loaders.gl/gltf`; animation
primitives, geometry, and shader modules remain in their existing luma.gl packages.
Expand Down Expand Up @@ -43,7 +44,8 @@ const gltf = postProcessGLTF(asset);

const scenegraphs = createScenegraphsFromGLTF(device, gltf, {
useTangents: true,
useByteColors: false
useByteColors: false,
strictExtensions: true
});

for (const scene of scenegraphs.scenes) {
Expand All @@ -56,6 +58,9 @@ function renderFrame(timeMilliseconds: number): void {
}

requestAnimationFrame(renderFrame);

// When the asset is no longer needed, release every model and owned GPU resource.
window.addEventListener('pagehide', () => scenegraphs.destroy(), {once: true});
```

`GLTFAnimator.setTime()` takes an absolute clock value in **milliseconds**. The shared
Expand All @@ -77,15 +82,20 @@ bundle contains:
| --- | --- |
| `scenes` | One `@luma.gl/engine` `GroupNode` root per source scene. |
| `materials` | Shared engine materials in source glTF material order. |
| `variants` | Source-authored `KHR_materials_variants` controller with selection and reset. |
| `cameras` | Independent source camera definitions updated by supported animation pointers. |
| `animator` | A `GLTFAnimator` backed by the shared engine animation mixer. |
| `animations` | Decoded source clips, including supported animation-pointer channels. |
| `skins` | Automatically updated mesh-local skin palettes and source joint bindings. |
| `lights` | World-space directional, point, and spot lights from `KHR_lights_punctual`. |
| `extensionSupport` | A map describing support for extensions reported by the asset. |
| `sceneBounds` | World-space bounds and camera-framing recommendations for each scene. |
| `modelBounds` | Combined world-space bounds for the complete asset. |
| `gltfNodeIdToNodeMap`, `gltfNodeIndexToNodeMap` | Source-node lookup tables for application integration. |
| `gltfMeshIdToNodeMap` | Source-mesh lookup table. |
| `resourceCache` | Asset-owned or explicitly shared GPU texture and material-specialization cache. |
| `gltf` | The original postprocessed glTF document. |
| `destroy()`, `dispose()` | Idempotent release of every scene-owned model, material, and GPU buffer. |

Each bounds object contains `bounds`, `center`, `size`, `radius`, and
`recommendedOrbitDistance`.
Expand All @@ -100,6 +110,8 @@ type ParseGLTFOptions = {
lights?: boolean;
useTangents?: boolean;
useByteColors?: boolean;
strictExtensions?: boolean;
resourceCache?: GLTFAssetResourceCache;
};
```

Expand All @@ -112,14 +124,52 @@ type ParseGLTFOptions = {
tangent data.
- `useByteColors: false` keeps authored punctual-light colors in the linear `[0, 1]` range. The
default preserves luma.gl's legacy byte-style light-color convention.
- `strictExtensions: true` rejects required glTF extensions that do not have a complete supported
runtime path. Optional unsupported extensions remain visible in `extensionSupport`.
- `resourceCache` shares compatible asset textures and parsed material specializations across
independently owned scenegraphs. Omit it to give the returned scenegraph an automatic private
cache.

Import the complete public option and return types directly from the package root:

```ts
import type {GLTFScenegraphs, ParseGLTFOptions} from '@luma.gl/gltf';
```

Parsed CPU geometry retains source semantics such as `POSITION`, `NORMAL`, `TANGENT`, `COLOR_0`,
`TEXCOORD_0`, `TEXCOORD_1`, `JOINTS_0`, and `WEIGHTS_0`. Shader-facing attribute names are
resolved only at model boundaries.

## Source-native extension controls

The returned scenegraph preserves standards-native asset controls rather than converting them into
application-specific material or scene formats:

```ts
for (const name of scenegraphs.variants.names) {
console.log(name);
}

scenegraphs.variants.selectVariant('Midnight');
scenegraphs.variants.resetVariant();

const camera = scenegraphs.cameras[0];
const sourceNode = scenegraphs.gltfNodeIndexToNodeMap.get(0);
const sourceSkin = scenegraphs.skins.getBinding(0);
```

`EXT_mesh_gpu_instancing` creates one real instanced draw per source primitive; use
`getGLTFNodeInstancing()` to inspect its authored transforms and custom attributes.
`KHR_node_visibility` recursively suppresses hidden geometry and punctual lights. Supported
`KHR_animation_pointer` targets update node transforms, morph weights, visibility, material
factors, UV transforms, camera projections, and light properties.

See [native glTF extensions](/docs/api-reference/gltf/gltf-native-extensions) for complete
selection examples, support guarantees, and structural-material limitations.

## Materials, textures, and lights

The canonical PBR path preserves all 17 supported core and extension texture slots, authored
The canonical PBR path preserves all registered canonical material texture slots, authored
sampler addressing/filtering, generated or supplied mipmaps, per-slot UV transforms, secondary UV
coordinates, advanced material factors, alpha modes, and punctual lights.

Expand All @@ -140,12 +190,54 @@ See [glTF animation and deformation](/docs/api-reference/gltf/gltf-animation), t
[engine animation guide](/docs/api-guide/engine/animation), and
[glTF extension support](/docs/api-reference/gltf/gltf-extensions) for details and limitations.

## Asset lifetime and shared GPU resources

Every scenegraph owns its generated models, materials, geometry buffers, and instance buffers.
Generated source-image textures are cached by image identity, authored sampler settings, and
color/data interpretation. Identical images are uploaded once; differently wrapped, filtered, or
interpreted textures stay independent.

```ts
const scenegraphs = createScenegraphsFromGLTF(device, gltf);

// Safe to call multiple times; `dispose()` is an equivalent alias.
scenegraphs.destroy();
scenegraphs.dispose();
```

Scene destruction also releases hidden nodes and detached source-mesh templates. It never destroys
the application-owned `Device`, original source images, or caller-supplied image-based-lighting
environment textures.

### Share textures between independent scenegraphs

Create an explicit cache when independently animated scenegraphs should reuse immutable source
textures without sharing mutable materials, joint palettes, or scene nodes:

```ts
import {createScenegraphsFromGLTF, GLTFAssetResourceCache} from '@luma.gl/gltf';

const resourceCache = new GLTFAssetResourceCache(device);
const first = createScenegraphsFromGLTF(device, gltf, {resourceCache});
const second = createScenegraphsFromGLTF(device, gltf, {resourceCache});

console.log(resourceCache.textureCount, resourceCache.materialCount, resourceCache.referenceCount);

first.destroy();
second.destroy();
resourceCache.destroy();
```

A caller-supplied cache remains caller-owned after its final scenegraph is destroyed. If
`resourceCache.destroy()` is called while scenes still exist, destruction is safely deferred until
the last scene releases it. A cache can only be used with its original device.

## Source-faithful asset interchange

`exportGLTF()` serializes renderer-independent glTF scene descriptors as embedded JSON or binary
GLB. Existing hierarchy, skins, inverse bind matrices, morph targets, animation clips, material
pointers, variants, GPU instancing, cameras, punctual lights, sampler settings, and authored
physical materials remain available to the output asset.
physical materials remain available to the output asset when present in the supplied descriptor.

```ts
import {exportGLTF, type GLTFExportScene} from '@luma.gl/gltf';
Expand All @@ -156,13 +248,16 @@ const binary: ArrayBuffer = exportGLTF(scene, {binary: true});
```

See [glTF asset interchange](/docs/api-reference/gltf/gltf-interchange) for typed descriptors,
RGBA vertex colors, normalized joint weights, animation pointers, and resource ownership.
RGBA vertex colors, normalized joint weights, animation pointers, and resource ownership. Export
consumes a `GLTFExportScene` descriptor; it is not an automatic byte-for-byte repackager for an
arbitrary loaded asset or its original external-file layout.

## Package ownership

- `@loaders.gl/gltf` loads and decompresses `.gltf` and `.glb` assets.
- `@luma.gl/gltf` interprets glTF-specific scene, material, sampler, light, and animation data.
- `@luma.gl/engine` owns generic scenegraph, animation, and morph-target primitives.
- `@luma.gl/shadertools` owns the shared PBR, lighting, and skinning shader modules.
- `@luma.gl/experimental` owns optional high-level physical rendering and captured-scene refraction.
- `@luma.gl/anari/gltf`, when explicitly imported, adapts decoded glTF data to retained ANARI
objects without making the core ANARI entry point a glTF loader.
11 changes: 7 additions & 4 deletions docs/capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,14 @@ Try [Lightstorm Megacity](/examples/showcase/lightstorm-megacity),
| Authored normals and tangents | Evolving | WebGPU + WebGL2 | `@luma.gl/gltf` | Preserve supported vertex attributes; complete renderer-to-renderer fidelity varies. |
| Punctual-light parsing | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Parse supported authored directional, point, and spot light definitions. |
| Shared animation clips | Available | WebGPU + WebGL2 | `@luma.gl/engine` | Play, blend, crossfade, loop, and interpolate compatible imported tracks. |
| Selected animation pointers | Evolving | WebGPU + WebGL2 | `@luma.gl/gltf` | Update supported `KHR_animation_pointer` transforms, material factors, and UV properties. |
| Selected animation pointers | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Update supported `KHR_animation_pointer` transforms, morph weights, visibility, material factors, UV transforms, cameras, and punctual lights. |
| Existing joint-driven skinning | Available | WebGPU + WebGL2 | `@luma.gl/shadertools` | Reuse established skin shaders and automatically bind mesh-local glTF joint palettes. |
| Morph-target animation | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Animate POSITION, NORMAL, and TANGENT morph targets through shared glTF, engine, and retained-scene paths. |
| Imported GPU instancing | Opportunity | WebGPU + WebGL2 | `@luma.gl/gltf` | `EXT_mesh_gpu_instancing` is not yet translated into retained instance batches. |
| Imported node visibility | Opportunity | WebGPU + WebGL2 | `@luma.gl/gltf` | `KHR_node_visibility` does not yet have a supported runtime integration. |
| Imported GPU instancing | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | `EXT_mesh_gpu_instancing` creates one real instanced draw per canonical source primitive. |
| Imported node visibility | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | `KHR_node_visibility` recursively controls canonical scenegraph geometry, punctual lights, and supported STEP animation. |
| Source material variants | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Select and reset compatible `KHR_materials_variants` without replacing source scenegraph nodes. |
| Shared asset GPU resources | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Deduplicate compatible image uploads, reuse feature-specialized materials, and explicitly destroy owned scene resources. |
| Animated glTF and GLB interchange | Available | WebGPU + WebGL2 | `@luma.gl/gltf` | Export source-faithful scene descriptors with supported animation, skins, morph targets, materials, lights, and extensions. |

The ownership boundaries are intentional: `@luma.gl/gltf` interprets assets,
`@luma.gl/shadertools` owns shared shading, `@luma.gl/engine` owns generic animation,
Expand All @@ -438,7 +441,7 @@ See the [glTF extension support matrix](/docs/api-reference/gltf/gltf-extensions
| Retained animation playback | Experimental | WebGPU + WebGL2 | `@luma.gl/anari` | Play supported transform, material, and texture-coordinate animations. |
| Editable JSON scenes | Experimental | WebGPU + WebGL2 | `@luma.gl/anari` | Inspect and edit supported retained scene descriptions interactively. |
| Experimental OpenUSD import | Experimental | WebGPU + WebGL2 | `@luma.gl/anari` | The ANARI Playground imports supported ASCII USD and ASCII-root USDZ examples. |
| Scene-level skeletal animation | Opportunity | WebGPU + WebGL2 | `@luma.gl/anari` | Existing joint skinning has not yet been integrated into the retained ANARI renderer. |
| Scene-level skeletal animation | Experimental | WebGPU + WebGL2 | `@luma.gl/anari` | Imported glTF joint hierarchies automatically update retained mesh-local palettes through the existing shared skinning module. |

This is an ANARI-inspired proof of concept, not a claim of complete standards conformance.
Explore the [ANARI Playground](/examples/experimental/anari-playground).
Expand Down
Loading
Loading