gaussian-splat-lite 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +44 -2
  2. package/README.md +22 -13
  3. package/dist/gaussian-splat-lite.cjs +819 -88
  4. package/dist/gaussian-splat-lite.cjs.map +1 -1
  5. package/dist/gaussian-splat-lite.min.cjs +81 -20
  6. package/dist/gaussian-splat-lite.min.cjs.map +1 -1
  7. package/dist/gaussian-splat-lite.module.js +821 -90
  8. package/dist/gaussian-splat-lite.module.js.map +1 -1
  9. package/dist/gaussian-splat-lite.module.min.js +2984 -2427
  10. package/dist/gaussian-splat-lite.module.min.js.map +1 -1
  11. package/dist/types/addons/TAANode.d.cts +4 -2
  12. package/dist/types/addons/TAANode.d.ts +4 -2
  13. package/dist/types/addons/TAAPass.d.cts +6 -15
  14. package/dist/types/addons/TAAPass.d.ts +6 -15
  15. package/dist/types/addons/taaShared.d.cts +4 -2
  16. package/dist/types/addons/taaShared.d.ts +4 -2
  17. package/dist/types/capture/SplatCapture.d.cts +66 -0
  18. package/dist/types/capture/SplatCapture.d.ts +66 -0
  19. package/dist/types/capture/WebGLCapture.d.cts +13 -0
  20. package/dist/types/capture/WebGLCapture.d.ts +13 -0
  21. package/dist/types/capture/WebGPUCapture.d.cts +17 -0
  22. package/dist/types/capture/WebGPUCapture.d.ts +17 -0
  23. package/dist/types/capture/pixels.d.cts +5 -0
  24. package/dist/types/capture/pixels.d.ts +5 -0
  25. package/dist/types/capture/rendererState.d.cts +3 -0
  26. package/dist/types/capture/rendererState.d.ts +3 -0
  27. package/dist/types/capture/sceneView.d.cts +3 -0
  28. package/dist/types/capture/sceneView.d.ts +3 -0
  29. package/dist/types/index.d.cts +1 -1
  30. package/dist/types/index.d.ts +1 -1
  31. package/dist/types/rendering/GaussianSplatRenderer.d.cts +17 -11
  32. package/dist/types/rendering/GaussianSplatRenderer.d.ts +17 -11
  33. package/dist/types/rendering/SplatAccumulator.d.cts +2 -1
  34. package/dist/types/rendering/SplatAccumulator.d.ts +2 -1
  35. package/dist/types/rendering/backend.d.cts +1 -1
  36. package/dist/types/rendering/backend.d.ts +1 -1
  37. package/dist/types/rendering/rendererUtils.d.cts +1 -5
  38. package/dist/types/rendering/rendererUtils.d.ts +1 -5
  39. package/dist/types/rendering/tsl/ProjectionProgram.d.cts +2 -0
  40. package/dist/types/rendering/tsl/ProjectionProgram.d.ts +2 -0
  41. package/dist/types/rendering/tsl/SplatMaterial.d.cts +1 -0
  42. package/dist/types/rendering/tsl/SplatMaterial.d.ts +1 -0
  43. package/dist/types/rendering/tsl/tslCompat.d.cts +1 -0
  44. package/dist/types/rendering/tsl/tslCompat.d.ts +1 -0
  45. package/dist/types/rendering/uniforms.d.cts +3 -3
  46. package/dist/types/rendering/uniforms.d.ts +3 -3
  47. package/dist/types/scene/SplatMesh.d.cts +1 -1
  48. package/dist/types/scene/SplatMesh.d.ts +1 -1
  49. package/docs/Architecture.md +54 -3
  50. package/docs/GaussianSplatRenderer.md +71 -55
  51. package/docs/PostDecode.md +52 -36
  52. package/docs/RadStreamScheduler.md +53 -41
  53. package/docs/SogStreamScheduler.md +49 -39
  54. package/docs/SplatCapture.md +147 -0
  55. package/docs/SplatEdit.md +33 -26
  56. package/docs/SplatFileType.md +11 -13
  57. package/docs/SplatLoader.md +19 -14
  58. package/docs/SplatMesh.md +69 -49
  59. package/docs/Splats.md +33 -26
  60. package/docs/StochasticRendering.md +27 -30
  61. package/docs/TAAPass.md +98 -73
  62. package/package.json +1 -1
  63. package/docs/SplatAccumulator.md +0 -37
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- `SplatLoader` follows the Three.js `Loader` API. Load a model as `Splats` data, then use `parse()` to create a scene object.
5
+ `SplatLoader` works like other Three.js loaders. It loads a model as [Splats](Splats.md) data, and `parse()` turns that data into a `SplatMesh` for your scene. The format is detected automatically.
6
6
 
7
7
  ```js
8
8
  import { SplatLoader } from "gaussian-splat-lite";
@@ -16,7 +16,7 @@ const splat = loader.parse(decoded);
16
16
  scene.add(splat);
17
17
  ```
18
18
 
19
- The callback form matches the normal Three.js Loader pattern:
19
+ The callback form matches the usual Three.js pattern:
20
20
 
21
21
  ```js
22
22
  loader.load(
@@ -27,7 +27,13 @@ loader.load(
27
27
  );
28
28
  ```
29
29
 
30
- `loadAsync(url, onProgress?, signal?)` accepts an optional `AbortSignal`. Use it to cancel loading:
30
+ If you do not need the loader API, `new SplatMesh({ url })` loads a model in one step; see [SplatMesh](SplatMesh.md).
31
+
32
+ For large RAD scenes with levels of detail, use [RadStreamScheduler](RadStreamScheduler.md). For SOG `lod-meta.json` scenes, use [SogStreamScheduler](SogStreamScheduler.md).
33
+
34
+ ## Cancel loading
35
+
36
+ `loadAsync(url, onProgress?, signal?)` accepts an optional `AbortSignal`:
31
37
 
32
38
  ```js
33
39
  const controller = new AbortController();
@@ -35,26 +41,25 @@ const loading = loader.loadAsync("/assets/model.sog", undefined, controller.sign
35
41
  controller.abort(); // `loading` rejects with the signal's reason.
36
42
  ```
37
43
 
38
- `loader.abort()` cancels every load the loader has in progress; loads started afterwards are not affected. For `Splats` or `SplatMesh`, call `dispose()` to cancel a pending load.
39
-
40
- For large RAD scenes with levels of detail, use [RadStreamScheduler](RadStreamScheduler.md).
41
- For `lod-meta.json` scenes, use [SogStreamScheduler](SogStreamScheduler.md).
44
+ `loader.abort()` cancels every load the loader has in progress; loads started afterwards are not affected. For a `Splats` or `SplatMesh` that is still loading, call its `dispose()`.
42
45
 
43
46
  ## Loading progress
44
47
 
45
- `onProgress` receives a `SplatProgressEvent` (a `ProgressEvent` with a `stage` field). This also applies to `Splats` and `SplatMesh`:
48
+ `onProgress` receives a `SplatProgressEvent`: a standard `ProgressEvent` with an extra `stage` field. `Splats` and `SplatMesh` report progress the same way.
46
49
 
47
50
  | `stage` | `loaded` / `total` |
48
51
  | --- | --- |
49
- | `download` | Bytes read or downloaded; `total === 0` means unknown size |
50
- | `postDecode` | Splats processed by the configured `postDecode` program |
51
- | `optimize` | Completed work units for Morton ordering and bounding-box calculation |
52
+ | `download` | Bytes read or downloaded; `total === 0` means the size is unknown |
53
+ | `postDecode` | Splats processed by your [`postDecode`](PostDecode.md) program; skipped when none is set |
54
+ | `optimize` | Steps completed while preparing the model for rendering |
55
+
56
+ Progress starts again from zero for each stage. Use `event.loaded / event.total` when `event.lengthComputable` is true. It measures completed work, not time.
52
57
 
53
- Progress restarts for each stage. Use `event.loaded / event.total` when `event.lengthComputable` is true. `postDecode` is skipped when no program is configured; empty work reports completion immediately. Percentages describe completed work, not elapsed time. Download completion can precede the end of decoding; wait for `loadAsync()` or `.initialized` to resolve before using the model.
58
+ The model is ready when `loadAsync()` or `.initialized` resolves, which can be a little after the download reaches 100%.
54
59
 
55
60
  ## Local split files
56
61
 
57
- Single `.sog` and `.rad` files need only `file`. For a local SOG `meta.json` with external `.webp` images, supply those images through `resolveFile`. The same option resolves external RAD `.radc` pages:
62
+ A single `.sog` or `.rad` file needs only `file`. Some models are split across several files: a SOG `meta.json` with `.webp` images, or a RAD file with `.radc` pages. For these, pass the main file as `file` and supply the others through `resolveFile`:
58
63
 
59
64
  ```js
60
65
  import { SplatMesh } from "gaussian-splat-lite";
@@ -75,4 +80,4 @@ scene.add(mesh);
75
80
  await mesh.initialized;
76
81
  ```
77
82
 
78
- A resolver may return a URL, `Blob`, `Uint8Array`, or `ArrayBuffer`, directly or as a promise. For subfolders, match the paths referenced by the model.
83
+ `resolveFile` is called with each file name the model refers to. Return a URL, `Blob`, `Uint8Array`, or `ArrayBuffer`, directly or as a promise. If the model refers to files in subfolders, match those paths.
package/docs/SplatMesh.md CHANGED
@@ -2,15 +2,19 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- `SplatMesh` is a `THREE.Object3D` with standard transforms, visibility, layers, and children.
5
+ A Splat model in your scene. `SplatMesh` is a `THREE.Object3D`, so position, rotation, scale, visibility, layers, and children work as usual.
6
6
 
7
- ```ts
8
- new SplatMesh(options?: SplatMeshOptions)
7
+ ```js
8
+ import { SplatMesh } from "gaussian-splat-lite";
9
+
10
+ const splat = new SplatMesh({ url: "/assets/model.spz" });
11
+ scene.add(splat);
12
+ await splat.initialized;
9
13
  ```
10
14
 
11
15
  ## Loading
12
16
 
13
- Use `url` for remote files. For a local PLY/SPZ/SOG/RAD file:
17
+ Use `url` for a remote file. For a local PLY, SPZ, SOG, or RAD file:
14
18
 
15
19
  ```js
16
20
  const file = fileInput.files[0];
@@ -19,68 +23,85 @@ scene.add(splat);
19
23
  await splat.initialized;
20
24
  ```
21
25
 
22
- `file` accepts a `File` or `Blob`. For bytes, use `fileBytes: bytes`; `fileName` or `fileType` can supply an explicit format hint for any input.
26
+ `file` accepts a `File` or `Blob`. For data already in memory, use `fileBytes`. The format is detected from the file name; pass `fileName` or [`fileType`](SplatFileType.md) when there is no name to go by.
27
+
28
+ Splats are reordered while loading, so their indices differ from the order in the file; see [data rules](Splats.md#data-rules).
23
29
 
24
- Loaded indices may differ from file order; see [data rules](Splats.md#data-rules).
30
+ For large streamed scenes, use [RadStreamScheduler](RadStreamScheduler.md) or [SogStreamScheduler](SogStreamScheduler.md) instead.
25
31
 
26
32
  ## Options
27
33
 
28
34
  | Option | Type | Default | Description |
29
35
  | --- | --- | --- | --- |
30
- | `url` | `string` | `undefined` | PLY/SPZ/SOG/RAD file or SOG metadata URL |
36
+ | `url` | `string` | `undefined` | PLY/SPZ/SOG/RAD file or SOG `meta.json` URL |
31
37
  | `file` | `Blob` (including `File`) | `undefined` | Local file |
32
38
  | `fileBytes` | `Uint8Array \| ArrayBuffer` | `undefined` | Complete file data in memory |
33
- | `fileType` | `SplatFileType` | Inferred from name | Explicitly selects `PLY`, `SPZ`, `SOG`, or `RAD` |
34
- | `fileName` | `string` | `File.name` when available | Supplies a name for inferring the input format |
35
- | `resolveFile` | `SplatFileResolver` | `undefined` | Resolves external SOG images or RAD pages by metadata filename; see [local split files](SplatLoader.md#local-split-files) |
36
- | `postDecode` | `SplatPostDecodeProgram` | `undefined` | Apply a [load-time transform](PostDecode.md) to each Splat |
37
- | `splats` | `Splats` | New `Splats` | Uses an existing `Splats` instance |
38
- | `onProgress` | `(event: SplatProgressEvent) => void` | `undefined` | [Per-stage loading progress](SplatLoader.md#loading-progress) callback |
39
- | `onLoad` | `(mesh) => void \| Promise<void>` | `undefined` | Called after initialization completes |
40
- | `editable` | `boolean` | `true` | Allow scene-wide and model-specific region edits |
41
- | `raycastable` | `boolean` | `true` | Participates in Three.js raycasting |
42
- | `minRaycastOpacity` | `number` | `0.15` | Ignore more transparent areas when picking; higher values narrow the hit area |
43
- | `onFrame` | `({ mesh, time, deltaTime }) => void` | `undefined` | Called before each model update; use for animation |
44
-
45
- Choose at most one of `url`, `file`, `fileBytes`, or `splats`; mixing inputs throws.
46
-
47
- ## Common properties
39
+ | `fileType` | `SplatFileType` | Detected from the name | Set the format explicitly: `PLY`, `SPZ`, `SOG`, or `RAD` |
40
+ | `fileName` | `string` | `File.name` when available | Name used to detect the format |
41
+ | `resolveFile` | `SplatFileResolver` | `undefined` | Supply the extra files of a split SOG or RAD model; see [local split files](SplatLoader.md#local-split-files) |
42
+ | `postDecode` | `SplatPostDecodeProgram` | `undefined` | [Change each Splat while loading](PostDecode.md) |
43
+ | `splats` | `Splats` | New `Splats` | Use existing [Splats](Splats.md) data instead of loading |
44
+ | `onProgress` | `(event: SplatProgressEvent) => void` | `undefined` | [Loading progress](SplatLoader.md#loading-progress) callback |
45
+ | `onLoad` | `(mesh) => void \| Promise<void>` | `undefined` | Called when loading completes |
46
+ | `onFrame` | `({ mesh, time, deltaTime }) => void` | `undefined` | Called before each update of the model; use it for animation |
47
+ | `editable` | `boolean` | `true` | Allow [SDF edits](SplatEdit.md) to affect this model |
48
+ | `raycastable` | `boolean` | `true` | Include this model in Three.js raycasting |
49
+ | `minRaycastOpacity` | `number` | `0.15` | Ignore more transparent areas when picking; higher values narrow the area that can be hit |
50
+
51
+ Choose at most one of `url`, `file`, `fileBytes`, or `splats`; combining them throws.
52
+
53
+ ## Properties
48
54
 
49
55
  | Property | Type / default | Description |
50
56
  | --- | --- | --- |
51
- | `initialized` | `Promise<SplatMesh>` | Resolves after loading and the `onLoad` callback |
52
- | `isInitialized` | `boolean` | Whether initialization has completed |
57
+ | `initialized` | `Promise<SplatMesh>` | Resolves when loading and the `onLoad` callback have finished |
58
+ | `isInitialized` | `boolean` | Whether loading has finished |
53
59
  | `numSplats` | `number` | Current Splat count |
54
- | `recolor` | `THREE.Color(1, 1, 1)` | RGB multiplier applied to the entire object |
55
- | `opacity` | `1` | Opacity multiplier applied to the entire object |
56
- | `maxSh` | `3` | Limit view-dependent color detail; `0` uses base color only |
57
- | `edits` | `SplatEdit[] \| null` | Explicit edits applied only to this mesh |
58
- | `splats` | `Splats \| undefined` | Current underlying Splat data |
59
- | `needsUpdate` | `boolean` setter | Set to `true` to force a refresh; `false` does nothing |
60
+ | `recolor` | `THREE.Color(1, 1, 1)` | Color multiplier for the whole model |
61
+ | `opacity` | `1` | Opacity multiplier for the whole model |
62
+ | `maxSh` | `3` | Limit view-dependent color detail; `0` uses the base color only |
63
+ | `edits` | `SplatEdit[] \| null` | Explicit list of [edits](SplatEdit.md) for this mesh |
64
+ | `splats` | `Splats \| undefined` | The model's [Splats](Splats.md) data |
65
+ | `needsUpdate` | `boolean` setter | Set to `true` to force a refresh |
60
66
 
61
- When the mesh's `Splats` is reinitialized, `initialized` and `isInitialized` follow the new load, and `onLoad` runs again once it finishes.
67
+ Changes to the transform, `recolor`, `opacity`, `maxSh`, and edits are picked up automatically. If the mesh's `Splats` is loaded again, `initialized` and `isInitialized` follow the new load, and `onLoad` runs again when it finishes.
62
68
 
63
- ## Common methods
69
+ ## Methods
64
70
 
65
71
  ```ts
66
72
  await mesh.initialized;
67
73
 
68
- mesh.getBoundingBox(); // Centers only.
69
- mesh.getBoundingBox(false); // Includes scale, rotation and shape at alpha 0.01.
74
+ mesh.getBoundingBox(); // Box around the Splat centers.
75
+ mesh.getBoundingBox(false); // Box that also covers each Splat's size and shape.
70
76
 
71
77
  mesh.forEachSplat((index, center, scales, quaternion, opacity, color) => {});
72
78
 
73
- mesh.updateVersion(); // Regenerate and re-sort.
74
- mesh.updateVersion({ sort: false }); // Appearance only; reuse sorting.
75
- mesh.updateMappingVersion(); // Count or mapping changed.
76
79
  mesh.dispose();
77
80
  ```
78
81
 
79
- Bounds require initialization. `getBoundingBox()` returns a new `Box3` in mesh-local space; pass `false` to include Splat scale, rotation and kernel shape at a fixed source-opacity threshold of `0.01`. Splats below this threshold are omitted from these expanded bounds. These bounds do not track renderer settings, mesh opacity, streaming fades or SDF edits. Pass an existing box as the second argument, `mesh.getBoundingBox(true, target)`, to reuse it and avoid allocating a new box. Bounds include zero-scale Splats that meet the opacity threshold and ignore non-finite centers. Streamed bounds follow the visible selection, but RAD bounds may also include unselected Splats.
82
+ ### Bounding box
83
+
84
+ `getBoundingBox()` returns a new `Box3` in the mesh's local space; the mesh must be initialized first. To avoid creating a box each time, pass one as the second argument: `mesh.getBoundingBox(true, target)`.
85
+
86
+ - Pass `false` to cover each Splat's full size instead of only its center. Nearly transparent Splats, with opacity below `0.01`, are left out.
87
+ - The box describes the loaded data. It does not follow renderer settings, `opacity`, streaming fades, or SDF edits.
88
+ - For streamed models, the box follows the detail that is currently shown. With RAD it can be somewhat larger.
80
89
 
81
- For world-space bounds, update the world matrix and apply `mesh.matrixWorld` to the returned box.
90
+ For a box in world space, update the world matrix and apply `mesh.matrixWorld` to the result.
82
91
 
83
- `mesh.dispose()` also disposes its `Splats`, including caller-supplied data. To keep shared or reusable data:
92
+ ### Forcing an update
93
+
94
+ You rarely need these. They are for changes the mesh cannot detect by itself:
95
+
96
+ ```ts
97
+ mesh.updateVersion(); // Refresh the model and sort it again.
98
+ mesh.updateVersion({ sort: false }); // Refresh appearance only; keep the sort order.
99
+ mesh.updateMappingVersion(); // The Splat count changed.
100
+ ```
101
+
102
+ ### Disposing
103
+
104
+ `mesh.dispose()` also disposes its `Splats`, even data you supplied yourself. To keep the data for reuse:
84
105
 
85
106
  ```js
86
107
  await mesh.initialized;
@@ -88,7 +109,7 @@ const data = mesh.splats;
88
109
  mesh.removeFromParent();
89
110
  mesh.splats = undefined;
90
111
  mesh.dispose();
91
- // Call data?.dispose() when no users need it anymore.
112
+ // Call data?.dispose() when nothing uses it anymore.
92
113
  ```
93
114
 
94
115
  ## Raycasting
@@ -105,11 +126,10 @@ if (intersections.length > 0) {
105
126
  }
106
127
  ```
107
128
 
108
- Requires `raycastable: true`. Picking may return no hits during initial setup. Streaming models can be picked, but hits do not follow their display fades.
109
-
110
- Picking first checks cached block bounds at a fixed source-opacity threshold of `0.01`. Lowering `minRaycastOpacity` below `0.01` does not expand these bounds, so more transparent areas outside them cannot be picked.
111
-
112
- Hits include `index` for reading the current Splat and `sourceIndex` for its original source ID (`SplatIntersection` in TypeScript). Streamed indices can change with the visible selection. RAD source IDs are file-global node indices; streamed SOG source IDs are indices within the hit batch's source chunk.
129
+ - The model needs `raycastable: true`, the default. Picking may return nothing while the model is still being set up.
130
+ - Each hit has an `index`, for reading the Splat from the current data, and a `sourceIndex`, its ID in the original file (`SplatIntersection` in TypeScript).
131
+ - Values of `minRaycastOpacity` below `0.01` have limited effect: areas that transparent may not be pickable.
132
+ - Streamed models can be picked. Hits ignore their display fades, and an `index` can change as the shown detail changes. For RAD, `sourceIndex` is the node index within the whole file; for streamed SOG, it is the index within the chunk file the hit Splat was loaded from.
113
133
 
114
134
  ## Scene integration
115
135
 
@@ -123,8 +143,8 @@ const splat = new SplatMesh({
123
143
  scene.add(splat);
124
144
  ```
125
145
 
126
- If `onFrame` throws, the current update stops and the error propagates through the renderer's update/render call. Changes already made by the callback are not rolled back.
146
+ If `onFrame` throws, the error comes out of the render or `update()` call that ran it. Changes the callback already made are kept.
127
147
 
128
- For GIS/ECEF scenes, keep model coordinates local and put large offsets in the mesh transform. This helps preserve detail; precision already lost in the source file cannot be restored.
148
+ For GIS/ECEF scenes, keep the model's own coordinates small and put the large offset in the mesh transform. This preserves detail; precision already lost in the source file cannot be restored.
129
149
 
130
- For models using `+Y` down and `+Z` forward, use `splat.quaternion.set(1, 0, 0, 0)` to rotate 180° around X.
150
+ For models with `+Y` down and `+Z` forward, use `splat.quaternion.set(1, 0, 0, 0)` to turn them 180° around X.
package/docs/Splats.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- `Splats` stores decoded Splat data. Wait for initialization before reading:
5
+ `Splats` holds the data of a loaded model. Every `SplatMesh` has one as `mesh.splats`. Use it to read individual Splats, or to share one model's data between meshes.
6
+
7
+ Wait for loading to finish before reading:
6
8
 
7
9
  ```js
8
10
  await splat.initialized;
@@ -17,42 +19,47 @@ The constructor and `initialize()` accept `SplatsOptions`:
17
19
 
18
20
  | Option | Type | Default | Description |
19
21
  | --- | --- | --- | --- |
20
- | `url` | `string` | `undefined` | PLY/SPZ/SOG/RAD file or SOG metadata URL |
22
+ | `url` | `string` | `undefined` | PLY/SPZ/SOG/RAD file or SOG `meta.json` URL |
21
23
  | `file` | `Blob` (including `File`) | `undefined` | Local file |
22
- | `fileBytes` | `Uint8Array \| ArrayBuffer` | `undefined` | In-memory file data |
23
- | `fileType` | `SplatFileType` | Inferred from name | Explicit file format |
24
- | `fileName` | `string` | `File.name` when available | Name used to infer the input format |
25
- | `resolveFile` | `SplatFileResolver` | `undefined` | Resolves external SOG images or RAD pages by metadata filename; see [local split files](SplatLoader.md#local-split-files) |
26
- | `postDecode` | `SplatPostDecodeProgram` | `undefined` | Apply a [load-time transform](PostDecode.md) to each Splat |
27
- | `onProgress` | `(event: SplatProgressEvent) => void` | `undefined` | [Per-stage loading progress](SplatLoader.md#loading-progress) callback |
28
-
29
- Choose at most one of `url`, `file`, or `fileBytes`; mixing inputs throws.
24
+ | `fileBytes` | `Uint8Array \| ArrayBuffer` | `undefined` | Complete file data in memory |
25
+ | `fileType` | `SplatFileType` | Detected from the name | Set the format explicitly |
26
+ | `fileName` | `string` | `File.name` when available | Name used to detect the format |
27
+ | `resolveFile` | `SplatFileResolver` | `undefined` | Supply the extra files of a split SOG or RAD model; see [local split files](SplatLoader.md#local-split-files) |
28
+ | `postDecode` | `SplatPostDecodeProgram` | `undefined` | [Change each Splat while loading](PostDecode.md) |
29
+ | `onProgress` | `(event: SplatProgressEvent) => void` | `undefined` | [Loading progress](SplatLoader.md#loading-progress) callback |
30
30
 
31
- `initialize()` returns the new `initialized` promise and replaces earlier data. Reinitializing or disposing cancels pending file loading with `AbortError`.
31
+ Choose at most one of `url`, `file`, or `fileBytes`; combining them throws.
32
32
 
33
33
  ## Methods
34
34
 
35
35
  | API | Description |
36
36
  | --- | --- |
37
- | `initialized` / `isInitialized` | Asynchronous initialization state |
38
- | `getNumSplats()` / `getNumSh()` | Returns Splat count and available SH degree |
39
- | `getByteLength()` | Return memory used by the retained data arrays |
40
- | `getSplat(index, includeSh?)` | Read one Splat; pass `false` to skip spherical harmonics |
41
- | `getSourceIndex(index)` | Map a current data index to its original source ID |
42
- | `forEachCenter(callback)` | Iterates centers only, suitable for spatial-index construction |
37
+ | `initialized` / `isInitialized` | Promise that resolves when loading finishes, and whether it has |
38
+ | `initialize(options)` | Load new data from a URL, file, or bytes, replacing what was there. Returns the new `initialized` promise |
39
+ | `getNumSplats()` / `getNumSh()` | Splat count, and the level of view-dependent color (spherical harmonics degree) the model has |
40
+ | `getByteLength()` | Memory used by the data, in bytes |
41
+ | `getSplat(index, includeSh?)` | Read one Splat; pass `false` to skip its view-dependent color |
42
+ | `getSourceIndex(index)` | The Splat's ID in the original file |
43
+ | `forEachCenter(callback)` | Visit only the center of every Splat, for example to build a spatial index |
43
44
  | `forEachSplat(callback)` | Visit every Splat |
44
- | `initialize(options)` | Initializes or replaces data from a URL, file, or bytes |
45
- | `dispose()` | Cancel pending loading and release data resources |
45
+ | `dispose()` | Cancel loading and release the data |
46
+
47
+ Calling `initialize()` again or `dispose()` cancels a load still in progress; its promise rejects with `AbortError`.
46
48
 
47
49
  ## Data rules
48
50
 
49
- - File data is spatially reordered after `postDecode`; indices refer to the loaded order. Use `getSourceIndex(index)` or a picking hit's `sourceIndex` for the original source ID. Passing existing `Splats` to a mesh keeps their order.
50
- - `getSplat()` returns new `center`, `scales`, `quaternion`, `opacity`, `color`, and `sh` (0, 3, 8, or 15 RGB coefficients for SH0/1/2/3) values on each call. Changing them does not update the source. `forEachSplat()` reuses the same objects for every Splat; clone any you need to keep after the callback returns.
51
- - Streamed RAD/SOG data cannot be reinitialized.
52
- - Read bounds through [`mesh.getBoundingBox()`](SplatMesh.md#common-methods). They update when data is reinitialized or the streaming selection changes.
51
+ - **Indices are not file order.** Splats are reordered while loading. Use `getSourceIndex(index)`, or a picking hit's `sourceIndex`, to get the ID from the original file. Passing existing `Splats` to a mesh keeps their order.
52
+ - **Reads return copies.** `getSplat()` returns new `center`, `scales`, `quaternion`, `opacity`, `color`, and `sh` values on each call; changing them does not change the model. `sh` holds 0, 3, 8, or 15 RGB coefficients, depending on the model's degree.
53
+ - **`forEachSplat()` reuses its objects.** The same objects are passed for every Splat, so clone anything you want to keep after the callback returns.
54
+ - **Streamed data is read-only.** Data from [RadStreamScheduler](RadStreamScheduler.md) or [SogStreamScheduler](SogStreamScheduler.md) cannot be reinitialized.
55
+ - **Bounds live on the mesh.** Use [`mesh.getBoundingBox()`](SplatMesh.md#bounding-box).
56
+
57
+ To change a model, use [postDecode](PostDecode.md) while loading, or [SplatMesh properties](SplatMesh.md#properties) and [SDF edits](SplatEdit.md) for display color and opacity.
58
+
59
+ ## After reloading data
53
60
 
54
- Use [postDecode](PostDecode.md) to transform data at load time, or [SplatMesh properties](SplatMesh.md#common-properties) to adjust display color and opacity.
61
+ Data loaded with `initialize()` appears once the renderer has processed it. On WebGL this can take a few frames, and the previous data stays on screen meanwhile.
55
62
 
56
- Reinitialized data becomes visible after the renderer updates it and any required sorting completes. Sorted WebGL rendering keeps the previous display while waiting for an asynchronous sort. For [on-demand rendering](GaussianSplatRenderer.md#on-demand-rendering), request a redraw after initialization and connect `onDirty` to the same render scheduler. With `autoUpdate: false`, await `splatRenderer.update({ scene, camera })` before rendering.
63
+ With [on-demand rendering](GaussianSplatRenderer.md#on-demand-rendering), request a redraw when `initialized` resolves, and connect `onDirty` to the same render request. With `autoUpdate: false`, await `splatRenderer.update({ scene, camera })` before rendering.
57
64
 
58
- For loading progress, cancellation, and companion files, see [SplatLoader](SplatLoader.md).
65
+ For loading progress, cancellation, and split files, see [SplatLoader](SplatLoader.md).
@@ -2,11 +2,11 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- Stochastic rendering is an optional mode for `GaussianSplatRenderer`. It produces visible noise; use temporal anti-aliasing (TAA) to smooth the result. Sorted alpha blending remains the default.
5
+ Stochastic rendering is an optional way for `GaussianSplatRenderer` to draw transparency. It produces visible noise, so pair it with temporal anti-aliasing (TAA) to get a smooth image. Sorted alpha blending remains the default.
6
6
 
7
- Supported on WebGPU, WebGL2, and WebGPURenderer's WebGL2 fallback, including WebXR.
7
+ It works on WebGPU, WebGL2, and `WebGPURenderer`'s WebGL2 fallback, including WebXR.
8
8
 
9
- ## Enable stochastic rendering
9
+ ## Turn it on
10
10
 
11
11
  With an existing [GaussianSplatRenderer](GaussianSplatRenderer.md):
12
12
 
@@ -20,19 +20,15 @@ Splats are sorted from front to back by default. To skip this sorting:
20
20
  splatRenderer.stochasticSort = false;
21
21
  ```
22
22
 
23
- Both options can be changed at runtime. While stochastic rendering is active, transparent blending is disabled and depth testing and writing are enabled. Your `transparent`, `depthTest`, and `depthWrite` settings take effect again when you return to sorted rendering.
23
+ Both can be changed at any time. While stochastic rendering is active, Splats are drawn without blending and with depth testing and depth writing on. Your `transparent`, `depthTest`, and `depthWrite` settings apply again when you return to sorted rendering.
24
24
 
25
25
  ## Smooth the noise
26
26
 
27
- Use the library's [TAAPass](TAAPass.md) with **WebGLRenderer**, or the library's **TAANode** with **WebGPURenderer** (including its WebGL2 fallback). The examples below assume an existing `renderer`, `scene`, `camera`, and `splatRenderer`, with the Splat renderer already added to the scene. They use the default `autoUpdate = true` and a single non-XR camera.
28
-
29
- The noise pattern changes on each render by default so TAA can smooth it over time. The library does not enable TAA or schedule these extra renders for you. With on-demand rendering, keep rendering while TAA accumulates.
30
-
31
- WebGPURenderer blends in Three.js's linear working color space, which makes partially transparent Splats slightly brighter than WebGLRenderer drawing directly to the canvas. `TAAPass` matches direct canvas rendering by default; see [TAAPass color space](TAAPass.md#color-space).
27
+ Use [`TAANode`](TAAPass.md#taanode-webgpurenderer) with `WebGPURenderer`, or [`TAAPass`](TAAPass.md#taapass-webglrenderer) with `WebGLRenderer`. The library does not turn TAA on for you. The examples assume an existing `renderer`, `scene`, `camera`, and `splatRenderer`, with one camera outside WebXR.
32
28
 
33
29
  ### WebGPURenderer: TAANode
34
30
 
35
- Use this setup for both native WebGPU and WebGPURenderer's WebGL2 fallback, after `await renderer.init()`:
31
+ Use this on both WebGPU and the WebGL2 fallback, after `await renderer.init()`:
36
32
 
37
33
  ```js
38
34
  import { TAANode } from "gaussian-splat-lite";
@@ -41,8 +37,7 @@ import { RenderPipeline } from "three/webgpu";
41
37
  splatRenderer.stochastic = true;
42
38
 
43
39
  const taa = new TAANode(scene, camera);
44
- // Chain Bloom or other linear effects from taa here.
45
- // RenderPipeline applies the final tone mapping and output conversion.
40
+ // Chain Bloom or other effects from taa here.
46
41
  const pipeline = new RenderPipeline(renderer, taa);
47
42
 
48
43
  renderer.setAnimationLoop(() => {
@@ -51,44 +46,46 @@ renderer.setAnimationLoop(() => {
51
46
  });
52
47
  ```
53
48
 
54
- Call `taa.reset()` after a camera cut, scene replacement, or an abrupt object change. See [TAANode](TAAPass.md#webgpurenderer-tsl-version) for behavior, supported cameras, and cleanup.
55
-
56
49
  ### WebGLRenderer: TAAPass
57
50
 
58
51
  ```js
59
52
  import { TAAPass } from "gaussian-splat-lite";
53
+ import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
54
+ import { OutputPass } from "three/addons/postprocessing/OutputPass.js";
60
55
 
61
56
  splatRenderer.stochastic = true;
62
57
 
63
58
  const taa = new TAAPass(scene, camera);
59
+ const composer = new EffectComposer(renderer);
60
+ composer.addPass(taa);
61
+ // Insert Bloom or other effects here.
62
+ composer.addPass(new OutputPass());
63
+
64
64
  renderer.setAnimationLoop(() => {
65
65
  // Update controls / animation here.
66
- taa.render(renderer);
66
+ composer.render();
67
67
  });
68
68
  ```
69
69
 
70
- `TAAPass` renders the scene itself, so no `RenderPass` or `OutputPass` is needed. It tracks camera movement but not object motion; call `taa.reset()` after a camera cut or scene replacement. See [TAAPass](TAAPass.md) for linear effects, depth effects, and offscreen rendering.
70
+ `TAAPass` takes the place of `RenderPass`. On resize, call `composer.setSize(width, height)` along with the renderer.
71
71
 
72
- For on-demand rendering with either setup, keep rendering for several frames after camera, model, or streamed-content changes, including the Splat renderer's `onDirty` callback; the viewer uses 32. The repository's `examples/viewer/viewerTAA.js` shows both setups.
72
+ ### With either setup
73
+
74
+ - Call `taa.reset()` after a camera cut, a scene replacement, or an abrupt change to an object. TAA follows camera movement, not moving objects.
75
+ - With on-demand rendering, keep rendering for several frames after the camera, a model, or streamed content changes, and after the Splat renderer's `onDirty` callback, so the noise can settle. The viewer renders 32.
76
+
77
+ See [TAAPass and TAANode](TAAPass.md) for effects, depth, color, and cleanup. The repository's `examples/viewer/viewerTAA.js` shows both setups.
73
78
 
74
79
  ## Control the noise pattern
75
80
 
76
- To keep the noise fixed, or control samples in your own TAA integration:
81
+ The noise pattern changes on every render, which is what lets TAA smooth it over time. To keep it fixed, or to drive it from your own TAA:
77
82
 
78
83
  ```js
79
84
  splatRenderer.autoAdvanceStochasticSample = false;
80
- splatRenderer.stochasticSample = 0; // Keep fixed, or increment it yourself.
85
+ splatRenderer.stochasticSample = 0; // Keep fixed, or increase it yourself.
81
86
  ```
82
87
 
83
- Set `autoAdvanceStochasticSample = true` to restore automatic updates.
84
-
85
- Coverage uses a 32-frame spatiotemporal blue-noise sequence on all backends.
86
- Each Splat keeps its own spatial offset and temporal phase, so consecutive
87
- samples follow the texture's time axis instead of choosing unrelated offsets.
88
- The temporal sequence is optimized for exponential history accumulation.
89
- The sequence wraps after 32 samples; this reduces temporal sampling error but
90
- does not guarantee a noise-free result after 32 renders. Keep advancing the
91
- sample once per scene render, including when using camera jitter.
88
+ When you advance it yourself, increase it by one for each render of the scene. The patterns repeat every 32 samples; a smooth image is not guaranteed after exactly 32 renders. Set `autoAdvanceStochasticSample = true` to hand control back.
92
89
 
93
90
  ## Return to sorted rendering
94
91
 
@@ -96,11 +93,11 @@ sample once per scene render, including when using camera jitter.
96
93
  splatRenderer.stochastic = false;
97
94
  ```
98
95
 
99
- Switching in either direction takes effect at the next update boundary, after the current draw. WebGL backends also wait for the matching accumulator and sort. `stochasticActive` reports whether stochastic rendering is in use. Keep TAA running until it turns `false`. With `autoUpdate = false`, update before drawing:
96
+ The switch, in either direction, takes effect on a later frame rather than immediately. `stochasticActive` tells you which mode is being drawn; keep TAA running until it is `false`. With `autoUpdate = false`, update before drawing:
100
97
 
101
98
  ```js
102
99
  await splatRenderer.update({ scene, camera });
103
100
  renderer.render(scene, camera);
104
101
  ```
105
102
 
106
- If you keep TAA running with sorted rendering, set `splatRenderer.depthWrite = true` so TAA can see Splat depth.
103
+ If you keep TAA running with sorted rendering, set `splatRenderer.depthWrite = true` so TAA can see the Splats' depth.