@voluma/vlam 0.3.2 → 0.4.0
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/README.md +2 -2
- package/dist/core/compute-sorter.d.ts +7 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/radix-sorter.d.ts +6 -0
- package/dist/core/sort-worker-protocol.d.ts +2 -0
- package/dist/core/sorter.d.ts +4 -4
- package/dist/core/splat-mesh-types.d.ts +22 -5
- package/dist/core/splat-mesh.d.ts +11 -2
- package/dist/core/splat-sort-bounds.d.ts +17 -0
- package/dist/core/worker-sorter.d.ts +7 -5
- package/dist/formats/lcc.js +276 -277
- package/dist/formats/lcc.js.map +1 -1
- package/dist/formats/rad/index.d.ts +1 -1
- package/dist/formats/rad/parse-rad.d.ts +1 -1
- package/dist/formats/rad.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/lod-scheduler-ChoZyEeq.js +466 -0
- package/dist/lod-scheduler-ChoZyEeq.js.map +1 -0
- package/dist/radix-sorter-tSffmerk.js +181 -0
- package/dist/radix-sorter-tSffmerk.js.map +1 -0
- package/dist/relighting-qaANKC4Z.js +997 -0
- package/dist/relighting-qaANKC4Z.js.map +1 -0
- package/dist/{splat-mesh-CsLOQb08.js → splat-mesh-B1KlWHvx.js} +545 -513
- package/dist/splat-mesh-B1KlWHvx.js.map +1 -0
- package/dist/splat-mesh-types-BZIko-_9.js.map +1 -1
- package/dist/static-lod.js +1 -1
- package/dist/streaming/lod-scheduler.d.ts +32 -0
- package/dist/streaming/lod-source.d.ts +15 -9
- package/dist/streaming/streamed-splat-mesh.d.ts +38 -22
- package/dist/streaming.js +959 -927
- package/dist/streaming.js.map +1 -1
- package/dist/unified.js +17 -17
- package/package.json +1 -1
- package/dist/lod-scheduler-B0a_uBlv.js +0 -383
- package/dist/lod-scheduler-B0a_uBlv.js.map +0 -1
- package/dist/radix-sorter-BrbUg_CV.js +0 -178
- package/dist/radix-sorter-BrbUg_CV.js.map +0 -1
- package/dist/relighting-Tiwep8yd.js +0 -977
- package/dist/relighting-Tiwep8yd.js.map +0 -1
- package/dist/splat-mesh-CsLOQb08.js.map +0 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ renderer.setAnimationLoop(() => {
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
Supported formats: `.sog`, `.ply`, `.spz`, `.splat`, `.ksplat`, `.lcc`, `.lcc2`, `.rad
|
|
54
|
+
Supported formats: `.sog`, `.ply`, `.spz`, `.splat`, `.ksplat`, `.lcc`, `.lcc2`, `.rad`.
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
## Contributing
|
|
@@ -62,4 +62,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/architecture.md](docs/architect
|
|
|
62
62
|
|
|
63
63
|
[MIT](LICENSE). Third-party notices: [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
64
64
|
|
|
65
|
-
Made
|
|
65
|
+
Made by [Voluma](https://voluma.ai).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as THREE from 'three/webgpu';
|
|
2
2
|
import type { SplatSorter } from './sorter';
|
|
3
|
+
import type { SplatSortMetric } from './splat-mesh-types';
|
|
3
4
|
import type { uniformArray } from 'three/tsl';
|
|
4
5
|
/**
|
|
5
6
|
* Optional per-source world transform for a unified {@link MergedSplatMesh} pool.
|
|
@@ -78,7 +79,9 @@ export declare class ComputeSorter implements SplatSorter {
|
|
|
78
79
|
private readonly mirrors;
|
|
79
80
|
/** Set by {@link dispose}; makes a second dispose a no-op. */
|
|
80
81
|
private disposed;
|
|
81
|
-
/**
|
|
82
|
+
/** Rows of the model-view matrix used by the selected sort metric. */
|
|
83
|
+
private readonly viewRow0;
|
|
84
|
+
private readonly viewRow1;
|
|
82
85
|
private readonly viewRow2;
|
|
83
86
|
private readonly depthMin;
|
|
84
87
|
private readonly depthScale;
|
|
@@ -87,6 +90,7 @@ export declare class ComputeSorter implements SplatSorter {
|
|
|
87
90
|
/** Highest bucket index this sort uses; see {@link effectiveBucketCount}. */
|
|
88
91
|
private readonly bucketMax;
|
|
89
92
|
private readonly viewCenter;
|
|
93
|
+
private readonly sortMetric;
|
|
90
94
|
constructor(options: {
|
|
91
95
|
renderer: THREE.WebGPURenderer;
|
|
92
96
|
/** Pool capacity in splats; all buffers are sized once from this. */
|
|
@@ -103,6 +107,8 @@ export declare class ComputeSorter implements SplatSorter {
|
|
|
103
107
|
sourceIndexAttribute: THREE.StorageBufferAttribute;
|
|
104
108
|
/** Per-source world transform for a unified pool; omit for a single mesh. */
|
|
105
109
|
perSource?: PerSourceSortTransform;
|
|
110
|
+
/** Camera-space ordering key. Default `'depth'`. */
|
|
111
|
+
sortMetric?: SplatSortMetric;
|
|
106
112
|
});
|
|
107
113
|
/**
|
|
108
114
|
* Buckets to actually use for `activeCount` splats, rounded up to a power of
|
package/dist/core/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - `@voluma/vlam/effects` - tree-shakeable modifier presets
|
|
15
15
|
* - `@voluma/vlam/formats/ply` - 3DGS `.ply`, raw and compressed
|
|
16
16
|
* - `@voluma/vlam/formats/sog` - PlayCanvas SOG, bundled and unbundled
|
|
17
|
-
* - `@voluma/vlam/formats/rad` - Spark `.rad
|
|
17
|
+
* - `@voluma/vlam/formats/rad` - Spark `.rad`
|
|
18
18
|
* - `@voluma/vlam/formats/lcc` - XGRIDS LCC / `.lcc2` + collision helpers
|
|
19
19
|
* - `@voluma/vlam/formats/spz` - Niantic `.spz`
|
|
20
20
|
* - `@voluma/vlam/formats/splat` - antimatter15 `.splat`
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*
|
|
26
26
|
* @module core
|
|
27
27
|
*/
|
|
28
|
-
export { SplatMesh, MAX_SH_BANDS, DEFAULT_FOVEATION_TARGET_PX, DEFAULT_FOVEATION_DRAW_BUDGET, resolveSplatPerformanceProfile, type UnifiedSourceView, type SplatMeshOptions, type SplatUpdateOptions, type SplatSortStrategy, type SplatPerformanceProfile, type SplatFoveationMode, type SplatRange, type SplatPickOptions, type SplatPickResult, type SplatNearestResult, type SplatRayResult, type SplatHeightResult, type SplatChannelType, type SplatChannelOptions, } from './splat-mesh';
|
|
28
|
+
export { SplatMesh, MAX_SH_BANDS, DEFAULT_FOVEATION_TARGET_PX, DEFAULT_FOVEATION_DRAW_BUDGET, resolveSplatPerformanceProfile, type UnifiedSourceView, type SplatMeshOptions, type SplatUpdateOptions, type SplatSortStrategy, type SplatSortMetric, type SplatPerformanceProfile, type SplatFoveationMode, type SplatRange, type SplatPickOptions, type SplatPickResult, type SplatNearestResult, type SplatRayResult, type SplatHeightResult, type SplatChannelType, type SplatChannelOptions, } from './splat-mesh';
|
|
29
29
|
export { SplatPool, type SplatPoolOptions } from './splat-mesh-pool';
|
|
30
30
|
export { SPLAT_DATA_TEXTURE_WIDTH, deviceMaxTextureSize, assertPoolRowsFitDevice, } from './splat-mesh-pool';
|
|
31
31
|
export { MAX_DOF_RADIUS_PX, MAX_DOF_VARIANCE, apertureAngleFromSize, computeDofCocVariancePx2, computeDofOpacityFade, clampDepthOfFieldSettings, type DepthOfFieldSettings, } from './depth-of-field';
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as THREE from 'three/webgpu';
|
|
6
6
|
import type { SplatSorter } from './sorter';
|
|
7
|
+
import type { SplatSortMetric } from './splat-mesh-types';
|
|
7
8
|
/**
|
|
8
9
|
* Stable four-bit-per-pass WebGPU radix sorter.
|
|
9
10
|
*
|
|
@@ -22,6 +23,8 @@ export declare class RadixSorter implements SplatSorter {
|
|
|
22
23
|
private readonly mirrors;
|
|
23
24
|
/** Set by {@link dispose}; makes a second dispose a no-op. */
|
|
24
25
|
private disposed;
|
|
26
|
+
private readonly viewRow0;
|
|
27
|
+
private readonly viewRow1;
|
|
25
28
|
private readonly viewRow2;
|
|
26
29
|
private readonly depthMin;
|
|
27
30
|
private readonly depthScale;
|
|
@@ -29,6 +32,7 @@ export declare class RadixSorter implements SplatSorter {
|
|
|
29
32
|
private readonly viewCenter;
|
|
30
33
|
/** Exact mode avoids scene-bounds quantization entirely. */
|
|
31
34
|
private readonly exactDepth;
|
|
35
|
+
private readonly sortMetric;
|
|
32
36
|
constructor(options: {
|
|
33
37
|
renderer: THREE.WebGPURenderer;
|
|
34
38
|
capacity: number;
|
|
@@ -40,6 +44,8 @@ export declare class RadixSorter implements SplatSorter {
|
|
|
40
44
|
sourceIndexAttribute: THREE.StorageBufferAttribute;
|
|
41
45
|
/** Keep every Float32 depth bit instead of quantizing to 24 bits. */
|
|
42
46
|
exactDepth?: boolean;
|
|
47
|
+
/** Camera-space ordering key. Default `'depth'`. */
|
|
48
|
+
sortMetric?: SplatSortMetric;
|
|
43
49
|
});
|
|
44
50
|
sort(modelView: THREE.Matrix4, activeCount: number, bounds: THREE.Sphere): boolean;
|
|
45
51
|
dispose(): void;
|
|
@@ -21,6 +21,8 @@ export interface WriteMessage {
|
|
|
21
21
|
}
|
|
22
22
|
export interface SortMessage {
|
|
23
23
|
type: 'sort';
|
|
24
|
+
/** Camera-space ordering key. */
|
|
25
|
+
sortMetric: 'depth' | 'radial';
|
|
24
26
|
/** Column-major 4×4 model-view matrix elements. */
|
|
25
27
|
modelView: Float32Array;
|
|
26
28
|
/** Active ranges as (start, count) pairs of pool splat indices, in
|
package/dist/core/sorter.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ import type * as THREE from 'three/webgpu';
|
|
|
5
5
|
*
|
|
6
6
|
* - `ComputeSorter`: GPU counting sort in TSL compute (WebGPU backend);
|
|
7
7
|
* supports dynamic-capacity meshes via source-index indirection.
|
|
8
|
-
* - `WorkerSorter`: CPU
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the active spans.
|
|
8
|
+
* - `WorkerSorter`: stable CPU radix sort in a Web Worker (the WebGL2
|
|
9
|
+
* fallback and an explicit WebGPU stability option); handles static and
|
|
10
|
+
* dynamic-capacity meshes alike by mirroring the pool's centers and
|
|
11
|
+
* sorting the active spans.
|
|
12
12
|
* - `RadixSorter`: experimental GPU radix (opt-in via `sortStrategy: 'radix'`).
|
|
13
13
|
*/
|
|
14
14
|
export type SplatSorterKind = 'counting' | 'radix' | 'worker';
|
|
@@ -66,18 +66,33 @@ export interface SplatMeshOptions {
|
|
|
66
66
|
/**
|
|
67
67
|
* Minimum interval between WebGPU sorts while the camera moves. When
|
|
68
68
|
* omitted, the interval adapts to the active splat count. Use `0` to sort
|
|
69
|
-
* every changed frame. WebGL worker sorting is unaffected
|
|
69
|
+
* every changed frame. WebGL worker sorting is unaffected; a worker selected
|
|
70
|
+
* explicitly on WebGPU still observes this submission cadence.
|
|
70
71
|
*/
|
|
71
72
|
sortIntervalMs?: number;
|
|
72
73
|
/**
|
|
73
74
|
* WebGPU sorter used for A/B validation. Defaults to the proven counting
|
|
74
|
-
* sorter. `'
|
|
75
|
-
* stable
|
|
76
|
-
*
|
|
75
|
+
* sorter. `'worker'` keeps rendering on WebGPU but sorts asynchronously in
|
|
76
|
+
* the stable CPU worker also used by the WebGL fallback; this is useful for
|
|
77
|
+
* Spark-like temporal stability on captures with extreme position outliers.
|
|
78
|
+
* `'radix'` keeps the fast 24-bit GPU key path; `'exact'` lazy-loads a 32-bit
|
|
79
|
+
* Float32-depth GPU radix path. The first frames may skip GPU radix sorting
|
|
80
|
+
* until the module resolves.
|
|
77
81
|
*
|
|
78
82
|
* @experimental Radix strategies may change in a minor release.
|
|
79
83
|
*/
|
|
80
84
|
sortStrategy?: SplatSortStrategy;
|
|
85
|
+
/**
|
|
86
|
+
* Geometric key used to order transparent splats back-to-front.
|
|
87
|
+
*
|
|
88
|
+
* `'depth'` (default) sorts along the camera's view axis and gives the most
|
|
89
|
+
* accurate alpha order for a fixed view. `'radial'` sorts by distance from
|
|
90
|
+
* the camera, matching Spark's stable default: camera rotation alone leaves
|
|
91
|
+
* the order unchanged, which greatly reduces whole-scene shimmer while
|
|
92
|
+
* orbiting dense captures. Pair it with `sortStrategy: 'exact'` when extreme
|
|
93
|
+
* position outliers would make quantized buckets too coarse.
|
|
94
|
+
*/
|
|
95
|
+
sortMetric?: SplatSortMetric;
|
|
81
96
|
/**
|
|
82
97
|
* Render-quality policy. `smooth` rejects negligible projected contributions.
|
|
83
98
|
*
|
|
@@ -272,7 +287,9 @@ export interface SplatMeshOptions {
|
|
|
272
287
|
maxTextureSize?: number;
|
|
273
288
|
}
|
|
274
289
|
/** Available WebGPU depth-sort implementations. */
|
|
275
|
-
export type SplatSortStrategy = 'counting' | 'radix' | 'exact';
|
|
290
|
+
export type SplatSortStrategy = 'counting' | 'worker' | 'radix' | 'exact';
|
|
291
|
+
/** Camera-space key used for back-to-front splat ordering. */
|
|
292
|
+
export type SplatSortMetric = 'depth' | 'radial';
|
|
276
293
|
/** Controls optional work during a per-frame source update. */
|
|
277
294
|
export interface SplatUpdateOptions {
|
|
278
295
|
/** Leave sorting to {@link UnifiedSplatMesh}; uploads and LOD state still update. */
|
|
@@ -194,8 +194,10 @@ export declare class SplatMesh extends THREE.Mesh implements SplatPoolTenant {
|
|
|
194
194
|
* storage-attribute GPU buffers that never sat in a geometry. */
|
|
195
195
|
private lastRenderer;
|
|
196
196
|
private readonly currentModelView;
|
|
197
|
+
/** Pose components that can actually change the selected sort key. */
|
|
198
|
+
private readonly currentSortState;
|
|
197
199
|
/** Initialized to an impossible matrix so the first frame always sorts. */
|
|
198
|
-
private readonly
|
|
200
|
+
private readonly lastSortedState;
|
|
199
201
|
private readonly sortScheduler;
|
|
200
202
|
/** One-frame queue-headroom hint used before a staged atomic commit. */
|
|
201
203
|
private deferSortRequestOnce;
|
|
@@ -204,6 +206,7 @@ export declare class SplatMesh extends THREE.Mesh implements SplatPoolTenant {
|
|
|
204
206
|
/** The active list the current depth order was built from. */
|
|
205
207
|
private sortedActiveListVersion;
|
|
206
208
|
private readonly sortStrategy;
|
|
209
|
+
private readonly sortMetric;
|
|
207
210
|
/** Resolved only when `sortStrategy === 'radix'`; see {@link ensureRadixSorter}. */
|
|
208
211
|
private RadixSorterCtor;
|
|
209
212
|
private radixSorterLoad;
|
|
@@ -604,7 +607,7 @@ export declare class SplatMesh extends THREE.Mesh implements SplatPoolTenant {
|
|
|
604
607
|
renderView(camera: THREE.PerspectiveCamera, renderer: THREE.WebGPURenderer, target?: THREE.RenderTarget | null): void;
|
|
605
608
|
/**
|
|
606
609
|
* Sorts the shared order buffer for a secondary view's camera, bypassing the
|
|
607
|
-
* primary view's sort scheduler and its
|
|
610
|
+
* primary view's sort scheduler and its last-sorted pose record (that
|
|
608
611
|
* state belongs to `update()`'s camera). WebGPU dispatches synchronously into
|
|
609
612
|
* the render queue, so the following draw reads this order.
|
|
610
613
|
*/
|
|
@@ -722,6 +725,12 @@ export declare class SplatMesh extends THREE.Mesh implements SplatPoolTenant {
|
|
|
722
725
|
* order then changes without any camera motion.
|
|
723
726
|
*/
|
|
724
727
|
protected invalidateSort(): void;
|
|
728
|
+
/**
|
|
729
|
+
* Writes the camera/mesh state that can change the selected ordering key.
|
|
730
|
+
* Radial distance is invariant under camera rotation, so its state contains
|
|
731
|
+
* the mesh's world linear transform and camera-relative translation only.
|
|
732
|
+
*/
|
|
733
|
+
private writeSortState;
|
|
725
734
|
private createSorter;
|
|
726
735
|
/** Prefetches the experimental radix sorter; safe to call repeatedly. */
|
|
727
736
|
private ensureRadixSorter;
|
|
@@ -9,3 +9,20 @@ import type * as THREE from 'three/webgpu';
|
|
|
9
9
|
* compose into a shear.
|
|
10
10
|
*/
|
|
11
11
|
export declare function viewDepthRadius(modelView: THREE.Matrix4, radius: number): number;
|
|
12
|
+
/**
|
|
13
|
+
* A conservative camera-space radius for radial-distance quantization.
|
|
14
|
+
*
|
|
15
|
+
* Uses `sqrt(||A^T A||∞)`, an upper bound on the linear part's largest
|
|
16
|
+
* singular value. Unlike `Matrix4.getMaxScaleOnAxis()`, it cannot under-bound
|
|
17
|
+
* a sphere when a transformed hierarchy introduces shear.
|
|
18
|
+
*/
|
|
19
|
+
export declare function viewRadialRadius(modelView: THREE.Matrix4, radius: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Builds the pose signature relevant to radial sorting.
|
|
22
|
+
*
|
|
23
|
+
* World-space distance depends on the mesh's linear transform and its
|
|
24
|
+
* translation relative to the camera, but not on camera orientation. The
|
|
25
|
+
* scheduler compares this matrix so rotating in place does not dispatch an
|
|
26
|
+
* identical radial sort.
|
|
27
|
+
*/
|
|
28
|
+
export declare function radialSortState(meshWorld: THREE.Matrix4, cameraWorld: THREE.Matrix4, out: THREE.Matrix4): THREE.Matrix4;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type * as THREE from 'three/webgpu';
|
|
2
2
|
import type { SplatSorter } from './sorter';
|
|
3
|
+
import type { SplatSortMetric } from './splat-mesh-types';
|
|
3
4
|
/**
|
|
4
|
-
* CPU
|
|
5
|
-
*
|
|
6
|
-
* dynamic-capacity
|
|
7
|
-
* the pool's centers
|
|
5
|
+
* Stable CPU radix sorter in a Web Worker. Used by the WebGL2 fallback and,
|
|
6
|
+
* when explicitly selected, alongside WebGPU rendering for Spark-like sort
|
|
7
|
+
* cadence. Works for static and dynamic-capacity meshes alike: the worker
|
|
8
|
+
* keeps a mirror of the pool's centers and sorts only the active spans.
|
|
8
9
|
*
|
|
9
10
|
* One sort runs at a time; requests that arrive while the worker is busy
|
|
10
11
|
* are declined so the caller retries with the then-current camera on a
|
|
@@ -15,6 +16,7 @@ export declare class WorkerSorter implements SplatSorter {
|
|
|
15
16
|
private readonly worker;
|
|
16
17
|
private readonly splatIndexAttribute;
|
|
17
18
|
private readonly host;
|
|
19
|
+
private readonly sortMetric;
|
|
18
20
|
private inFlight;
|
|
19
21
|
/** Set by {@link dispose}; drops any already-delivered order message. */
|
|
20
22
|
private disposed;
|
|
@@ -25,7 +27,7 @@ export declare class WorkerSorter implements SplatSorter {
|
|
|
25
27
|
private lastSubmittedAt;
|
|
26
28
|
private lastCompletedAt;
|
|
27
29
|
private lastLatencyMs;
|
|
28
|
-
constructor(host: WorkerSorterHost);
|
|
30
|
+
constructor(host: WorkerSorterHost, sortMetric?: SplatSortMetric);
|
|
29
31
|
sort(modelView: THREE.Matrix4, _activeCount: number, _bounds: THREE.Sphere): boolean;
|
|
30
32
|
/** Internal timing diagnostics used by the demo's opt-in XR A/B harness. */
|
|
31
33
|
snapshot(): {
|