@voluma/vlam 0.2.2 → 0.2.4

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.
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Host-safe lighting-map pass for {@link SplatMesh.setRelighting}.
3
+ *
4
+ * The relight example is a sidecar `render(relightScene, camera)` into an RT.
5
+ * That only fills TSL `shadow()` maps when the renderer looks like a fresh
6
+ * `createSplatRenderer` (`autoClear` true, no tone-map wrap). Host apps often
7
+ * already own a `WebGPURenderer` with `autoClear: false` and an inline ACES /
8
+ * sRGB `contextNode`. This helper isolates those for one pass, then restores
9
+ * them, so the example works in a custom scene.
10
+ *
11
+ * Important: do **not** assign `contextNode = undefined`. WebGPURenderer reads
12
+ * `contextNode.id` while building render objects; clearing it throws and the
13
+ * lighting RT never fills.
14
+ */
15
+ import * as THREE from 'three/webgpu';
16
+ /**
17
+ * Minimal renderer surface {@link renderRelightingFactorMap} needs. A real
18
+ * `THREE.WebGPURenderer` satisfies this; tests can pass a stub.
19
+ */
20
+ export type RelightingFactorRenderer = {
21
+ autoClear: boolean;
22
+ shadowMap: {
23
+ enabled: boolean;
24
+ autoUpdate?: boolean;
25
+ };
26
+ getDrawingBufferSize(target: THREE.Vector2): THREE.Vector2;
27
+ getRenderTarget(): THREE.RenderTarget | null;
28
+ getActiveCubeFace(): number;
29
+ getActiveMipmapLevel(): number;
30
+ getMRT(): THREE.MRTNode | null;
31
+ setMRT(mrt: THREE.MRTNode | null): void;
32
+ setRenderTarget(target: THREE.RenderTarget | null, activeCubeFace?: number, activeMipmapLevel?: number): void;
33
+ getClearColor(target: THREE.Color): THREE.Color;
34
+ getClearAlpha(): number;
35
+ setClearColor(color: THREE.ColorRepresentation, alpha?: number): void;
36
+ clear(): void;
37
+ render(scene: THREE.Object3D, camera: THREE.Camera): void;
38
+ contextNode: unknown;
39
+ };
40
+ /**
41
+ * Renders `scene` from `camera` into `target` as a shadow-factor map:
42
+ * resizes to the drawing buffer, clears **white + A0**, forces `autoClear`
43
+ * and shadow maps on, and swaps in a passthrough `contextNode` so a host
44
+ * ACES/sRGB wrap cannot turn the linear multiplier into speckle.
45
+ *
46
+ * Call each frame **before** `splats.update` / the main splat draw. Restore
47
+ * is guaranteed even if `render` throws.
48
+ */
49
+ export declare function renderRelightingFactorMap(renderer: RelightingFactorRenderer, scene: THREE.Scene, camera: THREE.Camera, target: THREE.RenderTarget): void;
@@ -54,7 +54,7 @@ export declare function isClassicLccSwapSet(groups: readonly SwapGroup[]): boole
54
54
  */
55
55
  export declare function compareClassicSwapGroups(a: SwapGroup, b: SwapGroup): number;
56
56
  /** One classic-path chunk want, ranked before {@link StreamedSplatMesh} issues it. */
57
- export type ClassicFetchPhase = 'finest-target' | 'coverage' | 'target' | 'background';
57
+ export type ClassicFetchPhase = 'environment' | 'finest-target' | 'coverage' | 'target' | 'background';
58
58
  export interface ClassicFetchWant {
59
59
  /** Cross-mesh scheduler kind derived from {@link phase}. */
60
60
  kind: 'priority' | 'base';
@@ -173,9 +173,11 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
173
173
  * A one-minute watchdog also degrades if the cut cannot finish.
174
174
  * - `'hold-coverage'` (the default for `.lcc2` when unset): hide the mesh
175
175
  * until every in-view finest cell has a coarsest covering node resident
176
- * (any LOD). Does not wait for finest tiles or the rest of the stream.
177
- * An empty frustum falls back to the nearest cell. Requires
178
- * `LodSource.coverageRunsFor`; other formats treat this as disabled.
176
+ * (any LOD), and until the always-resident environment tile is in the pool
177
+ * when the scene ships one and it starts enabled. Does not wait for finest
178
+ * tiles or the rest of the stream. An empty frustum falls back to the
179
+ * nearest cell. Requires `LodSource.coverageRunsFor`; other formats treat
180
+ * this as disabled.
179
181
  *
180
182
  * A one-minute watchdog degrades to progressive if the frozen set cannot
181
183
  * finish. Does not make detail downloads instantaneous. Classic `.lcc` uses
@@ -899,6 +901,11 @@ export declare class StreamedSplatMesh extends SplatMesh {
899
901
  private captureOrContinueInitialReveal;
900
902
  /** After staging/commits, release the hold when every frozen run is resident. */
901
903
  private finishInitialRevealIfComplete;
904
+ /**
905
+ * Startup hold still needs the environment tile when the scene ships one
906
+ * and it starts enabled. Failed / unfit / disabled tiles do not block reveal.
907
+ */
908
+ private environmentPendingForReveal;
902
909
  /** Creates a marker for a changed streamed-LOD tick, if any. */
903
910
  private createPerformanceEvent;
904
911
  /** Returns whether all new rows can coexist with the currently visible region. */
@@ -949,8 +956,12 @@ export declare class StreamedSplatMesh extends SplatMesh {
949
956
  * it is wanted. The tile has no LOD ladder and no manifest count, so it is
950
957
  * appended whole (measuring its splat count at decode) and thereafter toggled
951
958
  * by flipping its pool range active - never scheduled, refetched, or evicted.
959
+ * When `pending` is supplied, a miss is ranked as an `'environment'` want so
960
+ * it issues ahead of LOD coverage.
952
961
  */
953
962
  private updateEnvironment;
963
+ /** Ranks the env tile ahead of every LOD want in {@link flushClassicFetches}. */
964
+ private enqueueEnvironmentFetch;
954
965
  /**
955
966
  * Page-table reschedule (`foveationMode: 'pagetable'`): posts the camera to the
956
967
  * worker, which owns the cache + traversal + pager and replies asynchronously
@@ -20,8 +20,21 @@ export declare class WorkerSorter implements SplatSorter {
20
20
  private disposed;
21
21
  /** The active spans the in-flight sort was computed against. */
22
22
  private sentSpans;
23
+ private submittedCount;
24
+ private completedCount;
25
+ private lastSubmittedAt;
26
+ private lastCompletedAt;
27
+ private lastLatencyMs;
23
28
  constructor(host: WorkerSorterHost);
24
29
  sort(modelView: THREE.Matrix4, _activeCount: number, _bounds: THREE.Sphere): boolean;
30
+ /** Internal timing diagnostics used by the demo's opt-in XR A/B harness. */
31
+ snapshot(): {
32
+ submittedCount: number;
33
+ completedCount: number;
34
+ lastSubmittedAt: number;
35
+ lastCompletedAt: number;
36
+ lastLatencyMs: number;
37
+ };
25
38
  dispose(): void;
26
39
  /** Sends written pool rows to keep the worker's centers mirror current. */
27
40
  private pushCenters;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voluma/vlam",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "VLAM! - A lightweight WebGPU Gaussian splat viewer for three.js, built for high performance, streaming LOD, and fully customizable rendering through an open shader pipeline.",
5
5
  "license": "MIT",
6
6
  "author": "Voluma",