gaussian-splat-lite 1.3.2 → 1.4.1

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 (53) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/CONTRIBUTING.md +14 -2
  3. package/NOTICE +11 -3
  4. package/README.md +5 -7
  5. package/THIRD_PARTY_LICENSES.md +64 -6
  6. package/bin/build-lod.js +241 -0
  7. package/bin/decoder/decoder.js +340 -0
  8. package/bin/decoder/decoder_bg.wasm +0 -0
  9. package/bin/rad/grid.js +620 -0
  10. package/bin/rad/heap.js +270 -0
  11. package/bin/rad/input.js +87 -0
  12. package/bin/rad/lod.js +657 -0
  13. package/bin/rad/math.js +166 -0
  14. package/bin/rad/parallel.js +578 -0
  15. package/bin/rad/progress.js +50 -0
  16. package/bin/rad/rad.js +612 -0
  17. package/bin/rad/splats.js +432 -0
  18. package/bin/rad/storage.js +776 -0
  19. package/dist/gaussian-splat-lite.cjs +392 -794
  20. package/dist/gaussian-splat-lite.cjs.map +1 -1
  21. package/dist/gaussian-splat-lite.min.cjs +246 -308
  22. package/dist/gaussian-splat-lite.min.cjs.map +1 -1
  23. package/dist/gaussian-splat-lite.module.js +394 -796
  24. package/dist/gaussian-splat-lite.module.js.map +1 -1
  25. package/dist/gaussian-splat-lite.module.min.js +2518 -2802
  26. package/dist/gaussian-splat-lite.module.min.js.map +1 -1
  27. package/dist/types/addons/NeuralDenoiseNode.d.cts +1 -2
  28. package/dist/types/addons/NeuralDenoiseNode.d.ts +1 -2
  29. package/dist/types/addons/NeuralDenoiseXR.d.cts +31 -0
  30. package/dist/types/addons/NeuralDenoiseXR.d.ts +31 -0
  31. package/dist/types/addons/neuralDenoiseState.d.cts +22 -0
  32. package/dist/types/addons/neuralDenoiseState.d.ts +22 -0
  33. package/dist/types/addons/neuralDenoiseWeights.d.cts +41 -2
  34. package/dist/types/addons/neuralDenoiseWeights.d.ts +41 -2
  35. package/dist/types/data/RadPagedSplats.d.cts +1 -1
  36. package/dist/types/data/RadPagedSplats.d.ts +1 -1
  37. package/dist/types/index.d.cts +1 -2
  38. package/dist/types/index.d.ts +1 -2
  39. package/dist/types/loaders/rad/radFormat.d.cts +2 -2
  40. package/dist/types/loaders/rad/radFormat.d.ts +2 -2
  41. package/docs/BuildRad.md +91 -0
  42. package/docs/GaussianSplatRenderer.md +2 -2
  43. package/docs/NeuralDenoiseNode.md +32 -13
  44. package/docs/RadStreamScheduler.md +3 -1
  45. package/docs/StochasticRendering.md +20 -42
  46. package/package.json +9 -3
  47. package/dist/types/addons/TAANode.d.cts +0 -49
  48. package/dist/types/addons/TAANode.d.ts +0 -49
  49. package/dist/types/addons/TAAPass.d.cts +0 -57
  50. package/dist/types/addons/TAAPass.d.ts +0 -57
  51. package/dist/types/addons/taaShared.d.cts +0 -74
  52. package/dist/types/addons/taaShared.d.ts +0 -74
  53. package/docs/TAAPass.md +0 -184
@@ -9,8 +9,7 @@ import { Node, type NodeBuilder, type NodeFrame } from "three/webgpu";
9
9
  export type NeuralDenoiseMode = "performance" | "quality";
10
10
  /**
11
11
  * Experimental temporal neural denoiser for stochastic Splat rendering on WebGPURenderer,
12
- * including its WebGL2 fallback,
13
- * used in place of TAANode. After Hu et al., "Ultra-fast Neural Inference for
12
+ * including its WebGL2 fallback. After Hu et al., "Ultra-fast Neural Inference for
14
13
  * Stochastic Gaussian Splatting Denoising" (arXiv 2609.25604), adapted to
15
14
  * scenes whose objects move.
16
15
  */
@@ -9,8 +9,7 @@ import { Node, type NodeBuilder, type NodeFrame } from "three/webgpu";
9
9
  export type NeuralDenoiseMode = "performance" | "quality";
10
10
  /**
11
11
  * Experimental temporal neural denoiser for stochastic Splat rendering on WebGPURenderer,
12
- * including its WebGL2 fallback,
13
- * used in place of TAANode. After Hu et al., "Ultra-fast Neural Inference for
12
+ * including its WebGL2 fallback. After Hu et al., "Ultra-fast Neural Inference for
14
13
  * Stochastic Gaussian Splatting Denoising" (arXiv 2609.25604), adapted to
15
14
  * scenes whose objects move.
16
15
  */
@@ -0,0 +1,31 @@
1
+ import type { PerspectiveCamera, Scene, WebGLRenderer } from "three";
2
+ import type { WebGPURenderer } from "three/webgpu";
3
+ import type { NeuralDenoiseMode } from "./NeuralDenoiseNode.cjs";
4
+
5
+ /** Per-eye neural denoising and presentation during an active WebXR session. */
6
+ export declare class NeuralDenoiseXR {
7
+ readonly renderer: WebGLRenderer | WebGPURenderer;
8
+ scene: Scene;
9
+ camera: PerspectiveCamera;
10
+ readonly mode: NeuralDenoiseMode;
11
+ readonly msaa: boolean;
12
+ stabilize: boolean;
13
+ private views;
14
+ private output;
15
+ private readonly nodeRenderer;
16
+ private readonly onSessionEnd;
17
+ constructor(
18
+ renderer: WebGLRenderer | WebGPURenderer,
19
+ scene: Scene,
20
+ camera: PerspectiveCamera,
21
+ mode?: NeuralDenoiseMode,
22
+ msaa?: boolean,
23
+ );
24
+ private createViews;
25
+ /** Capture, denoise and present each eye during an active XR animation frame. */
26
+ render(): void;
27
+ /** Discards both eyes' history after a camera cut or scene replacement. */
28
+ reset(): void;
29
+ private disposeViews;
30
+ dispose(): void;
31
+ }
@@ -0,0 +1,31 @@
1
+ import type { PerspectiveCamera, Scene, WebGLRenderer } from "three";
2
+ import type { WebGPURenderer } from "three/webgpu";
3
+ import type { NeuralDenoiseMode } from "./NeuralDenoiseNode.js";
4
+
5
+ /** Per-eye neural denoising and presentation during an active WebXR session. */
6
+ export declare class NeuralDenoiseXR {
7
+ readonly renderer: WebGLRenderer | WebGPURenderer;
8
+ scene: Scene;
9
+ camera: PerspectiveCamera;
10
+ readonly mode: NeuralDenoiseMode;
11
+ readonly msaa: boolean;
12
+ stabilize: boolean;
13
+ private views;
14
+ private output;
15
+ private readonly nodeRenderer;
16
+ private readonly onSessionEnd;
17
+ constructor(
18
+ renderer: WebGLRenderer | WebGPURenderer,
19
+ scene: Scene,
20
+ camera: PerspectiveCamera,
21
+ mode?: NeuralDenoiseMode,
22
+ msaa?: boolean,
23
+ );
24
+ private createViews;
25
+ /** Capture, denoise and present each eye during an active XR animation frame. */
26
+ render(): void;
27
+ /** Discards both eyes' history after a camera cut or scene replacement. */
28
+ reset(): void;
29
+ private disposeViews;
30
+ dispose(): void;
31
+ }
@@ -0,0 +1,22 @@
1
+ import type { Camera, Matrix4, RenderTarget, Vector2 } from "three";
2
+
3
+ /** Capture sizing, projection jitter and history lifetime for neural denoising. */
4
+ export declare function createNeuralDenoiseState(
5
+ targets: RenderTarget[],
6
+ margin: number,
7
+ ): {
8
+ size: Vector2;
9
+ projection: Matrix4;
10
+ valid: boolean;
11
+ historyIndex: number;
12
+ jitterIndex: number;
13
+ reset(): void;
14
+ setSize(width: number, height: number): void;
15
+ setStencil(stencil: boolean): void;
16
+ beginCapture(camera: Camera): void;
17
+ endCapture(camera: Camera): void;
18
+ advance(): void;
19
+ };
20
+ export declare const getUnjitteredProjection: (
21
+ camera: Camera,
22
+ ) => Matrix4 | undefined;
@@ -0,0 +1,22 @@
1
+ import type { Camera, Matrix4, RenderTarget, Vector2 } from "three";
2
+
3
+ /** Capture sizing, projection jitter and history lifetime for neural denoising. */
4
+ export declare function createNeuralDenoiseState(
5
+ targets: RenderTarget[],
6
+ margin: number,
7
+ ): {
8
+ size: Vector2;
9
+ projection: Matrix4;
10
+ valid: boolean;
11
+ historyIndex: number;
12
+ jitterIndex: number;
13
+ reset(): void;
14
+ setSize(width: number, height: number): void;
15
+ setStencil(stencil: boolean): void;
16
+ beginCapture(camera: Camera): void;
17
+ endCapture(camera: Camera): void;
18
+ advance(): void;
19
+ };
20
+ export declare const getUnjitteredProjection: (
21
+ camera: Camera,
22
+ ) => Matrix4 | undefined;
@@ -9,8 +9,36 @@ export type NeuralDenoiseLayer = {
9
9
  * Trained on this renderer's stochastic frames.
10
10
  */
11
11
  export type NeuralDenoiseModel = {
12
- /** Use fixed local filtering without learned multiscale passes. */
12
+ /**
13
+ * Use fixed local filtering without learned multiscale passes.
14
+ * Requires `compactMix` and `movingKnee` when true.
15
+ */
13
16
  compact?: boolean;
17
+ /**
18
+ * Required with `compact`: shares of the 3x3 mean, each in [0, 1], for
19
+ * settled denoised history and for camera motion or short history.
20
+ * The transition uses `movingKnee` and `reach`.
21
+ */
22
+ compactMix?: [settled: number, movingOrShort: number];
23
+ /**
24
+ * Maximum share of smoothing applied to the displayed accumulated path,
25
+ * in [0, 1]. Omitted or zero disables it; otherwise `movingNoise` and
26
+ * `movingKnee` are required. Applies only while the camera moves and
27
+ * preserves the stored accumulated history. Object motion with a still
28
+ * camera continues to use the existing history rejection.
29
+ */
30
+ movingMean?: number;
31
+ /**
32
+ * Required with nonzero `movingMean`: nonnegative multiplier of the
33
+ * mean's squared standard error. Larger values allow smoothing across
34
+ * greater color differences.
35
+ */
36
+ movingNoise?: number;
37
+ /**
38
+ * Required with `compact` or nonzero `movingMean`: positive camera-induced
39
+ * screen motion, in pixels per frame, at which the motion response is 0.5.
40
+ */
41
+ movingKnee?: number;
14
42
  /** Strengthen display stabilization for single-sample stochastic noise. */
15
43
  stabilizeNoise?: boolean;
16
44
  /** Gain of the variance gate between the two history paths. */
@@ -111,7 +139,18 @@ export type NeuralDenoiseModel = {
111
139
  pointwise3: NeuralDenoiseLayer;
112
140
  head: NeuralDenoiseLayer;
113
141
  };
114
- };
142
+ } & (
143
+ | { compact?: false }
144
+ | {
145
+ compact: true;
146
+ compactMix: [settled: number, movingOrShort: number];
147
+ movingKnee: number;
148
+ }
149
+ ) &
150
+ (
151
+ | { movingMean?: 0 }
152
+ | { movingMean: number; movingNoise: number; movingKnee: number }
153
+ );
115
154
  export declare const neuralDenoiseModels: {
116
155
  quality: NeuralDenoiseModel;
117
156
  performance: NeuralDenoiseModel;
@@ -9,8 +9,36 @@ export type NeuralDenoiseLayer = {
9
9
  * Trained on this renderer's stochastic frames.
10
10
  */
11
11
  export type NeuralDenoiseModel = {
12
- /** Use fixed local filtering without learned multiscale passes. */
12
+ /**
13
+ * Use fixed local filtering without learned multiscale passes.
14
+ * Requires `compactMix` and `movingKnee` when true.
15
+ */
13
16
  compact?: boolean;
17
+ /**
18
+ * Required with `compact`: shares of the 3x3 mean, each in [0, 1], for
19
+ * settled denoised history and for camera motion or short history.
20
+ * The transition uses `movingKnee` and `reach`.
21
+ */
22
+ compactMix?: [settled: number, movingOrShort: number];
23
+ /**
24
+ * Maximum share of smoothing applied to the displayed accumulated path,
25
+ * in [0, 1]. Omitted or zero disables it; otherwise `movingNoise` and
26
+ * `movingKnee` are required. Applies only while the camera moves and
27
+ * preserves the stored accumulated history. Object motion with a still
28
+ * camera continues to use the existing history rejection.
29
+ */
30
+ movingMean?: number;
31
+ /**
32
+ * Required with nonzero `movingMean`: nonnegative multiplier of the
33
+ * mean's squared standard error. Larger values allow smoothing across
34
+ * greater color differences.
35
+ */
36
+ movingNoise?: number;
37
+ /**
38
+ * Required with `compact` or nonzero `movingMean`: positive camera-induced
39
+ * screen motion, in pixels per frame, at which the motion response is 0.5.
40
+ */
41
+ movingKnee?: number;
14
42
  /** Strengthen display stabilization for single-sample stochastic noise. */
15
43
  stabilizeNoise?: boolean;
16
44
  /** Gain of the variance gate between the two history paths. */
@@ -111,7 +139,18 @@ export type NeuralDenoiseModel = {
111
139
  pointwise3: NeuralDenoiseLayer;
112
140
  head: NeuralDenoiseLayer;
113
141
  };
114
- };
142
+ } & (
143
+ | { compact?: false }
144
+ | {
145
+ compact: true;
146
+ compactMix: [settled: number, movingOrShort: number];
147
+ movingKnee: number;
148
+ }
149
+ ) &
150
+ (
151
+ | { movingMean?: 0 }
152
+ | { movingMean: number; movingNoise: number; movingKnee: number }
153
+ );
115
154
  export declare const neuralDenoiseModels: {
116
155
  quality: NeuralDenoiseModel;
117
156
  performance: NeuralDenoiseModel;
@@ -1,7 +1,7 @@
1
1
  import { IndexedSplats } from "./IndexedSplats.cjs";
2
2
  import type { ReorderedSplatResult } from "./defines.cjs";
3
3
  export type RadPagedSplatsOptions = {
4
- /** Maximum records in one decoded chunk. Defaults to Spark's 65,536. */
4
+ /** Maximum records in one decoded chunk. Defaults to 65,536. */
5
5
  pageSize?: number;
6
6
  pageCount: number;
7
7
  numSh: number;
@@ -1,7 +1,7 @@
1
1
  import { IndexedSplats } from "./IndexedSplats.js";
2
2
  import type { ReorderedSplatResult } from "./defines.js";
3
3
  export type RadPagedSplatsOptions = {
4
- /** Maximum records in one decoded chunk. Defaults to Spark's 65,536. */
4
+ /** Maximum records in one decoded chunk. Defaults to 65,536. */
5
5
  pageSize?: number;
6
6
  pageCount: number;
7
7
  numSh: number;
@@ -2,11 +2,10 @@ export {
2
2
  GaussianSplatRenderer,
3
3
  type GaussianSplatRendererOptions,
4
4
  } from "./rendering/GaussianSplatRenderer.cjs";
5
- export { TAAPass } from "./addons/TAAPass.cjs";
6
- export { TAANode } from "./addons/TAANode.cjs";
7
5
  export type { NeuralDenoiseMode } from "./addons/NeuralDenoiseNode.cjs";
8
6
  export { NeuralDenoiseNode } from "./addons/NeuralDenoiseNode.cjs";
9
7
  export { NeuralDenoisePass } from "./addons/NeuralDenoisePass.cjs";
8
+ export { NeuralDenoiseXR } from "./addons/NeuralDenoiseXR.cjs";
10
9
  export {
11
10
  SplatCapture,
12
11
  type SplatCaptureOptions,
@@ -2,11 +2,10 @@ export {
2
2
  GaussianSplatRenderer,
3
3
  type GaussianSplatRendererOptions,
4
4
  } from "./rendering/GaussianSplatRenderer.js";
5
- export { TAAPass } from "./addons/TAAPass.js";
6
- export { TAANode } from "./addons/TAANode.js";
7
5
  export type { NeuralDenoiseMode } from "./addons/NeuralDenoiseNode.js";
8
6
  export { NeuralDenoiseNode } from "./addons/NeuralDenoiseNode.js";
9
7
  export { NeuralDenoisePass } from "./addons/NeuralDenoisePass.js";
8
+ export { NeuralDenoiseXR } from "./addons/NeuralDenoiseXR.js";
10
9
  export {
11
10
  SplatCapture,
12
11
  type SplatCaptureOptions,
@@ -7,7 +7,7 @@ export type RadChunkRange = {
7
7
  count?: number;
8
8
  filename?: string;
9
9
  };
10
- /** Spark RAD version 1 directory. Child references use file-global indices. */
10
+ /** RAD version 1 directory. Child references use file-global indices. */
11
11
  export type RadMeta = {
12
12
  version: number;
13
13
  type: "gsplat";
@@ -43,7 +43,7 @@ export type RadDecodedChunk = PostDecodeSplatData & {
43
43
  lodRadii?: Float32Array;
44
44
  };
45
45
  export declare function unpackRadChunk(decoded: RadDecodedChunk): RadChunkData;
46
- /** Without chunkSize, Spark treats the dataset as one chunk. */
46
+ /** Without chunkSize, the dataset is treated as one chunk. */
47
47
  export declare function getRadChunkSpan(
48
48
  meta: RadMeta,
49
49
  index: number,
@@ -7,7 +7,7 @@ export type RadChunkRange = {
7
7
  count?: number;
8
8
  filename?: string;
9
9
  };
10
- /** Spark RAD version 1 directory. Child references use file-global indices. */
10
+ /** RAD version 1 directory. Child references use file-global indices. */
11
11
  export type RadMeta = {
12
12
  version: number;
13
13
  type: "gsplat";
@@ -43,7 +43,7 @@ export type RadDecodedChunk = PostDecodeSplatData & {
43
43
  lodRadii?: Float32Array;
44
44
  };
45
45
  export declare function unpackRadChunk(decoded: RadDecodedChunk): RadChunkData;
46
- /** Without chunkSize, Spark treats the dataset as one chunk. */
46
+ /** Without chunkSize, the dataset is treated as one chunk. */
47
47
  export declare function getRadChunkSpan(
48
48
  meta: RadMeta,
49
49
  index: number,
@@ -0,0 +1,91 @@
1
+ # Building RAD files
2
+
3
+ [Back to documentation](../README.md#documentation)
4
+
5
+ Convert PLY or SPZ models into RAD files with levels of detail (LOD), ready for [RAD streaming](RadStreamScheduler.md). Requires Node.js 20.19+ on the 20.x branch, or 22.12+. No compilation is required.
6
+
7
+ ```sh
8
+ npm install --global gaussian-splat-lite
9
+ gsl-build-lod scene.ply
10
+ ```
11
+
12
+ This writes `scene-lod.rad` beside the input. Large models can take a long time to convert.
13
+
14
+ To run without a global installation:
15
+
16
+ ```sh
17
+ npx --package gaussian-splat-lite gsl-build-lod scene.ply
18
+ ```
19
+
20
+ From a repository checkout, first build the decoder with `npm run build:wasm:lod` (requires Rust), then use `npm run build-lod -- <input>` with the same options. The full `npm run build:wasm` command also builds the decoder.
21
+
22
+ ## Inputs and output
23
+
24
+ Inputs must be `.ply` or `.spz` files. Splats with NaN or infinite values, or a zero rotation, are skipped, and the conversion reports how many.
25
+
26
+ ```sh
27
+ # Convert several files, each to its own RAD file.
28
+ gsl-build-lod room.ply garden.spz
29
+
30
+ # Choose an output path for a single input.
31
+ gsl-build-lod scene.ply -o output/scene.rad
32
+
33
+ # Keep only the base color, reducing file size and memory use.
34
+ gsl-build-lod scene.ply --max-sh 0
35
+ ```
36
+
37
+ The output directory must exist. Existing output files, including matching `.radc` files when using `--rad-chunked`, are never overwritten. Choose a different output name or remove the old files before converting again. Output files are first written under hidden temporary names in the output directory and receive their final names only after all of them are complete. Failed conversions return a nonzero exit code and remove their output files; if a file cannot be removed, a warning shows its path.
38
+
39
+ The output keeps up to SH3. SH4 inputs are accepted and converted to SH3 or the level chosen with `--max-sh`. Higher SH levels retain more view-dependent color and increase file size. Conversion is lossy, so colors and shape can differ slightly from the source.
40
+
41
+ ## LOD spacing
42
+
43
+ ```sh
44
+ gsl-build-lod scene.ply --lod-base 1.75
45
+ ```
46
+
47
+ `--lod-base` controls the spacing between detail levels (default `1.75`, range `1.1`–`16`). Smaller values produce more intermediate levels and usually larger files; larger values produce fewer levels and usually smaller files. This setting does not discard input splats.
48
+
49
+ ## Memory and temporary storage
50
+
51
+ ```sh
52
+ gsl-build-lod scene.ply --memory-budget 16 --temp-dir /fast-disk/rad-temp
53
+ ```
54
+
55
+ `--memory-budget` sets a target in GiB (default `4`, minimum `1`, fractional values accepted). Values such as `16` are supported when enough RAM is available. Lower targets may make conversion slower and require more temporary disk space; output quality is unchanged. If conversion reports insufficient memory, increase this value.
56
+
57
+ The target covers the whole conversion, worker threads included: the converter measures its memory as it runs and keeps within it. Leave room for the operating system and other applications.
58
+
59
+ `--temp-dir` chooses where temporary working files are stored; the default is the system temporary directory. Use a fast disk with enough free space, as temporary files can be much larger than the input. Each conversion keeps them in its own `gsl-build-rad-*` folder there, which is removed when the conversion finishes or fails; if it cannot be removed, a warning shows its path.
60
+
61
+ ## Split files
62
+
63
+ ```sh
64
+ gsl-build-lod scene.ply --rad-chunked
65
+ ```
66
+
67
+ This writes `scene-lod.rad` plus `scene-lod-0.radc`, `scene-lod-1.radc`, and so on.
68
+
69
+ Host all files together in the same directory and load the `.rad` file. A single `.rad` file also supports streaming; its server must support HTTP Range requests.
70
+
71
+ ```js
72
+ import { RadStreamScheduler } from "gaussian-splat-lite";
73
+
74
+ const streaming = new RadStreamScheduler({
75
+ url: "/models/scene-lod.rad",
76
+ });
77
+ ```
78
+
79
+ See [RadStreamScheduler](RadStreamScheduler.md) for the complete loading and display example.
80
+
81
+ ## Options
82
+
83
+ | Option | Default | Description |
84
+ | --- | --- | --- |
85
+ | `--lod-base <base>` | `1.75` | LOD spacing, from `1.1` to `16`; smaller values retain more detail levels. |
86
+ | `--max-sh <0..3>` | `3` | Highest SH degree to keep, limited by the input. |
87
+ | `--memory-budget <GiB>` | `4` | Target memory use in GiB, at least `1`; for example `16`. |
88
+ | `--temp-dir <path>` | System temp directory | Location for temporary files; created if needed. |
89
+ | `--rad-chunked` | Disabled | Write a header and separate `.radc` files. |
90
+ | `-o <path>` or `--output <path>` | `<input-stem>-lod.rad` | Output path; requires exactly one input. |
91
+ | `-h` or `--help` | — | Show command help. |
@@ -58,7 +58,7 @@ On native WebGPU, Splats are sorted before every draw. On WebGL, sorting finishe
58
58
 
59
59
  | Option | Type | Default | Description |
60
60
  | --- | --- | --- | --- |
61
- | `stochastic` | `boolean` | `false` | Use stochastic rendering; smooth its noise with temporal anti-aliasing |
61
+ | `stochastic` | `boolean` | `false` | Use stochastic rendering; smooth its noise with neural denoising |
62
62
  | `stochasticSort` | `boolean` | `true` | Sort Splats from front to back in stochastic rendering; `false` skips sorting |
63
63
  | `autoAdvanceStochasticSample` | `boolean` | `true` | Change the noise pattern on every render, including in WebXR |
64
64
 
@@ -100,7 +100,7 @@ Model colors are converted for you. Control the final image with your Three.js r
100
100
 
101
101
  Set `encodeLinear` to choose the conversion yourself. For example, to blend Splats in sRGB next to a linear scene, render them into their own target with `encodeLinear: false`, then unpremultiply that layer, convert it to linear, and premultiply it again before compositing.
102
102
 
103
- For temporal anti-aliasing and effects such as Bloom, see [TAAPass and TAANode](TAAPass.md). To render offscreen, read pixels back, or build cube and environment maps, use [SplatCapture](SplatCapture.md).
103
+ For neural denoising and effects such as Bloom, see [Neural denoising](NeuralDenoiseNode.md). To render offscreen, read pixels back, or build cube and environment maps, use [SplatCapture](SplatCapture.md).
104
104
 
105
105
  ## On-demand rendering
106
106
 
@@ -1,18 +1,10 @@
1
- # NeuralDenoiseNode and NeuralDenoisePass (Experimental)
1
+ # Neural denoising (Experimental)
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- The experimental neural denoiser smooths [stochastic rendering](StochasticRendering.md). Use `NeuralDenoiseNode` with `WebGPURenderer`, including its WebGL2 fallback, or `NeuralDenoisePass` with `WebGLRenderer`. The trained models are included; no extra downloads are needed.
5
+ The experimental neural denoiser smooths [stochastic rendering](StochasticRendering.md). Use `NeuralDenoiseNode` with `WebGPURenderer`, including its WebGL2 fallback, or `NeuralDenoisePass` with `WebGLRenderer`. For immersive rendering, use [NeuralDenoiseXR](#webxr) with either renderer. The trained models are included; no extra downloads are needed.
6
6
 
7
- ## Choose between TAA and neural denoising
8
-
9
- | | `TAANode` / `TAAPass` | `NeuralDenoiseNode` / `NeuralDenoisePass` |
10
- | --- | --- | --- |
11
- | Moving objects | May leave a faint trail | Helps reduce trails; moving detail can still look soft or grainy |
12
- | Camera movement | Some grain returns | Smooths noise during movement; fast turns can look softer |
13
- | Cost | Lower | Depends on mode; Quality uses more GPU time and memory |
14
-
15
- With neural denoising, newly exposed backgrounds need time to settle. Results vary by scene and motion.
7
+ Neural denoising smooths noise during movement and helps reduce trails behind moving objects. Moving detail can still look soft or grainy, and newly exposed backgrounds need time to settle. Results vary by scene and motion.
16
8
 
17
9
  ## Choose a mode
18
10
 
@@ -48,7 +40,7 @@ With MSAA off, stabilization is stronger to reduce flicker, which can add some t
48
40
  ## Before you start
49
41
 
50
42
  - **WebGL2 requirements.** Both WebGL2 paths require `EXT_color_buffer_float`. MSAA also requires `OES_sample_variables`; check `renderer.getContext().getExtension("OES_sample_variables")` before enabling MSAA. If it is unavailable, leave MSAA disabled. Unsupported configurations throw an error.
51
- - **One camera.** Use a `PerspectiveCamera` or `OrthographicCamera`. WebXR is not supported.
43
+ - **Camera.** Use a `PerspectiveCamera` or `OrthographicCamera` for the node/pass. For WebXR, use `NeuralDenoiseXR` with your application's `PerspectiveCamera` as shown below.
52
44
  - **Stencil masks.** Create the Three.js renderer with `stencil: true` to use them.
53
45
  - **Reset after a jump.** Call `denoise.reset()` after a camera cut or scene replacement. Resizing resets automatically; normal object movement needs no reset.
54
46
  - **On-demand rendering.** Keep rendering after each change so the image can settle.
@@ -88,7 +80,7 @@ const pipeline = new RenderPipeline(renderer, color.add(bloom(color, 0.6, 0.4, 0
88
80
 
89
81
  ## WebGLRenderer: NeuralDenoisePass
90
82
 
91
- Use the pass in place of `RenderPass` or `TAAPass`:
83
+ Use the pass in place of `RenderPass`:
92
84
 
93
85
  ```js
94
86
  import { NeuralDenoisePass } from "gaussian-splat-lite";
@@ -114,6 +106,33 @@ renderer.setAnimationLoop(() => {
114
106
  // On cleanup: stop the animation loop, then dispose the composer and each pass.
115
107
  ```
116
108
 
109
+ ## WebXR
110
+
111
+ Use `NeuralDenoiseXR` during XR frames. It supports `WebGLRenderer` and initialized `WebGPURenderer`, including its WebGL2 fallback. Each eye uses its own image history and resolution; both modes and optional MSAA are available.
112
+
113
+ ```js
114
+ import { NeuralDenoiseXR } from "gaussian-splat-lite";
115
+
116
+ renderer.xr.enabled = true;
117
+ splatRenderer.stochastic = true;
118
+ const xrDenoise = new NeuralDenoiseXR(renderer, scene, camera, "performance");
119
+
120
+ renderer.setAnimationLoop(() => {
121
+ // Update animation here. Start the XR session using your normal XR button.
122
+ if (renderer.xr.isPresenting) xrDenoise.render();
123
+ else renderer.render(scene, camera); // Or your desktop denoising pipeline.
124
+ });
125
+
126
+ // After a teleport or scene replacement: xrDenoise.reset().
127
+ // On cleanup: xrDenoise.dispose().
128
+ ```
129
+
130
+ Call `render()` directly during an active XR animation frame. It presents the final image, including tone mapping and output color conversion; do not put it in an `EffectComposer` or `RenderPipeline`. Those desktop pipelines do not automatically become stereo pipelines. When using a desktop denoiser too, reset its history when leaving XR.
131
+
132
+ The constructor takes `(renderer, scene, camera, mode = "quality", msaa = false)`. `scene`, `camera`, and `stabilize` can be changed; call `reset()` after replacing the scene or camera. If `renderer.xr.cameraAutoUpdate` is `false`, update the XR camera yourself before rendering. Eye resizing resets history automatically, and ending the session releases the eye resources.
133
+
134
+ Stereo rendering increases GPU and memory use. Start with `"performance"` and MSAA off, and check image quality and frame timing on the target headset. Native WebGPU also requires the browser's [WebXR WebGPU binding](https://immersive-web.github.io/webxr-webgpu-binding/) and a session requested with the `"webgpu"` feature. The XR path presents color only; it does not provide scene depth to the XR compositor or a stereo postprocessing chain.
135
+
117
136
  ## Color
118
137
 
119
138
  `RenderPipeline`, or the composer's `OutputPass`, applies tone mapping and the output color space at the end.
@@ -2,7 +2,9 @@
2
2
 
3
3
  [Back to documentation](../README.md#documentation)
4
4
 
5
- Shows large RAD scenes by loading only the detail the camera needs, and updating it as the camera moves. It supports RAD version 1 files with levels of detail (LOD), either as a single `.rad` file or split into a header and `.radc` pages. It works on WebGPU and WebGL2, and needs no Spark runtime.
5
+ Shows large RAD scenes by loading only the detail the camera needs, and updating it as the camera moves. It supports RAD version 1 files with levels of detail (LOD), either as a single `.rad` file or split into a header and `.radc` pages. It works on WebGPU and WebGL2.
6
+
7
+ To convert your own models, see [Building RAD files](BuildRad.md).
6
8
 
7
9
  ```js
8
10
  import { RadStreamScheduler } from "gaussian-splat-lite";