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.
- package/CHANGELOG.md +44 -2
- package/README.md +22 -13
- package/dist/gaussian-splat-lite.cjs +819 -88
- package/dist/gaussian-splat-lite.cjs.map +1 -1
- package/dist/gaussian-splat-lite.min.cjs +81 -20
- package/dist/gaussian-splat-lite.min.cjs.map +1 -1
- package/dist/gaussian-splat-lite.module.js +821 -90
- package/dist/gaussian-splat-lite.module.js.map +1 -1
- package/dist/gaussian-splat-lite.module.min.js +2984 -2427
- package/dist/gaussian-splat-lite.module.min.js.map +1 -1
- package/dist/types/addons/TAANode.d.cts +4 -2
- package/dist/types/addons/TAANode.d.ts +4 -2
- package/dist/types/addons/TAAPass.d.cts +6 -15
- package/dist/types/addons/TAAPass.d.ts +6 -15
- package/dist/types/addons/taaShared.d.cts +4 -2
- package/dist/types/addons/taaShared.d.ts +4 -2
- package/dist/types/capture/SplatCapture.d.cts +66 -0
- package/dist/types/capture/SplatCapture.d.ts +66 -0
- package/dist/types/capture/WebGLCapture.d.cts +13 -0
- package/dist/types/capture/WebGLCapture.d.ts +13 -0
- package/dist/types/capture/WebGPUCapture.d.cts +17 -0
- package/dist/types/capture/WebGPUCapture.d.ts +17 -0
- package/dist/types/capture/pixels.d.cts +5 -0
- package/dist/types/capture/pixels.d.ts +5 -0
- package/dist/types/capture/rendererState.d.cts +3 -0
- package/dist/types/capture/rendererState.d.ts +3 -0
- package/dist/types/capture/sceneView.d.cts +3 -0
- package/dist/types/capture/sceneView.d.ts +3 -0
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/rendering/GaussianSplatRenderer.d.cts +17 -11
- package/dist/types/rendering/GaussianSplatRenderer.d.ts +17 -11
- package/dist/types/rendering/SplatAccumulator.d.cts +2 -1
- package/dist/types/rendering/SplatAccumulator.d.ts +2 -1
- package/dist/types/rendering/backend.d.cts +1 -1
- package/dist/types/rendering/backend.d.ts +1 -1
- package/dist/types/rendering/rendererUtils.d.cts +1 -5
- package/dist/types/rendering/rendererUtils.d.ts +1 -5
- package/dist/types/rendering/tsl/ProjectionProgram.d.cts +2 -0
- package/dist/types/rendering/tsl/ProjectionProgram.d.ts +2 -0
- package/dist/types/rendering/tsl/SplatMaterial.d.cts +1 -0
- package/dist/types/rendering/tsl/SplatMaterial.d.ts +1 -0
- package/dist/types/rendering/tsl/tslCompat.d.cts +1 -0
- package/dist/types/rendering/tsl/tslCompat.d.ts +1 -0
- package/dist/types/rendering/uniforms.d.cts +3 -3
- package/dist/types/rendering/uniforms.d.ts +3 -3
- package/dist/types/scene/SplatMesh.d.cts +1 -1
- package/dist/types/scene/SplatMesh.d.ts +1 -1
- package/docs/Architecture.md +54 -3
- package/docs/GaussianSplatRenderer.md +71 -55
- package/docs/PostDecode.md +52 -36
- package/docs/RadStreamScheduler.md +53 -41
- package/docs/SogStreamScheduler.md +49 -39
- package/docs/SplatCapture.md +147 -0
- package/docs/SplatEdit.md +33 -26
- package/docs/SplatFileType.md +11 -13
- package/docs/SplatLoader.md +19 -14
- package/docs/SplatMesh.md +69 -49
- package/docs/Splats.md +33 -26
- package/docs/StochasticRendering.md +27 -30
- package/docs/TAAPass.md +98 -73
- package/package.json +1 -1
- package/docs/SplatAccumulator.md +0 -37
|
@@ -7,7 +7,7 @@ import { WebGPUSplatBackend } from './webgpu/SplatBackend';
|
|
|
7
7
|
import * as THREE from "three";
|
|
8
8
|
export type SplatBackend = WebGLSplatBackend | WebGPUSplatBackend | WebGLFallbackSplatBackend;
|
|
9
9
|
export declare function createSplatBackend(renderer: GaussianSplatCompatibleRenderer, uniforms: Uniforms, options: SplatMaterialOptions): SplatBackend;
|
|
10
|
-
export declare function configureSplatOutput(renderer: GaussianSplatCompatibleRenderer, target: THREE.RenderTarget | null, uniforms: Uniforms): void;
|
|
10
|
+
export declare function configureSplatOutput(renderer: GaussianSplatCompatibleRenderer, target: THREE.RenderTarget | null, uniforms: Uniforms, encodeLinear?: boolean): void;
|
|
11
11
|
export type CPUOrderingUpdate = {
|
|
12
12
|
ordering: Uint32Array;
|
|
13
13
|
activeSplats: number;
|
|
@@ -2,11 +2,7 @@ import * as THREE from "three";
|
|
|
2
2
|
type WebGPURenderer = import('three/webgpu').WebGPURenderer;
|
|
3
3
|
export type GaussianSplatCompatibleRenderer = THREE.WebGLRenderer | WebGPURenderer;
|
|
4
4
|
export declare function isWebGPURenderer(renderer: GaussianSplatCompatibleRenderer): renderer is WebGPURenderer;
|
|
5
|
-
export declare function usesNativeWebGPU(renderer: GaussianSplatCompatibleRenderer):
|
|
6
|
-
backend: {
|
|
7
|
-
isWebGPUBackend: true;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
5
|
+
export declare function usesNativeWebGPU(renderer: GaussianSplatCompatibleRenderer): boolean;
|
|
10
6
|
/**
|
|
11
7
|
* The eyes of a WebXR camera, or the camera itself. An ArrayCamera without
|
|
12
8
|
* eyes draws as a single view.
|
|
@@ -2,11 +2,7 @@ import * as THREE from "three";
|
|
|
2
2
|
type WebGPURenderer = import('three/webgpu').WebGPURenderer;
|
|
3
3
|
export type GaussianSplatCompatibleRenderer = THREE.WebGLRenderer | WebGPURenderer;
|
|
4
4
|
export declare function isWebGPURenderer(renderer: GaussianSplatCompatibleRenderer): renderer is WebGPURenderer;
|
|
5
|
-
export declare function usesNativeWebGPU(renderer: GaussianSplatCompatibleRenderer):
|
|
6
|
-
backend: {
|
|
7
|
-
isWebGPUBackend: true;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
5
|
+
export declare function usesNativeWebGPU(renderer: GaussianSplatCompatibleRenderer): boolean;
|
|
10
6
|
/**
|
|
11
7
|
* The eyes of a WebXR camera, or the camera itself. An ArrayCamera without
|
|
12
8
|
* eyes draws as a single view.
|
|
@@ -30,6 +30,8 @@ export type SplatProjection = {
|
|
|
30
30
|
/** Source color space; the draw stage applies encodeLinear. */
|
|
31
31
|
rgba: Node<"vec4">;
|
|
32
32
|
supportRadius: Node<"float">;
|
|
33
|
+
/** A wide kernel's low 16 bits hold its edge fade as a half. */
|
|
34
|
+
supportRadiusSquared: Node<"float">;
|
|
33
35
|
kernelPower: Node<"float">;
|
|
34
36
|
};
|
|
35
37
|
/** Shared projection for vertex and compute paths. Call inside a TSL Fn. */
|
|
@@ -30,6 +30,8 @@ export type SplatProjection = {
|
|
|
30
30
|
/** Source color space; the draw stage applies encodeLinear. */
|
|
31
31
|
rgba: Node<"vec4">;
|
|
32
32
|
supportRadius: Node<"float">;
|
|
33
|
+
/** A wide kernel's low 16 bits hold its edge fade as a half. */
|
|
34
|
+
supportRadiusSquared: Node<"float">;
|
|
33
35
|
kernelPower: Node<"float">;
|
|
34
36
|
};
|
|
35
37
|
/** Shared projection for vertex and compute paths. Call inside a TSL Fn. */
|
|
@@ -8,6 +8,7 @@ export type ProjectedVertexData = {
|
|
|
8
8
|
splatUv: Node<"vec2">;
|
|
9
9
|
/** Stochastic variant only. */
|
|
10
10
|
stochasticSeed?: Node<"uint">;
|
|
11
|
+
/** A wide kernel's low 16 bits hold its edge fade as a half. */
|
|
11
12
|
supportRadiusSquared: Node<"float">;
|
|
12
13
|
kernelPower: Node<"float">;
|
|
13
14
|
viewportOrigin: Node<"vec2">;
|
|
@@ -8,6 +8,7 @@ export type ProjectedVertexData = {
|
|
|
8
8
|
splatUv: Node<"vec2">;
|
|
9
9
|
/** Stochastic variant only. */
|
|
10
10
|
stochasticSeed?: Node<"uint">;
|
|
11
|
+
/** A wide kernel's low 16 bits hold its edge fade as a half. */
|
|
11
12
|
supportRadiusSquared: Node<"float">;
|
|
12
13
|
kernelPower: Node<"float">;
|
|
13
14
|
viewportOrigin: Node<"vec2">;
|
|
@@ -37,6 +37,7 @@ type UintWorkgroup = WorkgroupInfoNode & {
|
|
|
37
37
|
setName(name: string): UintWorkgroup;
|
|
38
38
|
};
|
|
39
39
|
type Compatibility = {
|
|
40
|
+
convertColorSpace(value: Node<"vec4">, source: string, target: string): Node<"vec4">;
|
|
40
41
|
floatBitsToUint<T extends keyof FloatToUint>(value: Node<T>): Node<FloatToUint[T]>;
|
|
41
42
|
uintBitsToFloat<T extends keyof UintToFloat>(value: Node<T>): Node<UintToFloat[T]>;
|
|
42
43
|
packHalf2x16(value: Node<"vec2">): Node<"uint">;
|
|
@@ -37,6 +37,7 @@ type UintWorkgroup = WorkgroupInfoNode & {
|
|
|
37
37
|
setName(name: string): UintWorkgroup;
|
|
38
38
|
};
|
|
39
39
|
type Compatibility = {
|
|
40
|
+
convertColorSpace(value: Node<"vec4">, source: string, target: string): Node<"vec4">;
|
|
40
41
|
floatBitsToUint<T extends keyof FloatToUint>(value: Node<T>): Node<FloatToUint[T]>;
|
|
41
42
|
uintBitsToFloat<T extends keyof UintToFloat>(value: Node<T>): Node<UintToFloat[T]>;
|
|
42
43
|
packHalf2x16(value: Node<"vec2">): Node<"uint">;
|
|
@@ -35,12 +35,12 @@ export declare function makeSplatUniforms(): {
|
|
|
35
35
|
minPixelRadius: {
|
|
36
36
|
value: number;
|
|
37
37
|
};
|
|
38
|
-
maxPixelRadius: {
|
|
39
|
-
value: number;
|
|
40
|
-
};
|
|
41
38
|
minAlpha: {
|
|
42
39
|
value: number;
|
|
43
40
|
};
|
|
41
|
+
edgeFade: {
|
|
42
|
+
value: THREE.Vector2;
|
|
43
|
+
};
|
|
44
44
|
preBlurAmount: {
|
|
45
45
|
value: number;
|
|
46
46
|
};
|
|
@@ -35,12 +35,12 @@ export declare function makeSplatUniforms(): {
|
|
|
35
35
|
minPixelRadius: {
|
|
36
36
|
value: number;
|
|
37
37
|
};
|
|
38
|
-
maxPixelRadius: {
|
|
39
|
-
value: number;
|
|
40
|
-
};
|
|
41
38
|
minAlpha: {
|
|
42
39
|
value: number;
|
|
43
40
|
};
|
|
41
|
+
edgeFade: {
|
|
42
|
+
value: THREE.Vector2;
|
|
43
|
+
};
|
|
44
44
|
preBlurAmount: {
|
|
45
45
|
value: number;
|
|
46
46
|
};
|
|
@@ -70,7 +70,7 @@ export declare class SplatMesh extends THREE.Object3D {
|
|
|
70
70
|
dispose(): void;
|
|
71
71
|
/** Copy cached local bounds; false includes scale/rotation and shape at source alpha 0.01. */
|
|
72
72
|
getBoundingBox(centersOnly?: boolean, target?: THREE.Box3): THREE.Box3;
|
|
73
|
-
frameUpdate({ time, deltaTime, globalEdits }: SplatMeshFrameContext): void;
|
|
73
|
+
frameUpdate({ time, deltaTime, globalEdits }: SplatMeshFrameContext, callbacks?: boolean): void;
|
|
74
74
|
updateVersion({ sort }?: {
|
|
75
75
|
sort?: boolean;
|
|
76
76
|
}): void;
|
|
@@ -70,7 +70,7 @@ export declare class SplatMesh extends THREE.Object3D {
|
|
|
70
70
|
dispose(): void;
|
|
71
71
|
/** Copy cached local bounds; false includes scale/rotation and shape at source alpha 0.01. */
|
|
72
72
|
getBoundingBox(centersOnly?: boolean, target?: THREE.Box3): THREE.Box3;
|
|
73
|
-
frameUpdate({ time, deltaTime, globalEdits }: SplatMeshFrameContext): void;
|
|
73
|
+
frameUpdate({ time, deltaTime, globalEdits }: SplatMeshFrameContext, callbacks?: boolean): void;
|
|
74
74
|
updateVersion({ sort }?: {
|
|
75
75
|
sort?: boolean;
|
|
76
76
|
}): void;
|
package/docs/Architecture.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[Back to documentation](../README.md#documentation)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This guide is for contributors. It describes internal module boundaries, backend differences, and resource lifetimes. To use the library, start from the [README](../README.md#quick-start) and the API pages it lists; those pages describe behavior, and this one explains how it is implemented.
|
|
6
|
+
|
|
7
|
+
[`src/index.ts`](../src/index.ts) defines the public exports. Applications use `SplatMesh` for models and one `GaussianSplatRenderer` for the scene.
|
|
6
8
|
|
|
7
9
|
## Source layout
|
|
8
10
|
|
|
@@ -21,11 +23,13 @@
|
|
|
21
23
|
| `rust/gaussian-splat-rs/src/` | WASM bridges, typed-array output, LOD selection, sorting, and raycasting |
|
|
22
24
|
| `src/runtime/` | Worker RPC, pooling, transferables, and WASM initialization |
|
|
23
25
|
| `src/utils/` | Numeric conversion, spatial transforms, and Three.js helpers |
|
|
24
|
-
| `src/rendering/` | Shared updates
|
|
26
|
+
| `src/rendering/` | Shared updates, sorting handoffs, backend selection, and stochastic blue noise |
|
|
25
27
|
| `src/rendering/tsl/` | Shared TSL generation, projection, drawing, and view uniforms |
|
|
26
28
|
| `src/rendering/webgpu/` | Compute projection, projected caches, GPU sorting, and indirect drawing |
|
|
27
29
|
| `src/rendering/webgl/` | GLSL materials, texture generation, and CPU ordering uploads |
|
|
28
30
|
| `src/rendering/webgl-fallback/` | WebGPURenderer WebGL2 raster generation and ordering uploads |
|
|
31
|
+
| `src/capture/` | Optional offscreen targets, readback, cube captures, and PMREM filtering |
|
|
32
|
+
| `src/addons/` | Temporal anti-aliasing: `TAAPass` for WebGLRenderer, `TAANode` for WebGPURenderer, and their shared state |
|
|
29
33
|
|
|
30
34
|
## Rendering boundaries
|
|
31
35
|
|
|
@@ -34,6 +38,7 @@ The renderer combines visible models using Three.js transforms, visibility, and
|
|
|
34
38
|
| Owner | Responsibility |
|
|
35
39
|
| --- | --- |
|
|
36
40
|
| `GaussianSplatRenderer` | Scene updates, accumulator handoff, and sorting |
|
|
41
|
+
| `SplatCapture` | Independent capture Splat state, offscreen targets, readback, and PMREM |
|
|
37
42
|
| `SplatAccumulator` | Scene mappings, versions, camera-relative origin, and WebGL texture generation |
|
|
38
43
|
| WebGPU backend | Compute projection, caches, GPU sorting, and indirect drawing |
|
|
39
44
|
| WebGL backend | GLSL materials, ordering textures, and texture generation |
|
|
@@ -44,11 +49,55 @@ For sorted rendering, native WebGPU keeps ordering and visible counts on the GPU
|
|
|
44
49
|
|
|
45
50
|
In `webgpu/`, `ProjectedSplats.ts` coordinates projection and sorting, `ProjectionCache.ts` owns projected storage, and `RadixSort.ts` owns sort passes. WebXR uses the eyes' mean pose for generation and sorting, with separate projections for each eye. Both WebGL backends share `webgl/OrderingTexture.ts` for allocation and disposal, while keeping their own upload and binding paths.
|
|
46
51
|
|
|
52
|
+
`backend.ts` selects the backend from the renderer type and its public `coordinateSystem`, which distinguishes native WebGPU from WebGL fallback. It chooses the blend space for each output: the working color space by default, `renderer.outputColorSpace` when WebGLRenderer draws to the canvas, and the target texture's color space when it draws to an XR-style target.
|
|
53
|
+
|
|
54
|
+
Projected Splat support is capped at the viewport's short side, in projection space scaled by `focalAdjustment`, in both the TSL projection program and the GLSL vertex shader. The quad and its UV extent shrink by the same ratio, preserving the Gaussian profile.
|
|
55
|
+
|
|
56
|
+
A kernel still above `minAlpha` where its support ends is faded there instead of cut off. The fragment stage rescales it about its peak, `(alpha + fade) * kernel - fade`, so it reaches `minAlpha` at the support edge. The quad is never enlarged.
|
|
57
|
+
|
|
58
|
+
- **Gaussians.** Only `maxStdDev` can end a Gaussian early, so its fade follows from its alpha and the per-draw `edgeFade` uniform, a scale and offset derived from `maxStdDev` and `minAlpha`. It needs no per-Splat data, and a Gaussian that `minAlpha` already ends is drawn exactly as before.
|
|
59
|
+
- **Wide kernels.** The edge value depends on the kernel power, so the projection computes the fade and stores it as a half in the low 16 bits of the squared support radius. That radius is first rounded down to its high 16 bits, at most 0.6% of the radius, which keeps the fragment stage's radius test exact. The squared radius therefore passes to the fragment stage bit for bit, and native WebGPU caches it in place of the radius.
|
|
60
|
+
|
|
61
|
+
Errors from automatic updates are caught and logged once per message; a draw whose preparation fails is skipped. Explicit `update()` calls rethrow to the caller. `frameCallbacks` is an internal flag for a second renderer on the same scene, so each `SplatMesh.onFrame` runs once per frame.
|
|
62
|
+
|
|
47
63
|
Resource rules:
|
|
48
64
|
|
|
49
65
|
- Wait for outstanding GPU compilation before disposing the sorter; preserve compute nodes when resizing resources or changing source meshes.
|
|
50
66
|
- Keep color conversion and XR output handling with the backend that owns them.
|
|
51
67
|
|
|
68
|
+
### Stochastic rendering
|
|
69
|
+
|
|
70
|
+
Sorted and stochastic draws compile separate shaders without mode branches. A mode change takes effect at the next update boundary, after the current draw; both WebGL backends also wait for the matching accumulator and sort, and `stochasticActive` reports the mode being drawn. Stochastic draws use the opaque list with depth testing and writing.
|
|
71
|
+
|
|
72
|
+
Coverage uses a tileable 32-frame spatiotemporal blue-noise atlas (`blueNoise.ts`, generated by `scripts/generate-blue-noise.js`) on all backends. Each Splat keeps its own spatial offset and temporal phase, so consecutive samples follow the atlas's time axis instead of choosing unrelated offsets. The temporal sequence is optimized for exponential history accumulation and wraps after 32 samples. `stochasticSample` advances once per scene render, and every view in that render shares it.
|
|
73
|
+
|
|
74
|
+
Seeds exist only for stochastic draws: WebGL accumulators omit the seed layer in sorted rendering, and native WebGPU allocates its seed buffer on demand. Front-to-back stochastic ordering uses 16-bit keys. With unsorted stochastic rendering, `shrinkResources()` releases the sort worker and ordering.
|
|
75
|
+
|
|
76
|
+
## Capture boundaries
|
|
77
|
+
|
|
78
|
+
[SplatCapture](SplatCapture.md) is optional; the core renderer allocates no capture resources.
|
|
79
|
+
|
|
80
|
+
- **Independent Splat state.** The helper owns an internal `GaussianSplatRenderer` with `autoUpdate` and stochastic rendering off, sharing the display renderer's timer, loaded Splat data, and model-owned SDF edit textures. Its accumulators, sorting, and projection resources are separate, so display ordering and camera state are untouched. Global and model-local edits apply to captures and follow their latest values. `frameCallbacks` is off, leaving `onFrame` to the display renderer.
|
|
81
|
+
- **Stencil captures.** 2D and cube targets follow the Three.js renderer's stencil setting, with no separate capture option; a 2D target without a depth buffer gets no stencil, since Three.js attaches stencil only with depth. The intermediate target uses a depth-stencil attachment when stencil is enabled. With stencil, native depth is 32-bit float only for a reversed depth buffer or a float output depth texture, and only when the device has `depth32float-stencil8`; otherwise it is 24-bit. The scene's stencil masking applies before copying its color and depth to the output.
|
|
82
|
+
- **Options.** Quality, sorting, and material options are copied from the supplied renderer at the start of each capture. The active Splat material's stencil comparison and write settings are copied as well. Cube captures force radial sorting. The internal renderer takes the capture camera's layer mask.
|
|
83
|
+
- **Two phases.** Preparation awaits `update()` on a filtered scene view (`sceneView.ts`), which excludes hidden models from traversal without changing visibility and collects edits with the original scene's visibility. If the display updates shared models during a pending sort, preparation runs again; appearance-only changes reuse the ordering. The draw is synchronous: other Splat renderers' layer masks are cleared, `hideObjects` are hidden, and the internal renderer joins the scene. `withCaptureState()` saves and restores the render target, cube face, mip level, XR setting, automatic clearing, and MRT. Nothing stays changed across an `await`, and everything is restored when drawing throws.
|
|
84
|
+
- **Ordering.** Captures on one helper are queued and run in call order. The camera or `worldCenter` is copied when the call is made. `renderReadTarget()` and `renderEnvMap()` read or filter inside the same queued task, before a later capture can redraw the target.
|
|
85
|
+
- **Cube captures.** Splat data is prepared at `worldCenter` with a 90° camera, then six faces render with automatic updates off. Both WebGL backends share one radial CPU sort across the faces; native WebGPU projects, compacts, and sorts for each face while drawing. Every capture runs `update()`, whose version checks reuse valid data and ordering, so 1.1.8's `update` option is not offered. Mipmaps are generated after the sixth face. Filtered and unfiltered cubes use separate targets, reallocated when size, clipping planes, or the renderer's stencil setting change.
|
|
86
|
+
- **Color.** `WebGLCapture` renders into an intermediate flagged as an XR-style target, 8-bit unless the output is float, so materials convert to the output color space before blending as on the canvas; a full-screen pass then converts to the target's storage space and copies depth. `WebGPUCapture` renders in the working color space, then applies the renderer's output transform and converts to storage space. On both, float outputs keep their type so values stay unclamped, and the intermediate takes the output's sample count, so multisampling applies to the scene and not to the final pass.
|
|
87
|
+
- **Readback.** `pixels.ts` returns packed RGBA8 with the bottom row first on every backend, removing native WebGPU's 256-byte row padding and flipping its top-left origin. Supersampled targets are box-filtered on the CPU. Cube faces are normalized to the WebGL cube render target layout: native WebGPU stores +X and −X swapped and reads each face rotated 180°.
|
|
88
|
+
- **Ownership.** `dispose()` releases the internal renderer, 2D and cube targets, readback buffers, and the PMREM generator. Each texture from `renderEnvMap()` belongs to the caller; disposing it also releases its PMREM render target.
|
|
89
|
+
|
|
90
|
+
## Temporal anti-aliasing boundaries
|
|
91
|
+
|
|
92
|
+
[TAAPass and TAANode](TAAPass.md) are derived from Three.js TRAA, without a velocity attachment: reprojection uses scene depth and camera motion only, so object motion is not tracked.
|
|
93
|
+
|
|
94
|
+
- `taaShared.ts` owns the state both share: a 32-entry Halton(2, 3) jitter sequence, jittered and unjittered projections, previous-frame matrices, the history index, sizing, and reset. It supports custom projections, scaled rigs, reversed depth, and logarithmic depth.
|
|
95
|
+
- Each implementation captures the scene itself into a half-float target with a depth texture and resolves between two history targets, with no history copies. The resolve applies depth rejection away from edges, neighborhood clipping, and luminance-aware blending.
|
|
96
|
+
- The capture target takes a stencil buffer when the Three.js renderer has one; the history targets never do, since the resolve writes only color and depth. Depth stays 32-bit float, except in `TAANode` on the WebGL2 fallback or on a device without `depth32float-stencil8`, where it is 24-bit.
|
|
97
|
+
- The camera's projection is jittered only during capture. Native Splat projection reads the unjittered matrix through `getTAAProjection()`, so projection and sorting results are reused while only the jitter changes.
|
|
98
|
+
- `TAAPass` flags its capture target as an XR-style target, so Three.js converts materials to `renderer.outputColorSpace` before blending, matching canvas blending. Tone mapping is disabled during capture. The final copy decodes the sRGB transfer into the composer's working-space buffer, the inverse of `OutputPass`, so the two round-trip at any alpha; as the last pass it presents the output-space image unchanged. An output color space change resets history.
|
|
99
|
+
- `TAANode` is a TSL node updated once per render. It captures and accumulates in `ColorManagement.workingColorSpace`, leaving tone mapping and output conversion to `RenderPipeline`. A working color space change resets history.
|
|
100
|
+
|
|
52
101
|
## Decoder boundaries
|
|
53
102
|
|
|
54
103
|
PLY, SPZ, SOG, and RAD decode in `gaussian-splat-lib` and publish through `SplatReceiver`. This core library has no JavaScript or WASM dependency. `gaussian-splat-rs` adapts browser inputs and writes the output into JS typed arrays through `SplatsData`.
|
|
@@ -69,6 +118,7 @@ The [postDecode](PostDecode.md) API builds expressions on the calling thread and
|
|
|
69
118
|
| --- | --- |
|
|
70
119
|
| `program.ts` / `builder.ts` | Public API, program identity, typed expressions, and patch validation |
|
|
71
120
|
| `protocol.ts` | Opcodes, packed layouts, and shared types without builder or runtime dependencies |
|
|
121
|
+
| `optimizer.ts` | Fusion of single-use arithmetic intermediates before compilation |
|
|
72
122
|
| `compiler.ts` | Conditional flow, dependencies, packed instructions, and attribute snapshots |
|
|
73
123
|
| `registers.ts` | Runtime register allocation and values carried between condition stages |
|
|
74
124
|
| `operations.ts` / `runtime.ts` | Packed input reads, block execution, conditions, and output writes |
|
|
@@ -81,7 +131,8 @@ Loaders own transport and parsing; schedulers own selection, fades, publication,
|
|
|
81
131
|
|
|
82
132
|
- `StreamWorkerPool.run()` queues worker leases, assigns task IDs, links cancellation, counts downloads, and balances loading-manager notifications. Each loader has its own pool; format-specific callbacks retain SOG caches or release RAD decoder slots.
|
|
83
133
|
- `IndexedSplats` shares texture storage and selected-index reads between `RadPagedSplats` and `SogRegionSplats`. Slot assignment and scene attachment remain with the format-specific scheduler and batch classes.
|
|
84
|
-
- `
|
|
134
|
+
- `StreamCameras.ts` owns the registered cameras and their resolutions, and expands a WebXR `ArrayCamera` into its eye views once they have a projection and viewport.
|
|
135
|
+
- `streamOptions.ts` owns shared defaults, validation, retry classification, and statistics. `StreamByteBudget` bounds pending copies separately from active loads; ready data has no per-update byte allowance.
|
|
85
136
|
|
|
86
137
|
`splatBudget` controls selected detail, not total memory. Resident-byte estimates exclude pending copies and WASM memory, which are reported separately; resident storage has no byte cap. Pending copies allow 8 MiB per concurrent load (32 MiB by default), enlarged for an indivisible RAD page; one oversized item can proceed alone. This bounds the waiting queue, not the bytes published or uploaded per frame.
|
|
87
138
|
|
|
@@ -2,83 +2,81 @@
|
|
|
2
2
|
|
|
3
3
|
[Back to documentation](../README.md#documentation)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Draws every visible `SplatMesh` in a scene. Add one to the scene; a single instance displays all your models.
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
|
|
7
|
+
```js
|
|
8
|
+
import { GaussianSplatRenderer } from "gaussian-splat-lite";
|
|
9
|
+
|
|
10
|
+
const splatRenderer = new GaussianSplatRenderer({ renderer });
|
|
11
|
+
scene.add(splatRenderer);
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
With `WebGPURenderer`, call `await renderer.init()` before creating it. Create your Three.js renderer with `antialias: false`: multisampling slows Splats down without improving them.
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
| --- | --- | --- | --- |
|
|
15
|
-
| `renderer` | `WebGPURenderer \| THREE.WebGLRenderer` | Required | Three.js renderer; call `await renderer.init()` first when using WebGPURenderer |
|
|
16
|
-
| `onDirty` | `() => void` | `undefined` | Called when the image needs a redraw |
|
|
17
|
-
| `premultipliedAlpha` | `boolean` | `true` | Use premultiplied alpha for blending |
|
|
18
|
-
| `timer` | `THREE.Timer` | New internal timer | Optional shared timer; update it yourself when supplied |
|
|
19
|
-
| `autoUpdate` | `boolean` | `true` | Update visible Splats when rendering |
|
|
20
|
-
| `preUpdate` | `boolean` | `true` | Update before rendering on WebGL; XR updates follow the render pass. Unused on native WebGPU |
|
|
16
|
+
Every option except `renderer` and `timer` is also a property, so you can change it at any time.
|
|
21
17
|
|
|
22
|
-
##
|
|
18
|
+
## Basic options
|
|
23
19
|
|
|
24
20
|
| Option | Type | Default | Description |
|
|
25
21
|
| --- | --- | --- | --- |
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `clipXY` | `number` | `1.25` | Allow centers slightly outside the view; `1` clips at its edge |
|
|
33
|
-
| `focalAdjustment` | `number` | `2` | Adjust projected size; higher values generally look sharper |
|
|
22
|
+
| `renderer` | `WebGPURenderer \| THREE.WebGLRenderer` | Required | Your Three.js renderer |
|
|
23
|
+
| `onDirty` | `() => void` | `undefined` | Called when the image needs a redraw; see [on-demand rendering](#on-demand-rendering) |
|
|
24
|
+
| `autoUpdate` | `boolean` | `true` | Update Splats automatically on each render. Set to `false` to call `update()` yourself |
|
|
25
|
+
| `preUpdate` | `boolean` | `true` | On WebGL, update before drawing so changes show in the same frame. In WebXR, updates run after drawing. Not used on native WebGPU |
|
|
26
|
+
| `timer` | `THREE.Timer` | New internal timer | Share your own timer with [`onFrame`](SplatMesh.md#scene-integration) animations; update it yourself when supplied |
|
|
27
|
+
| `premultipliedAlpha` | `boolean` | `true` | Blend with premultiplied alpha |
|
|
34
28
|
|
|
35
|
-
##
|
|
29
|
+
## Quality options
|
|
36
30
|
|
|
37
31
|
| Option | Type | Default | Description |
|
|
38
32
|
| --- | --- | --- | --- |
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `depthTest` | `boolean` | `true` | Respect depth from other geometry |
|
|
47
|
-
| `depthWrite` | `boolean` | `false` | Write depth directly; normally leave off for transparent Splats |
|
|
48
|
-
|
|
49
|
-
Native WebGPU sorts before drawing. On WebGL, the current sort order stays in use until a new sort is ready.
|
|
50
|
-
|
|
51
|
-
Automatic update errors are caught and logged once per error message, preventing unhandled promise rejections. If draw preparation fails, that draw is skipped so rendering can continue. Explicit `update()` calls report errors to the caller.
|
|
33
|
+
| `maxStdDev` | `number` | `Math.sqrt(8)` | How far each Splat extends from its center. Lower values trim its soft outer edge and render faster; a trimmed Splat fades to `minAlpha` at its edge instead of ending in a step. `Math.sqrt(4)` to `Math.sqrt(9)` looks acceptable |
|
|
34
|
+
| `minPixelRadius` | `number` | `1` | Skip Splats smaller than this radius in screen pixels |
|
|
35
|
+
| `minAlpha` | `number` | `0.5 / 255` | Hide the parts of a Splat more transparent than this |
|
|
36
|
+
| `preBlurAmount` | `number` | `0.3` | Enlarge and soften Splats. Use `0` for models trained with anti-aliasing |
|
|
37
|
+
| `blurAmount` | `number` | `0` | Soften Splats while adjusting their opacity to compensate. For models trained with anti-aliasing, use `0.3` together with `preBlurAmount: 0` |
|
|
38
|
+
| `clipXY` | `number` | `1.25` | How far outside the view a Splat's center may be before the Splat is skipped; `1` cuts exactly at the edge |
|
|
39
|
+
| `focalAdjustment` | `number` | `2` | Adjust the size of Splats on screen; higher values generally look sharper |
|
|
52
40
|
|
|
53
|
-
|
|
41
|
+
A Splat's radius on screen is limited automatically to the short side of the viewport.
|
|
54
42
|
|
|
55
|
-
|
|
43
|
+
## Sorting and blending options
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
| Option | Type | Default | Description |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `sortRadial` | `boolean` | `false` | Sort by distance from the camera instead of by depth. Depth suits most models; distance is steadier while the camera rotates |
|
|
48
|
+
| `fastSort` | `boolean` | `true` | Faster, lower-precision sorting. Has no effect on stochastic rendering |
|
|
49
|
+
| `minSortIntervalMs` | `number` | `0` | Minimum time between sorts on WebGL. Not used on native WebGPU |
|
|
50
|
+
| `transparent` | `boolean` | `true` | Blend Splats as transparent objects |
|
|
51
|
+
| `encodeLinear` | `boolean` | `undefined` | Convert model colors from sRGB to linear before blending; `false` keeps their sRGB values. Chosen automatically when unset |
|
|
52
|
+
| `depthTest` | `boolean` | `true` | Let other geometry hide the Splats behind it |
|
|
53
|
+
| `depthWrite` | `boolean` | `false` | Write Splat depth. Normally leave off, because most of a Splat is transparent |
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
On native WebGPU, Splats are sorted before every draw. On WebGL, sorting finishes in the background: after the view changes, the previous order stays on screen until the new one is ready.
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
## Stochastic rendering options
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
| Option | Type | Default | Description |
|
|
60
|
+
| --- | --- | --- | --- |
|
|
61
|
+
| `stochastic` | `boolean` | `false` | Use stochastic rendering; smooth its noise with temporal anti-aliasing |
|
|
62
|
+
| `stochasticSort` | `boolean` | `true` | Sort Splats from front to back in stochastic rendering; `false` skips sorting |
|
|
63
|
+
| `autoAdvanceStochasticSample` | `boolean` | `true` | Change the noise pattern on every render, including in WebXR |
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
See [Stochastic rendering](StochasticRendering.md) for setup.
|
|
66
66
|
|
|
67
|
-
##
|
|
67
|
+
## Properties and methods
|
|
68
68
|
|
|
69
69
|
| API | Description |
|
|
70
70
|
| --- | --- |
|
|
71
|
-
| `update({ scene, camera })` |
|
|
72
|
-
| `shrinkResources({ scene, camera })` |
|
|
73
|
-
| `clearSplats()` | Clear the
|
|
71
|
+
| `update({ scene, camera })` | Bring the Splats up to date with the scene and camera; returns a promise. Only needed with `autoUpdate = false` |
|
|
72
|
+
| `shrinkResources({ scene, camera })` | Update, then release memory that is no longer needed, for example after removing large models; returns a promise |
|
|
73
|
+
| `clearSplats()` | Clear the Splats from the display without removing models from the scene |
|
|
74
74
|
| `dispose()` | Release this renderer's resources |
|
|
75
|
-
| `stochasticActive` | Read
|
|
76
|
-
| `stochasticSample` | Noise pattern index
|
|
77
|
-
| `synchronousSort` | Read
|
|
78
|
-
|
|
79
|
-
`premultipliedAlpha`, `transparent`, `depthTest`, and `depthWrite` are also writable properties with the behavior listed above.
|
|
75
|
+
| `stochasticActive` | Read-only. Whether stochastic rendering is currently being drawn; it changes shortly after you set `stochastic` |
|
|
76
|
+
| `stochasticSample` | Noise pattern index, `0` by default. Set `autoAdvanceStochasticSample = false` to control it yourself |
|
|
77
|
+
| `synchronousSort` | Read-only. `true` when Splats are always sorted before they are drawn, as on native WebGPU |
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
To update manually after the scene or camera changes:
|
|
82
80
|
|
|
83
81
|
```js
|
|
84
82
|
splatRenderer.autoUpdate = false;
|
|
@@ -86,9 +84,25 @@ await splatRenderer.update({ scene, camera });
|
|
|
86
84
|
renderer.render(scene, camera);
|
|
87
85
|
```
|
|
88
86
|
|
|
87
|
+
Errors during automatic updates are logged to the console, once per message, and rendering continues. Errors from your own `update()` calls are thrown to you.
|
|
88
|
+
|
|
89
|
+
## WebXR and multiple views
|
|
90
|
+
|
|
91
|
+
WebXR needs no extra setup: render with your application camera as usual. A Splat model on either eye's layers is visible in both eyes.
|
|
92
|
+
|
|
93
|
+
For several views outside WebXR, render each one with its own camera. `ArrayCamera` is supported only in WebXR: elsewhere `update()` throws, and automatic draws skip the Splats and log an error. If each view needs its own sort order, give each camera its own Splat renderer on a separate layer.
|
|
94
|
+
|
|
95
|
+
## Color and postprocessing
|
|
96
|
+
|
|
97
|
+
Model colors are converted for you. Control the final image with your Three.js renderer's output color space, as for any other scene.
|
|
98
|
+
|
|
99
|
+
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.
|
|
100
|
+
|
|
101
|
+
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).
|
|
102
|
+
|
|
89
103
|
## On-demand rendering
|
|
90
104
|
|
|
91
|
-
|
|
105
|
+
To render only when something changes, connect `onDirty` and your controls to the same render request. This example assumes `renderer`, `scene`, and `camera` already exist:
|
|
92
106
|
|
|
93
107
|
```js
|
|
94
108
|
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
@@ -124,12 +138,14 @@ const splat = new SplatMesh({ url: "/assets/model.spz" });
|
|
|
124
138
|
scene.add(splat);
|
|
125
139
|
requestRender();
|
|
126
140
|
await splat.initialized;
|
|
127
|
-
requestRender(); // Loading may finish after the
|
|
141
|
+
requestRender(); // Loading may finish after the last requested render.
|
|
128
142
|
```
|
|
129
143
|
|
|
144
|
+
Request a render yourself after changing a model:
|
|
145
|
+
|
|
130
146
|
```js
|
|
131
147
|
splat.opacity = 0.5;
|
|
132
148
|
requestRender();
|
|
133
149
|
```
|
|
134
150
|
|
|
135
|
-
See the [
|
|
151
|
+
See the [quick start](../README.md#quick-start) for a complete setup.
|
package/docs/PostDecode.md
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[Back to documentation](../README.md#documentation)
|
|
4
4
|
|
|
5
|
-
Changes
|
|
6
|
-
|
|
7
|
-
`define()` runs its callback immediately, so mistakes in the expression throw right away; the result is then applied to each Splat while loading.
|
|
5
|
+
Changes every Splat of a model while it loads: move it, scale it, recolor it, or adjust its opacity. Describe the change once with `postDecode.define()`, then pass the result as the `postDecode` option of `SplatMesh` or `Splats`. It works for PLY, SPZ, SOG, and RAD files.
|
|
8
6
|
|
|
9
7
|
```ts
|
|
10
8
|
import { postDecode, SplatFileType, SplatMesh } from "gaussian-splat-lite";
|
|
@@ -22,38 +20,55 @@ const mesh = new SplatMesh({
|
|
|
22
20
|
await mesh.initialized;
|
|
23
21
|
```
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
This example shifts the model and gives it a warmer tint.
|
|
24
|
+
|
|
25
|
+
Your callback runs once, right away, to record the calculation; it does not run for each Splat. That has two consequences:
|
|
26
|
+
|
|
27
|
+
- Build the calculation with the `op` functions. A JavaScript `if` or `+` cannot see individual Splats.
|
|
28
|
+
- Mistakes in the calculation throw immediately from `define()`, not later during loading.
|
|
29
|
+
|
|
30
|
+
A transform never adds, removes, or reorders Splats. The [reordering done by loading](Splats.md#data-rules) happens afterwards.
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
To change a model after it has loaded, use [SplatMesh properties](SplatMesh.md#properties) or [SDF edits](SplatEdit.md) instead.
|
|
33
|
+
|
|
34
|
+
## Splat fields
|
|
35
|
+
|
|
36
|
+
Read these from `splat`:
|
|
28
37
|
|
|
29
38
|
| Field | Type | Description |
|
|
30
39
|
| --- | --- | --- |
|
|
31
|
-
| `splat.position` | `vec3` | xyz
|
|
32
|
-
| `splat.scale` | `vec3` |
|
|
33
|
-
| `splat.quaternion` | `quaternion` | xyzw
|
|
34
|
-
| `splat.opacity` | `float` |
|
|
35
|
-
| `splat.alpha` | `float` |
|
|
40
|
+
| `splat.position` | `vec3` | Center, xyz |
|
|
41
|
+
| `splat.scale` | `vec3` | Size along each axis |
|
|
42
|
+
| `splat.quaternion` | `quaternion` | Rotation, xyzw |
|
|
43
|
+
| `splat.opacity` | `float` | Opacity as stored in the model, which can be above 1 |
|
|
44
|
+
| `splat.alpha` | `float` | Opacity from 0 (transparent) to 1 (opaque) |
|
|
36
45
|
| `splat.color` | `vec3` | RGB color |
|
|
37
|
-
| `splat.sh.coefficient(index)` | `vec3` | One of the 15
|
|
46
|
+
| `splat.sh.coefficient(index)` | `vec3` | One of the 15 view-dependent color coefficients |
|
|
38
47
|
|
|
39
|
-
`splat.sh.map((coefficient, { degree }) => ...)` builds
|
|
48
|
+
`splat.sh.map((coefficient, { degree }) => ...)` builds a calculation for all 15 coefficients at once. Only the ones the model has are updated.
|
|
40
49
|
|
|
41
|
-
##
|
|
50
|
+
## Returning changes
|
|
42
51
|
|
|
43
|
-
Return any
|
|
52
|
+
Return any of `position`, `scale`, `quaternion`, `opacity`, `alpha`, `color`, or `sh`. Fields you leave out stay as they are.
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
- `alpha` is clamped to `[0, 1]`, preserving other opacity state. Output either `opacity` or `alpha`, never both.
|
|
47
|
-
- Quaternions are normalized. Invalid or zero-length results preserve the original.
|
|
48
|
-
- Position and scale updates keep sorting centers synchronized.
|
|
54
|
+
Add `when` to change only the Splats that match a condition. Splats that do not match stay exactly as loaded:
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
```ts
|
|
57
|
+
const transform = postDecode.define(({ splat, op }) => ({
|
|
58
|
+
when: op.lt(op.component(splat.position, 1), 0), // Only Splats below y = 0.
|
|
59
|
+
alpha: 0,
|
|
60
|
+
}));
|
|
61
|
+
```
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
Rules for the values you return:
|
|
53
64
|
|
|
54
|
-
|
|
65
|
+
- Return `opacity` or `alpha`, never both. `alpha` is limited to 0–1. A negative `opacity` becomes 0, and values above 1 are allowed up to a fixed maximum.
|
|
66
|
+
- Quaternions are normalized for you. An invalid or zero-length result keeps the original rotation.
|
|
67
|
+
- Values are stored in a compact format, so what you read back later can differ slightly from what you calculated.
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
## External data
|
|
70
|
+
|
|
71
|
+
Inside `define(({ splat, op, attribute }) => ...)`, use `attribute()` to bring in your own per-Splat data, such as a weight or label for each Splat:
|
|
57
72
|
|
|
58
73
|
```ts
|
|
59
74
|
const weights = attribute({
|
|
@@ -67,21 +82,22 @@ const weights = attribute({
|
|
|
67
82
|
```
|
|
68
83
|
|
|
69
84
|
- `data` accepts any `ArrayBufferView`, including `DataView`; `byteOffset` is relative to that view.
|
|
70
|
-
- `components`
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
## Expression operations
|
|
75
|
-
|
|
76
|
-
Use `op` to calculate per-Splat values; JavaScript `if` does not evaluate individual Splats.
|
|
85
|
+
- `components` can be 1 to 4. Formats: `f32`, `f16`, `u8`, `unorm8`, `i8`, `snorm8`, `u16`, `unorm16`, `i16`, `snorm16`, `u32`, `i32`.
|
|
86
|
+
- Order the data like the Splats in the original file, for RAD files too. If it is shorter than the model, only the Splats it covers are changed.
|
|
87
|
+
- The data is read when a load starts. Changing it afterwards affects only later loads.
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
- predicates: `isFinite`, `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `and`, `or`, `not`, and `select`;
|
|
80
|
-
- vectors: `vec2`, `vec3`, `vec4`, `component`, `length`, `normalize`, `dot`, `cross`, and `maxComponentIndex`;
|
|
81
|
-
- rotations: `quaternion`, `quatMul`, and `rotateVector`;
|
|
89
|
+
## Operations
|
|
82
90
|
|
|
83
|
-
|
|
91
|
+
- **Arithmetic:** `add`, `sub`, `mul`, `div`, `min`, `max`, `pow`, `clamp`, `mix`, `neg`, `abs`, `sqrt`, `log`, `exp`, `floor`, `ceil`, `round`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`
|
|
92
|
+
- **Conditions:** `isFinite`, `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `and`, `or`, `not`, `select`
|
|
93
|
+
- **Vectors:** `vec2`, `vec3`, `vec4`, `component`, `length`, `normalize`, `dot`, `cross`, `maxComponentIndex`
|
|
94
|
+
- **Rotations:** `quaternion`, `quatMul`, `rotateVector`
|
|
84
95
|
|
|
85
|
-
|
|
96
|
+
Things to know:
|
|
86
97
|
|
|
87
|
-
|
|
98
|
+
- A number can be combined with a vector: `op.mul(splat.scale, 2)`.
|
|
99
|
+
- Comparisons and vector products need matching types. `eq` and `ne` compare two values of the same type; `lt`, `lte`, `gt`, and `gte` compare numbers; `dot` takes two vectors of the same size; `cross` takes two `vec3` values.
|
|
100
|
+
- `op.or(A, op.and(B, C))` means `A || (B && C)`. Conditions stop as soon as the answer is known, so put cheap conditions that rule out many Splats first.
|
|
101
|
+
- Values from different `define()` calls cannot be combined.
|
|
102
|
+
- Calculations use 32-bit floats.
|
|
103
|
+
- Very large calculations throw: the limit is 4096 operations.
|