@voluma/vlam 0.3.0 → 0.3.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.
Files changed (123) hide show
  1. package/README.md +2 -4
  2. package/dist/chunk-loader-DlNwggfG.js.map +1 -1
  3. package/dist/{index.d.ts → core/index.d.ts} +2 -2
  4. package/dist/{splat-budget.d.ts → core/splat-budget.d.ts} +1 -1
  5. package/dist/{splat-data.d.ts → core/splat-data.d.ts} +1 -1
  6. package/dist/{splat-mesh-types.d.ts → core/splat-mesh-types.d.ts} +5 -2
  7. package/dist/{effects.d.ts → effects/index.d.ts} +3 -3
  8. package/dist/effects.js.map +1 -1
  9. package/dist/formats/ksplat/parse-ksplat.d.ts +1 -1
  10. package/dist/formats/ksplat.js.map +1 -1
  11. package/dist/formats/lcc/collision-mesh.d.ts +2 -2
  12. package/dist/formats/lcc/collision-partition.d.ts +1 -1
  13. package/dist/formats/lcc/lcc.d.ts +3 -3
  14. package/dist/formats/lcc/lcc2.d.ts +2 -2
  15. package/dist/formats/lcc/parse-lcc.d.ts +1 -1
  16. package/dist/formats/lcc.js +276 -277
  17. package/dist/formats/lcc.js.map +1 -1
  18. package/dist/formats/ply/parse-compressed-ply.d.ts +2 -2
  19. package/dist/formats/ply/parse-splat-ply.d.ts +2 -2
  20. package/dist/formats/ply.js.map +1 -1
  21. package/dist/formats/rad/frontier-worker-protocol.d.ts +8 -1
  22. package/dist/formats/rad/index.d.ts +2 -2
  23. package/dist/formats/rad/parse-rad.d.ts +2 -2
  24. package/dist/formats/rad/rad-foveated-source.d.ts +3 -3
  25. package/dist/formats/rad/rad.d.ts +5 -5
  26. package/dist/formats/rad.js.map +1 -1
  27. package/dist/formats/sog/parse-sog.d.ts +2 -2
  28. package/dist/formats/sog.js.map +1 -1
  29. package/dist/formats/splat/parse-splat.d.ts +1 -1
  30. package/dist/formats/splat.js.map +1 -1
  31. package/dist/formats/spz/parse-spz.d.ts +1 -1
  32. package/dist/formats/spz.js.map +1 -1
  33. package/dist/half-float-Cs4FDq8Q.js.map +1 -1
  34. package/dist/index.js +3 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/{chunk-loader.d.ts → loaders/chunk-loader.d.ts} +2 -2
  37. package/dist/{load-splat-data.d.ts → loaders/load-splat-data.d.ts} +1 -1
  38. package/dist/{load-worker-protocol.d.ts → loaders/load-worker-protocol.d.ts} +2 -2
  39. package/dist/loaders.js.map +1 -1
  40. package/dist/loading-wLo8vRbA.js.map +1 -1
  41. package/dist/lod-scheduler-ChoZyEeq.js +466 -0
  42. package/dist/lod-scheduler-ChoZyEeq.js.map +1 -0
  43. package/dist/logging-BfPdd7NJ.js.map +1 -1
  44. package/dist/ply-header-B9WllbPg.js.map +1 -1
  45. package/dist/{radix-sorter-R0FCSqKu.js → radix-sorter-BrbUg_CV.js} +2 -2
  46. package/dist/radix-sorter-BrbUg_CV.js.map +1 -0
  47. package/dist/{relighting-CSQF3UcL.js → relighting-Tiwep8yd.js} +302 -294
  48. package/dist/relighting-Tiwep8yd.js.map +1 -0
  49. package/dist/{selection-volume.d.ts → selection/selection-volume.d.ts} +1 -1
  50. package/dist/{splat-partition.d.ts → selection/splat-partition.d.ts} +1 -1
  51. package/dist/selection.js.map +1 -1
  52. package/dist/sh-pack-D5wAe5gg.js.map +1 -1
  53. package/dist/splat-budget-DuVZspPQ.js.map +1 -1
  54. package/dist/splat-data-BZM5dhhx.js.map +1 -1
  55. package/dist/{splat-mesh-aQdcWA6v.js → splat-mesh-CsLOQb08.js} +3 -3
  56. package/dist/splat-mesh-CsLOQb08.js.map +1 -0
  57. package/dist/splat-mesh-types-BZIko-_9.js.map +1 -1
  58. package/dist/{static-lod-splat-mesh.d.ts → static-lod/static-lod-splat-mesh.d.ts} +2 -2
  59. package/dist/{static-lod-worker-protocol.d.ts → static-lod/static-lod-worker-protocol.d.ts} +1 -1
  60. package/dist/{static-lod.d.ts → static-lod/static-lod.d.ts} +1 -1
  61. package/dist/static-lod.js +1 -1
  62. package/dist/static-lod.js.map +1 -1
  63. package/dist/{dataset-source.d.ts → streaming/dataset-source.d.ts} +1 -1
  64. package/dist/{streaming.d.ts → streaming/index.d.ts} +3 -3
  65. package/dist/{lod-scheduler.d.ts → streaming/lod-scheduler.d.ts} +32 -0
  66. package/dist/{lod-source.d.ts → streaming/lod-source.d.ts} +19 -13
  67. package/dist/{streamed-splat-mesh-utils.d.ts → streaming/streamed-splat-mesh-utils.d.ts} +2 -2
  68. package/dist/{streamed-splat-mesh.d.ts → streaming/streamed-splat-mesh.d.ts} +83 -27
  69. package/dist/streaming.js +711 -645
  70. package/dist/streaming.js.map +1 -1
  71. package/dist/{unified-splat-mesh.d.ts → unified/unified-splat-mesh.d.ts} +13 -6
  72. package/dist/{work-buffer-gather.d.ts → unified/work-buffer-gather.d.ts} +5 -5
  73. package/dist/{work-buffer-material.d.ts → unified/work-buffer-material.d.ts} +1 -1
  74. package/dist/unified.js +280 -272
  75. package/dist/unified.js.map +1 -1
  76. package/dist/webgpu-limits-Y3CI_6_6.js.map +1 -1
  77. package/package.json +9 -9
  78. package/dist/lod-scheduler-B0a_uBlv.js +0 -383
  79. package/dist/lod-scheduler-B0a_uBlv.js.map +0 -1
  80. package/dist/radix-sorter-R0FCSqKu.js.map +0 -1
  81. package/dist/relighting-CSQF3UcL.js.map +0 -1
  82. package/dist/splat-mesh-aQdcWA6v.js.map +0 -1
  83. /package/dist/{compute-sorter.d.ts → core/compute-sorter.d.ts} +0 -0
  84. /package/dist/{create-splat-renderer.d.ts → core/create-splat-renderer.d.ts} +0 -0
  85. /package/dist/{depth-of-field.d.ts → core/depth-of-field.d.ts} +0 -0
  86. /package/dist/{half-float.d.ts → core/half-float.d.ts} +0 -0
  87. /package/dist/{logging.d.ts → core/logging.d.ts} +0 -0
  88. /package/dist/{merged-splat-mesh.d.ts → core/merged-splat-mesh.d.ts} +0 -0
  89. /package/dist/{orientation.d.ts → core/orientation.d.ts} +0 -0
  90. /package/dist/{radix-sort.d.ts → core/radix-sort.d.ts} +0 -0
  91. /package/dist/{radix-sorter.d.ts → core/radix-sorter.d.ts} +0 -0
  92. /package/dist/{relighting-pass.d.ts → core/relighting-pass.d.ts} +0 -0
  93. /package/dist/{relighting.d.ts → core/relighting.d.ts} +0 -0
  94. /package/dist/{sh-pack.d.ts → core/sh-pack.d.ts} +0 -0
  95. /package/dist/{sort-scheduler.d.ts → core/sort-scheduler.d.ts} +0 -0
  96. /package/dist/{sort-worker-protocol.d.ts → core/sort-worker-protocol.d.ts} +0 -0
  97. /package/dist/{sorter.d.ts → core/sorter.d.ts} +0 -0
  98. /package/dist/{source-transform.d.ts → core/source-transform.d.ts} +0 -0
  99. /package/dist/{splat-depth-pack.d.ts → core/splat-depth-pack.d.ts} +0 -0
  100. /package/dist/{splat-mesh-material.d.ts → core/splat-mesh-material.d.ts} +0 -0
  101. /package/dist/{splat-mesh-picking.d.ts → core/splat-mesh-picking.d.ts} +0 -0
  102. /package/dist/{splat-mesh-pool.d.ts → core/splat-mesh-pool.d.ts} +0 -0
  103. /package/dist/{splat-mesh.d.ts → core/splat-mesh.d.ts} +0 -0
  104. /package/dist/{splat-modifier-stack.d.ts → core/splat-modifier-stack.d.ts} +0 -0
  105. /package/dist/{splat-modifier.d.ts → core/splat-modifier.d.ts} +0 -0
  106. /package/dist/{splat-query.d.ts → core/splat-query.d.ts} +0 -0
  107. /package/dist/{splat-sort-bounds.d.ts → core/splat-sort-bounds.d.ts} +0 -0
  108. /package/dist/{storage-attribute-mirror.d.ts → core/storage-attribute-mirror.d.ts} +0 -0
  109. /package/dist/{webgpu-limits.d.ts → core/webgpu-limits.d.ts} +0 -0
  110. /package/dist/{worker-sorter.d.ts → core/worker-sorter.d.ts} +0 -0
  111. /package/dist/{xr-view.d.ts → core/xr-view.d.ts} +0 -0
  112. /package/dist/{loaders.d.ts → loaders/index.d.ts} +0 -0
  113. /package/dist/{loading.d.ts → loaders/loading.d.ts} +0 -0
  114. /package/dist/{ply-header.d.ts → loaders/ply-header.d.ts} +0 -0
  115. /package/dist/{selection.d.ts → selection/index.d.ts} +0 -0
  116. /package/dist/{static-lod-entry.d.ts → static-lod/index.d.ts} +0 -0
  117. /package/dist/{budget-governor.d.ts → streaming/budget-governor.d.ts} +0 -0
  118. /package/dist/{camera-budget-governor.d.ts → streaming/camera-budget-governor.d.ts} +0 -0
  119. /package/dist/{chunk-cache-budget.d.ts → streaming/chunk-cache-budget.d.ts} +0 -0
  120. /package/dist/{chunk-fetch-scheduler.d.ts → streaming/chunk-fetch-scheduler.d.ts} +0 -0
  121. /package/dist/{lod-manifest.d.ts → streaming/lod-manifest.d.ts} +0 -0
  122. /package/dist/{unified.d.ts → unified/index.d.ts} +0 -0
  123. /package/dist/{unified-work-buffer.d.ts → unified/unified-work-buffer.d.ts} +0 -0
package/dist/unified.js CHANGED
@@ -1,15 +1,15 @@
1
1
  var je = Object.defineProperty;
2
- var Oe = (r, n, e) => n in r ? je(r, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[n] = e;
3
- var s = (r, n, e) => Oe(r, typeof n != "symbol" ? n + "" : n, e);
2
+ var We = (t, n, e) => n in t ? je(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e;
3
+ var s = (t, n, e) => We(t, typeof n != "symbol" ? n + "" : n, e);
4
4
  import * as l from "three/webgpu";
5
- import { uniform as w, storage as C, Fn as we, If as ze, float as R, instanceIndex as ce, int as ve, ivec2 as We, textureLoad as ee, mat3 as Ae, vec3 as D, vec4 as M, bool as Ie, colorSpaceToWorking as Ne, varying as oe, positionGeometry as ge, modelViewMatrix as Ce, cameraProjectionMatrix as _e, mix as ae, vec2 as z, Discard as qe, texture as te, screenUV as re } from "three/tsl";
6
- import { S as ke, o as He, p as Ke, q as ne, s as Xe, t as Ye, d as Ze, u as $e, w as Qe, m as Je, b as et, D as tt, c as rt, W as st, C as it, i as ot, j as at, y as nt, r as ct } from "./relighting-CSQF3UcL.js";
7
- import { RadixSorter as lt } from "./radix-sorter-R0FCSqKu.js";
8
- import { i as ut } from "./splat-budget-DuVZspPQ.js";
9
- import { a as dt } from "./webgpu-limits-Y3CI_6_6.js";
10
- const ue = class ue {
5
+ import { uniform as x, storage as k, Fn as ye, If as ze, float as A, instanceIndex as ue, int as Se, ivec2 as Ie, textureLoad as ee, mat3 as Re, vec3 as R, vec4 as C, bool as Ne, colorSpaceToWorking as _e, varying as te, positionGeometry as we, modelViewMatrix as Ae, cameraProjectionMatrix as qe, mix as ce, vec2 as I, Discard as He, texture as re, screenUV as se } from "three/tsl";
6
+ import { S as De, o as Ke, p as Xe, q as le, s as Ye, t as Ze, d as $e, u as Qe, w as Je, m as et, b as tt, D as rt, c as st, W as it, C as ot, i as at, j as nt, y as ct, r as lt } from "./relighting-Tiwep8yd.js";
7
+ import { RadixSorter as ut } from "./radix-sorter-BrbUg_CV.js";
8
+ import { i as dt } from "./splat-budget-DuVZspPQ.js";
9
+ import { a as ht } from "./webgpu-limits-Y3CI_6_6.js";
10
+ const he = class he {
11
11
  constructor(n) {
12
- /** World-space center xyz; w is the drawable flag (1 draw, 0 modifier-hidden). */
12
+ /** World-space center xyz; w is display opacity (`visibility × source opacity ×` RAD modifier ratio). */
13
13
  s(this, "centers");
14
14
  /** Resolved color and opacity per work slot. */
15
15
  s(this, "colors");
@@ -23,8 +23,8 @@ const ue = class ue {
23
23
  s(this, "isotropicScreenRadius");
24
24
  s(this, "mirrors");
25
25
  this.capacity = n;
26
- const e = n + ue.SCRATCH_SLOTS;
27
- this.centers = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.colors = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.covarianceA = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.covarianceB = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.isotropicMix = new l.StorageBufferAttribute(new Float32Array(e), 1), this.isotropicScreenRadius = new l.StorageBufferAttribute(new Float32Array(e), 1), this.mirrors = new ke([
26
+ const e = n + he.SCRATCH_SLOTS;
27
+ this.centers = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.colors = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.covarianceA = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.covarianceB = new l.StorageBufferAttribute(new Float32Array(e * 4), 4), this.isotropicMix = new l.StorageBufferAttribute(new Float32Array(e), 1), this.isotropicScreenRadius = new l.StorageBufferAttribute(new Float32Array(e), 1), this.mirrors = new De([
28
28
  this.centers,
29
29
  this.colors,
30
30
  this.covarianceA,
@@ -57,9 +57,9 @@ const ue = class ue {
57
57
  * same, silently, and cannot disturb a drawn slot: admission never allocates
58
58
  * past `capacity` and the draw's `instanceCount` never covers it.
59
59
  */
60
- s(ue, "SCRATCH_SLOTS", 256);
61
- let le = ue;
62
- class ht {
60
+ s(he, "SCRATCH_SLOTS", 256);
61
+ let de = he;
62
+ class ft {
63
63
  constructor(n) {
64
64
  /** World-space `xyzw` center buffer, one element per unified work slot. */
65
65
  s(this, "centers");
@@ -73,92 +73,94 @@ class ht {
73
73
  /** Shared target for this source's gathered range. */
74
74
  s(this, "workBuffer");
75
75
  s(this, "capacity");
76
- s(this, "activeCount", w(0));
77
- s(this, "targetOffset", w(0));
78
- s(this, "sourceMatrix", w(new l.Matrix4()));
79
- s(this, "cameraViewMatrix", w(new l.Matrix4()));
80
- s(this, "opacity", w(1));
76
+ s(this, "activeCount", x(0));
77
+ s(this, "targetOffset", x(0));
78
+ s(this, "sourceMatrix", x(new l.Matrix4()));
79
+ s(this, "cameraViewMatrix", x(new l.Matrix4()));
80
+ s(this, "opacity", x(1));
81
81
  s(this, "pass");
82
82
  const {
83
83
  capacity: e,
84
- sourceCapacity: o,
84
+ sourceCapacity: i,
85
85
  sourceIndex: a,
86
86
  centersTexture: c,
87
- colorsTexture: g,
88
- covarianceATexture: b,
87
+ colorsTexture: S,
88
+ covarianceATexture: B,
89
89
  covarianceBTexture: u,
90
- dataTextureWidth: p
91
- } = n, T = n.sh ?? null, V = n.modifiers ?? [], P = n.channels ?? /* @__PURE__ */ new Map(), m = n.localCameraPosition ?? w(new l.Vector3());
92
- this.workBuffer = n.workBuffer ?? new le(e), this.capacity = this.workBuffer.capacity, this.centers = this.workBuffer.centers, this.colors = this.workBuffer.colors, this.covarianceA = this.workBuffer.covarianceA, this.covarianceB = this.workBuffer.covarianceB, this.isotropicMix = this.workBuffer.isotropicMix, this.isotropicScreenRadius = this.workBuffer.isotropicScreenRadius;
93
- const v = C(a, "uint", o), A = C(this.centers, "vec4", e), k = C(this.colors, "vec4", e), t = C(this.covarianceA, "vec4", e), i = C(this.covarianceB, "vec4", e), d = C(this.isotropicMix, "float", e), B = C(this.isotropicScreenRadius, "float", e);
94
- this.pass = we(() => {
95
- ze(R(ce).lessThan(this.activeCount), () => {
96
- const y = ve(v.element(ce)), f = We(
97
- y.mod(ve(p)),
98
- y.div(ve(p))
99
- ), S = ee(c, f).xyz, x = ce.add(this.targetOffset.toUint()), F = ee(b, f), U = ee(u, f), L = Ae(
100
- D(F.x, F.y, F.z),
101
- D(F.y, F.w, U.x),
102
- D(F.z, U.x, U.y)
103
- ), E = ee(g, f), W = T === null ? E : M(
104
- E.rgb.add(
105
- He(
106
- T,
90
+ dataTextureWidth: f
91
+ } = n, D = n.sh ?? null, V = n.modifiers ?? [], T = n.channels ?? /* @__PURE__ */ new Map(), y = n.localCameraPosition ?? x(new l.Vector3());
92
+ this.workBuffer = n.workBuffer ?? new de(e), this.capacity = this.workBuffer.capacity, this.centers = this.workBuffer.centers, this.colors = this.workBuffer.colors, this.covarianceA = this.workBuffer.covarianceA, this.covarianceB = this.workBuffer.covarianceB, this.isotropicMix = this.workBuffer.isotropicMix, this.isotropicScreenRadius = this.workBuffer.isotropicScreenRadius;
93
+ const p = k(a, "uint", i), M = k(this.centers, "vec4", e), P = k(this.colors, "vec4", e), r = k(this.covarianceA, "vec4", e), o = k(this.covarianceB, "vec4", e), d = k(this.isotropicMix, "float", e), w = k(this.isotropicScreenRadius, "float", e);
94
+ this.pass = ye(() => {
95
+ ze(A(ue).lessThan(this.activeCount), () => {
96
+ const b = Se(p.element(ue)), m = Ie(
97
+ b.mod(Se(f)),
98
+ b.div(Se(f))
99
+ ), g = ee(c, m).xyz, v = ue.add(this.targetOffset.toUint()), F = ee(B, m), G = ee(u, m), E = Re(
100
+ R(F.x, F.y, F.z),
101
+ R(F.y, F.w, G.x),
102
+ R(F.z, G.x, G.y)
103
+ ), L = ee(S, m), O = D === null ? L : C(
104
+ L.rgb.add(
105
+ Ke(
106
+ D,
107
107
  { covarianceBTexture: u },
108
- f,
109
- S.sub(m).normalize()
108
+ m,
109
+ g.sub(y).normalize()
110
110
  )
111
111
  ).clamp(0, 1),
112
- E.a
113
- ), j = this.sourceMatrix.mul(M(S, 1)).xyz, h = Ke(V, m, {
114
- index: y,
115
- localCenter: S,
116
- color: W,
117
- makeWorldCenter: () => j,
118
- makeViewCenter: () => this.cameraViewMatrix.mul(M(j, 1)).xyz,
112
+ L.a
113
+ ), W = this.sourceMatrix.mul(C(g, 1)).xyz, h = Xe(V, y, {
114
+ index: b,
115
+ localCenter: g,
116
+ color: O,
117
+ makeWorldCenter: () => W,
118
+ makeViewCenter: () => this.cameraViewMatrix.mul(C(W, 1)).xyz,
119
119
  makeNormal: () => {
120
- const G = L.inverse(), H = m.sub(S), ie = G.mul(G.mul(H)).normalize();
121
- return ie.mul(ie.dot(H).sign());
120
+ const U = E.inverse(), X = y.sub(g), ne = U.mul(U.mul(X)).normalize();
121
+ return ne.mul(ne.dot(X).sign());
122
122
  },
123
- makeChannel: (G) => {
124
- const H = P.get(G);
125
- if (!H)
123
+ makeChannel: (U) => {
124
+ const X = T.get(U);
125
+ if (!X)
126
126
  throw new Error(
127
- `UnifiedSplatMesh: source modifier reads undefined channel "${G}".`
127
+ `UnifiedSplatMesh: source modifier reads undefined channel "${U}".`
128
128
  );
129
- return ee(H.texture, f).r;
129
+ return ee(X.texture, m).r;
130
130
  }
131
- }), I = h.offset === null ? S : S.add(h.offset), N = h.visible === null ? Ie(!0) : h.visible, Z = this.sourceMatrix.mul(M(I, 1)).xyz;
132
- A.element(x).assign(M(Z, N.select(R(1), R(0))));
133
- const $ = n.srgbOutput ? h.color : ne(Ne(h.color, l.SRGBColorSpace)), de = n.lodAlpha ? ne($.a.mul(2)) : ne($.a);
134
- k.element(x).assign(M($.rgb, N.select(de.mul(this.opacity), R(0))));
135
- const se = h.rotation === null ? L : h.rotation.mul(L).mul(h.rotation.transpose());
136
- let K = ne(se);
131
+ }), j = h.offset === null ? g : g.add(h.offset), N = h.visible === null ? Ne(!0) : h.visible, _ = this.sourceMatrix.mul(C(j, 1)).xyz, q = le(O.a), fe = le(h.color.a), ie = N.select(A(1), A(0)), Y = n.srgbOutput ? h.color : le(_e(h.color, l.SRGBColorSpace));
132
+ if (n.lodAlpha) {
133
+ const U = q.greaterThan(0).select(fe.div(q.max(1e-8)), A(1));
134
+ M.element(v).assign(C(_, ie.mul(this.opacity).mul(U))), P.element(v).assign(C(Y.rgb, q.mul(2)));
135
+ } else
136
+ M.element(v).assign(C(_, ie.mul(this.opacity))), P.element(v).assign(C(Y.rgb, Y.a));
137
+ const oe = h.rotation === null ? E : h.rotation.mul(E).mul(h.rotation.transpose());
138
+ let z = le(oe);
137
139
  if (h.isotropicCovarianceMix !== null) {
138
- const G = h.isotropicVarianceScale ?? R(Xe);
139
- K = Ye(
140
- K,
141
- D(0, 0, 1),
140
+ const U = h.isotropicVarianceScale ?? A(Ye);
141
+ z = Ze(
142
+ z,
143
+ R(0, 0, 1),
142
144
  h.isotropicCovarianceMix,
143
- G
145
+ U
144
146
  );
145
147
  }
146
- const _ = this.sourceMatrix.toMat3(), X = _.mul(K).mul(_.transpose()), O = h.scaleSquared === null ? X : X.mul(h.scaleSquared), q = O.mul(D(1, 0, 0)), Q = O.mul(D(0, 1, 0)), he = O.mul(D(0, 0, 1));
147
- t.element(x).assign(M(q.x, q.y, q.z, Q.y)), i.element(x).assign(M(Q.z, he.z, 0, 0)), d.element(x).assign(h.isotropicCovarianceMix === null ? R(0) : h.isotropicCovarianceMix), B.element(x).assign(
148
- h.isotropicCovarianceMix === null ? R(0) : h.isotropicScreenRadiusPx ?? R(0)
148
+ const Z = this.sourceMatrix.toMat3(), H = Z.mul(z).mul(Z.transpose()), K = h.scaleSquared === null ? H : H.mul(h.scaleSquared), $ = K.mul(R(1, 0, 0)), ae = K.mul(R(0, 1, 0)), pe = K.mul(R(0, 0, 1));
149
+ r.element(v).assign(C($.x, $.y, $.z, ae.y)), o.element(v).assign(C(ae.z, pe.z, 0, 0)), d.element(v).assign(h.isotropicCovarianceMix === null ? A(0) : h.isotropicCovarianceMix), w.element(v).assign(
150
+ h.isotropicCovarianceMix === null ? A(0) : h.isotropicScreenRadiusPx ?? A(0)
149
151
  );
150
152
  });
151
- })().compute(o, [256]);
153
+ })().compute(i, [256]);
152
154
  }
153
155
  /** Gathers a source's active pool slots into a contiguous work-buffer range. */
154
- gather(n, e, o, a, c = new l.Matrix4(), g = 1) {
155
- if (e < 0 || o < 0 || o + e > this.capacity)
156
+ gather(n, e, i, a, c = new l.Matrix4(), S = 1) {
157
+ if (e < 0 || i < 0 || i + e > this.capacity)
156
158
  throw new Error("WorkBufferGather: requested range exceeds work-buffer capacity.");
157
- this.activeCount.value = e, this.targetOffset.value = o, this.sourceMatrix.value.copy(a);
158
- const b = typeof c == "number" ? new l.Matrix4() : c;
159
- this.cameraViewMatrix.value.copy(b), this.opacity.value = Math.max(
159
+ this.activeCount.value = e, this.targetOffset.value = i, this.sourceMatrix.value.copy(a);
160
+ const B = typeof c == "number" ? new l.Matrix4() : c;
161
+ this.cameraViewMatrix.value.copy(B), this.opacity.value = Math.max(
160
162
  0,
161
- typeof c == "number" ? c : g
163
+ typeof c == "number" ? c : S
162
164
  ), this.pass.count = e, n.compute(this.pass), this.workBuffer.releaseCpuMirrors(n);
163
165
  }
164
166
  /**
@@ -187,112 +189,112 @@ class ht {
187
189
  this.pass.dispose();
188
190
  }
189
191
  }
190
- function Pe(r) {
191
- const n = new l.NodeMaterial(), e = C(r.centers, "vec4", r.capacity), o = C(r.order, "float", r.capacity), a = C(r.colors, "vec4", r.capacity), c = C(r.covarianceA, "vec4", r.capacity), g = C(r.covarianceB, "vec4", r.capacity), b = C(r.isotropicMix, "float", r.capacity), u = C(r.isotropicScreenRadius, "float", r.capacity), p = oe(M(1, 1, 1, 1), "vWorkColor"), T = oe(ge.xy, "vWorkQuadPosition"), V = oe(R(1), "vWorkOpacityCompensation"), P = oe(R(0), "vWorkAdjustedStdDev");
192
- return n.vertexNode = we(() => {
193
- const m = o.element(ce).toInt(), v = e.element(m), A = v.xyz, k = v.w.greaterThan(0.5);
194
- p.assign(a.element(m));
195
- const t = Ce.mul(M(A, 1)).toVar(), i = _e.mul(t).toVar(), d = c.element(m), B = g.element(m), y = Ae(
196
- D(d.x, d.y, d.z),
197
- D(d.y, d.w, B.x),
198
- D(d.z, B.x, B.y)
199
- ), f = R(1).div(t.z), S = f.mul(f), x = D(
200
- r.focal.x.mul(f),
192
+ function ke(t) {
193
+ const n = new l.NodeMaterial(), e = k(t.centers, "vec4", t.capacity), i = k(t.order, "float", t.capacity), a = k(t.colors, "vec4", t.capacity), c = k(t.covarianceA, "vec4", t.capacity), S = k(t.covarianceB, "vec4", t.capacity), B = k(t.isotropicMix, "float", t.capacity), u = k(t.isotropicScreenRadius, "float", t.capacity), f = te(C(1, 1, 1, 1), "vWorkColor"), D = te(we.xy, "vWorkQuadPosition"), V = te(A(1), "vWorkOpacityCompensation"), T = te(A(1), "vWorkDisplayOpacity"), y = te(A(0), "vWorkAdjustedStdDev");
194
+ return n.vertexNode = ye(() => {
195
+ const p = i.element(ue).toInt(), M = e.element(p), P = M.xyz, r = M.w.greaterThan(0);
196
+ T.assign(M.w), f.assign(a.element(p));
197
+ const o = Ae.mul(C(P, 1)).toVar(), d = qe.mul(o).toVar(), w = c.element(p), b = S.element(p), m = Re(
198
+ R(w.x, w.y, w.z),
199
+ R(w.y, w.w, b.x),
200
+ R(w.z, b.x, b.y)
201
+ ), g = A(1).div(o.z), v = g.mul(g), F = R(
202
+ t.focal.x.mul(g),
201
203
  0,
202
- r.focal.x.negate().mul(t.x).mul(S)
203
- ), F = D(
204
+ t.focal.x.negate().mul(o.x).mul(v)
205
+ ), G = R(
204
206
  0,
205
- r.focal.y.mul(f),
206
- r.focal.y.negate().mul(t.y).mul(S)
207
- ), U = Ce.toMat3().transpose(), L = U.mul(x), E = U.mul(F), W = L.dot(y.mul(L)), j = E.dot(y.mul(E)), h = L.dot(y.mul(E)), I = t.z.negate().max(1e-4), N = r.dofFocusDistance.max(1e-4), Z = r.dofAperture.max(0).mul(0.5).div(N).atan(), $ = I.sub(N).abs().div(I), de = r.focal.x.mul(Z.tan()), se = $.mul(de), K = se.mul(se).min(R(Ze)), _ = W.add(r.projectedLowPassVariance).add(K), X = j.add(r.projectedLowPassVariance).add(K), O = h, q = b.element(m), Q = _.mul(X).sub(O.mul(O)).max(1e-9), he = W.mul(j).sub(h.mul(h)).max(0), G = W.add(r.projectedLowPassVariance).mul(j.add(r.projectedLowPassVariance)).sub(h.mul(h)).max(1e-9), H = he.div(Q).sqrt(), ie = G.div(Q).sqrt(), De = r.antialias.max(r.compensateProjectedLowPass), Te = ae(ie, H, De);
208
- V.assign(ae(Te, R(1), q));
209
- const xe = _.add(X).mul(0.5), ye = z(_.sub(X).mul(0.5), O).length();
210
- let Y = xe.add(ye), J = xe.sub(ye).max(0);
211
- const be = $e(Y, J, q);
212
- Y = be.lambda1, J = be.lambda2;
213
- const Be = Qe(
214
- Y,
207
+ t.focal.y.mul(g),
208
+ t.focal.y.negate().mul(o.y).mul(v)
209
+ ), E = Ae.toMat3().transpose(), L = E.mul(F), O = E.mul(G), W = L.dot(m.mul(L)), h = O.dot(m.mul(O)), j = L.dot(m.mul(O)), N = o.z.negate().max(1e-4), _ = t.dofFocusDistance.max(1e-4), q = t.dofAperture.max(0).mul(0.5).div(_).atan(), fe = N.sub(_).abs().div(N), ie = t.focal.x.mul(q.tan()), Y = fe.mul(ie), oe = Y.mul(Y).min(A($e)), z = W.add(t.projectedLowPassVariance).add(oe), Z = h.add(t.projectedLowPassVariance).add(oe), H = j, K = B.element(p), $ = z.mul(Z).sub(H.mul(H)).max(1e-9), ae = W.mul(h).sub(j.mul(j)).max(0), pe = W.add(t.projectedLowPassVariance).mul(h.add(t.projectedLowPassVariance)).sub(j.mul(j)).max(1e-9), U = ae.div($).sqrt(), X = pe.div($).sqrt(), ne = t.antialias.max(t.compensateProjectedLowPass), Fe = ce(X, U, ne);
210
+ V.assign(ce(Fe, A(1), K));
211
+ const be = z.add(Z).mul(0.5), Be = I(z.sub(Z).mul(0.5), H).length();
212
+ let Q = be.add(Be), J = be.sub(Be).max(0);
213
+ const Me = Qe(Q, J, K);
214
+ Q = Me.lambda1, J = Me.lambda2;
215
+ const Ce = Je(
216
+ Q,
215
217
  J,
216
- q,
217
- u.element(m),
218
- r.maxStdDev
218
+ K,
219
+ u.element(p),
220
+ t.maxStdDev
219
221
  );
220
- Y = Be.lambda1, J = Be.lambda2;
221
- const Fe = p.a.mul(4).sub(3).min(5), fe = p.a.greaterThan(1).select(r.maxStdDev.add(Fe.sub(1).mul(0.7)), r.maxStdDev);
222
- P.assign(fe);
223
- const pe = z(O, Y.sub(_)).add(z(1e-6, 0)).normalize(), Me = r.minSplatSizePx, Le = pe.mul(Y.sqrt().mul(fe).min(1024).max(Me)), Ue = z(pe.y, pe.x.negate()).mul(
224
- J.sqrt().mul(fe).min(1024).max(Me)
225
- ), Ee = Le.mul(ge.x).add(Ue.mul(ge.y)), Ve = i.xy.div(i.w), Ge = M(
226
- Ve.add(Ee.mul(2).div(r.viewport)),
227
- i.z.div(i.w),
222
+ Q = Ce.lambda1, J = Ce.lambda2;
223
+ const Le = f.a.mul(4).sub(3).min(5), me = f.a.greaterThan(1).select(t.maxStdDev.add(Le.sub(1).mul(0.7)), t.maxStdDev);
224
+ y.assign(me);
225
+ const ve = I(H, Q.sub(z)).add(I(1e-6, 0)).normalize(), Pe = t.minSplatSizePx, Ue = ve.mul(Q.sqrt().mul(me).min(1024).max(Pe)), Ee = I(ve.y, ve.x.negate()).mul(
226
+ J.sqrt().mul(me).min(1024).max(Pe)
227
+ ), Ve = Ue.mul(we.x).add(Ee.mul(we.y)), Ge = d.xy.div(d.w), Oe = C(
228
+ Ge.add(Ve.mul(2).div(t.viewport)),
229
+ d.z.div(d.w),
228
230
  1
229
- ), me = i.w.mul(1.2);
230
- return i.z.greaterThan(me.negate()).and(i.x.abs().lessThan(me)).and(i.y.abs().lessThan(me)).and(k).select(Ge, M(0, 0, 2, 1));
231
- })(), n.fragmentNode = we(() => {
232
- const m = T.dot(T);
233
- qe(m.greaterThan(1));
234
- const v = m.mul(P.mul(P).mul(-0.5)).exp(), A = p.a.mul(4).sub(3).min(5), k = A.mul(A).sub(1).mul(1 / Math.E).exp(), t = v.oneMinus().pow(k).oneMinus(), d = p.a.greaterThan(1).select(t, v.mul(p.a)).mul(V), B = te(r.relightMap, re), y = r.relightSoftness.div(r.viewport.x.max(1)), f = r.relightSoftness.div(r.viewport.y.max(1)), S = B, x = te(r.relightMap, re.add(z(y, 0))), F = te(r.relightMap, re.add(z(y.negate(), 0))), U = te(r.relightMap, re.add(z(0, f))), L = te(r.relightMap, re.add(z(0, f.negate()))), E = S.a.add(x.a).add(F.a).add(U.a).add(L.a).max(1e-4), W = S.rgb.mul(S.a).add(x.rgb.mul(x.a)).add(F.rgb.mul(F.a)).add(U.rgb.mul(U.a)).add(L.rgb.mul(L.a)).div(E), j = E.mul(0.2), h = M(W, j), I = r.relightSoftness.greaterThan(0.5).select(h, B), N = ae(
235
- D(r.relightBackground),
236
- I.rgb.mul(r.relightBrightness),
237
- I.a
238
- ), Z = ae(p.rgb, p.rgb.mul(N), r.relightBlend);
239
- return M(Z.mul(d), d);
231
+ ), ge = d.w.mul(1.2);
232
+ return d.z.greaterThan(ge.negate()).and(d.x.abs().lessThan(ge)).and(d.y.abs().lessThan(ge)).and(r).select(Oe, C(0, 0, 2, 1));
233
+ })(), n.fragmentNode = ye(() => {
234
+ const p = D.dot(D);
235
+ He(p.greaterThan(1));
236
+ const M = p.mul(y.mul(y).mul(-0.5)).exp(), P = f.a.mul(4).sub(3).min(5), r = P.mul(P).sub(1).mul(1 / Math.E).exp(), o = M.oneMinus().pow(r).oneMinus(), w = f.a.greaterThan(1).select(o, M.mul(f.a)).mul(V).mul(T), b = re(t.relightMap, se), m = t.relightSoftness.div(t.viewport.x.max(1)), g = t.relightSoftness.div(t.viewport.y.max(1)), v = b, F = re(t.relightMap, se.add(I(m, 0))), G = re(t.relightMap, se.add(I(m.negate(), 0))), E = re(t.relightMap, se.add(I(0, g))), L = re(t.relightMap, se.add(I(0, g.negate()))), O = v.a.add(F.a).add(G.a).add(E.a).add(L.a).max(1e-4), W = v.rgb.mul(v.a).add(F.rgb.mul(F.a)).add(G.rgb.mul(G.a)).add(E.rgb.mul(E.a)).add(L.rgb.mul(L.a)).div(O), h = O.mul(0.2), j = C(W, h), N = t.relightSoftness.greaterThan(0.5).select(j, b), _ = ce(
237
+ R(t.relightBackground),
238
+ N.rgb.mul(t.relightBrightness),
239
+ N.a
240
+ ), q = ce(f.rgb, f.rgb.mul(_), t.relightBlend);
241
+ return C(q.mul(w), w);
240
242
  })(), n.transparent = !0, n.depthTest = !0, n.depthWrite = !1, n.side = l.DoubleSide, n.blending = l.CustomBlending, n.blendSrc = l.OneFactor, n.blendDst = l.OneMinusSrcAlphaFactor, n.blendSrcAlpha = l.OneFactor, n.blendDstAlpha = l.OneMinusSrcAlphaFactor, n.toneMapped = !1, n;
241
243
  }
242
- const ft = 16, pt = 72;
243
- function Re(r) {
244
- if (!Number.isFinite(r) || r < 0)
244
+ const pt = 16, mt = 72;
245
+ function Te(t) {
246
+ if (!Number.isFinite(t) || t < 0)
245
247
  throw new RangeError("Splat capacity must be a non-negative finite number.");
246
248
  }
247
- function mt(r) {
248
- return Re(r), Math.floor(r) * ft;
249
+ function vt(t) {
250
+ return Te(t), Math.floor(t) * pt;
249
251
  }
250
- function vt(r) {
251
- return Re(r), Math.floor(r) * pt;
252
+ function gt(t) {
253
+ return Te(t), Math.floor(t) * mt;
252
254
  }
253
- function Mt(r) {
254
- return vt(r) * 2;
255
+ function Ct(t) {
256
+ return gt(t) * 2;
255
257
  }
256
- function Se(r) {
258
+ function xe(t) {
257
259
  var n;
258
- return ((n = r.backend) == null ? void 0 : n.isWebGPUBackend) === !0;
260
+ return ((n = t.backend) == null ? void 0 : n.isWebGPUBackend) === !0;
259
261
  }
260
- class Ct extends l.Mesh {
261
- constructor(e, o, a = {}) {
262
- if (!Se(e))
262
+ class Pt extends l.Mesh {
263
+ constructor(e, i, a = {}) {
264
+ if (!xe(e))
263
265
  throw new Error(
264
266
  "UnifiedSplatMesh requires a WebGPU backend (renderer.backend.isWebGPUBackend). On WebGL2 use standalone SplatMesh draws or static MergedSplatMesh."
265
267
  );
266
- dt(e, mt(o), o);
267
- const c = new le(o), g = w(new l.Vector2()), b = w(new l.Vector2()), u = w(3), p = w(0), T = w(0), V = w(0.3), P = w(0), m = w(10), v = w(0), A = Je(), k = w(0), t = w(et), i = w(tt), d = w(rt), B = new l.StorageInstancedBufferAttribute(new Float32Array(o), 1), y = new l.InstancedBufferGeometry();
268
- y.setIndex([0, 1, 2, 0, 2, 3]), y.setAttribute(
268
+ ht(e, vt(i), i);
269
+ const c = new de(i), S = x(new l.Vector2()), B = x(new l.Vector2()), u = x(3), f = x(0), D = x(0), V = x(0.3), T = x(0), y = x(10), p = x(0), M = et(), P = x(0), r = x(tt), o = x(rt), d = x(st), w = new l.StorageInstancedBufferAttribute(new Float32Array(i), 1), b = new l.InstancedBufferGeometry();
270
+ b.setIndex([0, 1, 2, 0, 2, 3]), b.setAttribute(
269
271
  "position",
270
272
  new l.BufferAttribute(new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0]), 3)
271
- ), y.instanceCount = 0;
273
+ ), b.instanceCount = 0;
272
274
  super(
273
- y,
274
- Pe({
275
- capacity: o,
275
+ b,
276
+ ke({
277
+ capacity: i,
276
278
  centers: c.centers,
277
279
  colors: c.colors,
278
280
  covarianceA: c.covarianceA,
279
281
  covarianceB: c.covarianceB,
280
282
  isotropicMix: c.isotropicMix,
281
283
  isotropicScreenRadius: c.isotropicScreenRadius,
282
- order: B,
283
- focal: g,
284
- viewport: b,
284
+ order: w,
285
+ focal: S,
286
+ viewport: B,
285
287
  maxStdDev: u,
286
- minSplatSizePx: p,
287
- antialias: T,
288
+ minSplatSizePx: f,
289
+ antialias: D,
288
290
  projectedLowPassVariance: V,
289
- compensateProjectedLowPass: P,
290
- dofFocusDistance: m,
291
- dofAperture: v,
292
- relightMap: A,
293
- relightBlend: k,
294
- relightBrightness: t,
295
- relightBackground: i,
291
+ compensateProjectedLowPass: T,
292
+ dofFocusDistance: y,
293
+ dofAperture: p,
294
+ relightMap: M,
295
+ relightBlend: P,
296
+ relightBrightness: r,
297
+ relightBackground: o,
296
298
  relightSoftness: d
297
299
  })
298
300
  );
@@ -359,26 +361,26 @@ class Ct extends l.Mesh {
359
361
  s(this, "overflowedSourceCount", 0);
360
362
  s(this, "overflowedSplatCount", 0);
361
363
  s(this, "disposed", !1);
362
- const f = new Uint32Array(o);
363
- for (let x = 0; x < o; x++) f[x] = x;
364
- this.workBuffer = c, this.focal = g, this.viewport = b, this.maxStdDev = u, this.minSplatSizePx = p, this.antialias = T, this.projectedLowPassVariance = V, this.compensateProjectedLowPass = P, this.dofFocusDistance = m, this.dofAperture = v, this.relightPlaceholder = A, this.relightMap = A, this.relightBlend = k, this.relightBrightness = t, this.relightBackground = i, this.relightSoftness = d, this.srgbOutput = a.srgbOutput ?? !1, this.sortScheduler = new st(void 0, ut()), this.orderAttribute = B, this.workSourceIndex = new l.StorageBufferAttribute(f, 1), this.mirrors = new ke([this.workSourceIndex, this.orderAttribute]), this.renderer = e;
365
- const S = {
364
+ const m = new Uint32Array(i);
365
+ for (let v = 0; v < i; v++) m[v] = v;
366
+ this.workBuffer = c, this.focal = S, this.viewport = B, this.maxStdDev = u, this.minSplatSizePx = f, this.antialias = D, this.projectedLowPassVariance = V, this.compensateProjectedLowPass = T, this.dofFocusDistance = y, this.dofAperture = p, this.relightPlaceholder = M, this.relightMap = M, this.relightBlend = P, this.relightBrightness = r, this.relightBackground = o, this.relightSoftness = d, this.srgbOutput = a.srgbOutput ?? !1, this.sortScheduler = new it(void 0, dt()), this.orderAttribute = w, this.workSourceIndex = new l.StorageBufferAttribute(m, 1), this.mirrors = new De([this.workSourceIndex, this.orderAttribute]), this.renderer = e;
367
+ const g = {
366
368
  renderer: e,
367
- capacity: o,
369
+ capacity: i,
368
370
  centersBuffer: c.centers,
369
- splatIndexAttribute: B,
371
+ splatIndexAttribute: w,
370
372
  sourceIndexAttribute: this.workSourceIndex
371
373
  };
372
- this.sorter = a.sortStrategy === "exact" ? new lt({ ...S, exactDepth: !0 }) : new it(S), this.frustumCulled = !1, this.matrixAutoUpdate = !1, this.matrix.identity(), this.matrixWorld.identity();
374
+ this.sorter = a.sortStrategy === "exact" ? new ut({ ...g, exactDepth: !0 }) : new ot(g), this.frustumCulled = !1, this.matrixAutoUpdate = !1, this.matrix.identity(), this.matrixWorld.identity();
373
375
  }
374
376
  /** Fixed work-buffer splat capacity chosen at construction. */
375
377
  get capacity() {
376
378
  return this.workBuffer.capacity;
377
379
  }
378
380
  /** Registers a source. The caller keeps ownership and may still query it. */
379
- addSource(e, o = {}) {
380
- if (this.assertNotDisposed("addSource"), this.sources.some((g) => g.source === e)) return;
381
- const a = e.getUnifiedSourceView(), c = o.visible ?? e.visible;
381
+ addSource(e, i = {}) {
382
+ if (this.assertNotDisposed("addSource"), this.sources.some((S) => S.source === e)) return;
383
+ const a = e.getUnifiedSourceView(), c = i.visible ?? e.visible;
382
384
  if (a.hasSourcePlacement)
383
385
  throw new Error(
384
386
  "UnifiedSplatMesh: a MergedSplatMesh is already a unified pool with its own global sort; add its sources individually, or draw the mesh directly."
@@ -399,18 +401,18 @@ class Ct extends l.Mesh {
399
401
  throw new Error("UnifiedSplatMesh: every source must use the same antialias setting.");
400
402
  if (this.sourceProjectedFilterProfile === null) {
401
403
  this.sourceProjectedFilterProfile = a.projectedFilterProfile;
402
- const g = a.projectedFilterProfile === "lcc";
403
- this.projectedLowPassVariance.value = g ? 0.1 : 0.3, this.compensateProjectedLowPass.value = g ? 1 : 0;
404
+ const S = a.projectedFilterProfile === "lcc";
405
+ this.projectedLowPassVariance.value = S ? 0.1 : 0.3, this.compensateProjectedLowPass.value = S ? 1 : 0;
404
406
  } else if (this.sourceProjectedFilterProfile !== a.projectedFilterProfile)
405
407
  throw new Error("UnifiedSplatMesh: every source must use the same projected filter profile.");
406
408
  this.sources.push({
407
409
  source: e,
408
410
  gather: this.createGather(a),
409
411
  graphRevision: a.graphRevision,
410
- priority: o.priority ?? 0,
411
- opacity: o.opacity ?? 1,
412
+ priority: i.priority ?? 0,
413
+ opacity: i.opacity ?? 1,
412
414
  visible: c,
413
- cacheModifiers: o.cacheModifiers ?? !1,
415
+ cacheModifiers: i.cacheModifiers ?? !1,
414
416
  originalVisible: e.visible,
415
417
  lastGather: null,
416
418
  view: null,
@@ -428,8 +430,8 @@ class Ct extends l.Mesh {
428
430
  */
429
431
  invalidateSource(e) {
430
432
  this.assertNotDisposed("invalidateSource");
431
- const o = this.sources.find((a) => a.source === e);
432
- return o ? (o.lastGather = null, !0) : !1;
433
+ const i = this.sources.find((a) => a.source === e);
434
+ return i ? (i.lastGather = null, !0) : !1;
433
435
  }
434
436
  /** Number of whole sources omitted in the most recent update due to capacity. */
435
437
  get droppedSourceCount() {
@@ -439,19 +441,25 @@ class Ct extends l.Mesh {
439
441
  get droppedSplatCount() {
440
442
  return this.overflowedSplatCount;
441
443
  }
442
- /** Updates a source's resolved opacity without rebuilding its gather pipeline. */
443
- setSourceOpacity(e, o) {
444
+ /**
445
+ * Sets whole-source display opacity without rebuilding the gather pipeline.
446
+ *
447
+ * This scales the completed fragment after RAD merged-vs-leaf classification
448
+ * and falloff. It must never alter LOD selection or splat shape; hosts such as
449
+ * marker crossfades rely on that. Values `<= 0` skip drawing the source.
450
+ */
451
+ setSourceOpacity(e, i) {
444
452
  this.assertNotDisposed("setSourceOpacity");
445
453
  const a = this.sources.find((c) => c.source === e);
446
454
  if (!a) throw new Error("UnifiedSplatMesh: source is not registered.");
447
- a.opacity = o;
455
+ a.opacity = i;
448
456
  }
449
457
  /** Shows or hides a source without changing its residency. */
450
- setSourceVisible(e, o) {
458
+ setSourceVisible(e, i) {
451
459
  this.assertNotDisposed("setSourceVisible");
452
460
  const a = this.sources.find((c) => c.source === e);
453
461
  if (!a) throw new Error("UnifiedSplatMesh: source is not registered.");
454
- a.visible = o, a.source.setUnifiedPickVisibility(o);
462
+ a.visible = i, a.source.setUnifiedPickVisibility(i);
455
463
  }
456
464
  /**
457
465
  * Core projected-2D depth of field on the unified draw pass (not gather).
@@ -459,8 +467,8 @@ class Ct extends l.Mesh {
459
467
  */
460
468
  setDepthOfField(e) {
461
469
  this.assertNotDisposed("setDepthOfField");
462
- const o = ot(e, this.getDepthOfField());
463
- this.dofFocusDistance.value = o.focusDistance, this.dofAperture.value = o.aperture;
470
+ const i = at(e, this.getDepthOfField());
471
+ this.dofFocusDistance.value = i.focusDistance, this.dofAperture.value = i.aperture;
464
472
  }
465
473
  /** Current core DoF uniforms (`aperture === 0` means off). */
466
474
  getDepthOfField() {
@@ -479,8 +487,8 @@ class Ct extends l.Mesh {
479
487
  this.relightBlend.value = 0, this.relightMap !== this.relightPlaceholder && (this.relightMap = this.relightPlaceholder, this.rebuildDrawMaterial());
480
488
  return;
481
489
  }
482
- const o = at(e, this.getRelighting());
483
- this.relightBlend.value = o.blend, this.relightBrightness.value = o.brightness, this.relightBackground.value = o.background, this.relightSoftness.value = o.softness, e.map !== this.relightMap && (this.relightMap = e.map, this.rebuildDrawMaterial());
490
+ const i = nt(e, this.getRelighting());
491
+ this.relightBlend.value = i.blend, this.relightBrightness.value = i.brightness, this.relightBackground.value = i.background, this.relightSoftness.value = i.softness, e.map !== this.relightMap && (this.relightMap = e.map, this.rebuildDrawMaterial());
484
492
  }
485
493
  /** Current relight numeric uniforms (`blend === 0` means off). */
486
494
  getRelighting() {
@@ -507,31 +515,31 @@ class Ct extends l.Mesh {
507
515
  * serializes its own picks and shared renderer state is restored
508
516
  * synchronously before any await.
509
517
  */
510
- async pick(e, o, a) {
518
+ async pick(e, i, a) {
511
519
  if (this.disposed) return null;
512
520
  const c = this.sources.filter((u) => u.visible).map((u) => u.source);
513
521
  if (c.length === 0) return null;
514
- const g = await Promise.all(
522
+ const S = await Promise.all(
515
523
  c.map(async (u) => {
516
- const p = await u.pick(e, o, this.renderer, a);
517
- return p === null ? null : { source: u, point: p.point, distance: p.distance };
524
+ const f = await u.pick(e, i, this.renderer, a);
525
+ return f === null ? null : { source: u, point: f.point, distance: f.distance };
518
526
  })
519
527
  );
520
528
  if (this.disposed) return null;
521
- let b = null;
522
- for (const u of g) {
529
+ let B = null;
530
+ for (const u of S) {
523
531
  if (u === null) continue;
524
- const p = this.sources.find((T) => T.source === u.source);
525
- p === void 0 || !p.visible || (b === null || u.distance < b.distance) && (b = u);
532
+ const f = this.sources.find((D) => D.source === u.source);
533
+ f === void 0 || !f.visible || (B === null || u.distance < B.distance) && (B = u);
526
534
  }
527
- return b;
535
+ return B;
528
536
  }
529
537
  /** Unregisters a source and restores its standalone draw visibility. */
530
538
  removeSource(e) {
531
539
  this.assertNotDisposed("removeSource");
532
- const o = this.sources.findIndex((c) => c.source === e);
533
- if (o < 0) return !1;
534
- const [a] = this.sources.splice(o, 1);
540
+ const i = this.sources.findIndex((c) => c.source === e);
541
+ if (i < 0) return !1;
542
+ const [a] = this.sources.splice(i, 1);
535
543
  return a && (a.gather.dispose(), a.source.visible = a.originalVisible, a.source.setUnifiedPickVisibility(null), a.lastGather = null), this.previousLayout = this.previousLayout.filter((c) => c.source !== e), this.previousLayoutBySource.delete(e), this.sources.length === 0 && (this.sourceMaxStdDev = null, this.sourceAntialias = null, this.sourceProjectedFilterProfile = null, this.previousLayout = [], this.previousLayoutBySource.clear()), !0;
536
544
  }
537
545
  /** Updates source LODs, gathers their active splats, then globally sorts them. */
@@ -543,119 +551,119 @@ class Ct extends l.Mesh {
543
551
  * Mirrors and portals use this instead of rendering the hidden source meshes
544
552
  * individually, so their reflection keeps one global transparent order.
545
553
  */
546
- renderView(e, o, a = null) {
554
+ renderView(e, i, a = null) {
547
555
  if (this.disposed) return;
548
- if (o !== this.renderer)
556
+ if (i !== this.renderer)
549
557
  throw new Error("UnifiedSplatMesh: renderView must use its construction renderer.");
550
- if (!Se(o))
558
+ if (!xe(i))
551
559
  throw new Error(
552
560
  "UnifiedSplatMesh requires a WebGPU backend (renderer.backend.isWebGPUBackend)."
553
561
  );
554
562
  const c = a ? this.secondaryViewSize.set(a.width, a.height) : void 0;
555
563
  this.prepare(e, c, !0);
556
- const g = o.getRenderTarget();
564
+ const S = i.getRenderTarget();
557
565
  try {
558
- o.setRenderTarget(a), o.render(this, e);
566
+ i.setRenderTarget(a), i.render(this, e);
559
567
  } finally {
560
- o.setRenderTarget(g), this.sortScheduler.invalidate();
568
+ i.setRenderTarget(S), this.sortScheduler.invalidate();
561
569
  }
562
570
  }
563
- prepare(e, o, a = !1) {
564
- if (!Se(this.renderer))
571
+ prepare(e, i, a = !1) {
572
+ if (!xe(this.renderer))
565
573
  throw new Error(
566
574
  "UnifiedSplatMesh requires a WebGPU backend (renderer.backend.isWebGPUBackend)."
567
575
  );
568
576
  this.matrix.identity(), this.matrixWorld.identity();
569
- const c = o ? null : nt(e, this.renderer), g = (c == null ? void 0 : c.eye) ?? e, b = (c == null ? void 0 : c.head) ?? e, u = this.drawingBufferSize;
570
- o ? u.copy(o) : c ? u.set(c.width, c.height) : this.renderer.getDrawingBufferSize(u);
571
- const p = g.projectionMatrix.elements;
577
+ const c = i ? null : ct(e, this.renderer), S = (c == null ? void 0 : c.eye) ?? e, B = (c == null ? void 0 : c.head) ?? e, u = this.drawingBufferSize;
578
+ i ? u.copy(i) : c ? u.set(c.width, c.height) : this.renderer.getDrawingBufferSize(u);
579
+ const f = S.projectionMatrix.elements;
572
580
  this.viewport.value.copy(u);
573
- const T = p[0] ?? 0, V = p[5] ?? 0;
574
- this.focal.value.set(T * u.x / 2, V * u.y / 2);
575
- const P = this.candidateScratch;
576
- P.length = 0;
577
- for (let t = 0; t < this.sources.length; t++) {
578
- const i = this.sources[t];
579
- i.source.update(e, this.renderer, { sort: !1 }), i.view = i.source.getUnifiedSourceView(), i.registrationOrder = t, P.push(i);
581
+ const D = f[0] ?? 0, V = f[5] ?? 0;
582
+ this.focal.value.set(D * u.x / 2, V * u.y / 2);
583
+ const T = this.candidateScratch;
584
+ T.length = 0;
585
+ for (let r = 0; r < this.sources.length; r++) {
586
+ const o = this.sources[r];
587
+ o.source.update(e, this.renderer, { sort: !1 }), o.view = o.source.getUnifiedSourceView(), o.registrationOrder = r, T.push(o);
580
588
  }
581
- P.sort((t, i) => i.priority - t.priority || t.registrationOrder - i.registrationOrder), this.overflowedSourceCount = 0, this.overflowedSplatCount = 0, this.bounds.makeEmpty();
582
- const m = this.admittedScratch;
583
- m.length = 0;
584
- let v = 0;
585
- for (const t of P) {
586
- const i = t.view;
587
- if (t.graphRevision !== i.graphRevision) {
588
- const d = this.createGather(i);
589
- t.gather.dispose(), t.gather = d, t.graphRevision = i.graphRevision, t.lastGather = null;
589
+ T.sort((r, o) => o.priority - r.priority || r.registrationOrder - o.registrationOrder), this.overflowedSourceCount = 0, this.overflowedSplatCount = 0, this.bounds.makeEmpty();
590
+ const y = this.admittedScratch;
591
+ y.length = 0;
592
+ let p = 0;
593
+ for (const r of T) {
594
+ const o = r.view;
595
+ if (r.graphRevision !== o.graphRevision) {
596
+ const d = this.createGather(o);
597
+ r.gather.dispose(), r.gather = d, r.graphRevision = o.graphRevision, r.lastGather = null;
590
598
  }
591
- if (!t.visible) {
592
- t.lastGather = null;
599
+ if (!r.visible) {
600
+ r.lastGather = null;
593
601
  continue;
594
602
  }
595
- if (i.activeCount === 0) {
596
- t.lastGather = null;
603
+ if (o.activeCount === 0) {
604
+ r.lastGather = null;
597
605
  continue;
598
606
  }
599
- if (v + i.activeCount > this.workBuffer.capacity) {
600
- this.overflowedSourceCount++, this.overflowedSplatCount += i.activeCount, t.lastGather = null;
607
+ if (p + o.activeCount > this.workBuffer.capacity) {
608
+ this.overflowedSourceCount++, this.overflowedSplatCount += o.activeCount, r.lastGather = null;
601
609
  continue;
602
610
  }
603
- t.offset = v, m.push(t), this.bounds.union(i.worldBounds), v += i.activeCount;
611
+ r.offset = p, y.push(r), this.bounds.union(o.worldBounds), p += o.activeCount;
604
612
  }
605
- let A = !1;
606
- for (const t of m) {
607
- const i = t.view, d = t.offset, B = this.previousLayoutBySource.get(t.source), y = B !== void 0 && B.offset === d && B.activeCount === i.activeCount, f = t.lastGather, S = f !== null && y && f.activeCount === i.activeCount && f.contentRevision === i.contentRevision && f.offset === d && f.opacity === t.opacity && f.matrixWorld.equals(i.matrixWorld);
608
- S && // SH depends on camera position, not orientation. A stationary camera
613
+ let M = !1;
614
+ for (const r of y) {
615
+ const o = r.view, d = r.offset, w = this.previousLayoutBySource.get(r.source), b = w !== void 0 && w.offset === d && w.activeCount === o.activeCount, m = r.lastGather, g = m !== null && b && m.activeCount === o.activeCount && m.contentRevision === o.contentRevision && m.offset === d && m.opacity === r.opacity && m.matrixWorld.equals(o.matrixWorld);
616
+ g && // SH depends on camera position, not orientation. A stationary camera
609
617
  // can reuse the resolved colors instead of re-running a full-source
610
618
  // gather every frame; camera motion invalidates only SH-bearing slices.
611
- (i.sh === null || f.localCameraPosition.equals(i.localCameraPosition.value)) && (i.modifiers.length === 0 || t.cacheModifiers) && // Belt-and-braces: a placed pool's splats move without its own
619
+ (o.sh === null || m.localCameraPosition.equals(o.localCameraPosition.value)) && (o.modifiers.length === 0 || r.cacheModifiers) && // Belt-and-braces: a placed pool's splats move without its own
612
620
  // `matrixWorld` changing, so a cached gather would go stale silently.
613
621
  // `addSource` already rejects these.
614
- !i.hasSourcePlacement || (t.gather.gather(
622
+ !o.hasSourcePlacement || (r.gather.gather(
615
623
  this.renderer,
616
- i.activeCount,
624
+ o.activeCount,
617
625
  d,
618
- i.matrixWorld,
619
- b.matrixWorldInverse,
620
- t.opacity
621
- ), S || (A = !0), t.lastGather === null ? t.lastGather = {
622
- activeCount: i.activeCount,
623
- contentRevision: i.contentRevision,
626
+ o.matrixWorld,
627
+ B.matrixWorldInverse,
628
+ r.opacity
629
+ ), g || (M = !0), r.lastGather === null ? r.lastGather = {
630
+ activeCount: o.activeCount,
631
+ contentRevision: o.contentRevision,
624
632
  offset: d,
625
- opacity: t.opacity,
626
- matrixWorld: i.matrixWorld.clone(),
627
- localCameraPosition: i.localCameraPosition.value.clone()
628
- } : (t.lastGather.activeCount = i.activeCount, t.lastGather.contentRevision = i.contentRevision, t.lastGather.offset = d, t.lastGather.opacity = t.opacity, t.lastGather.matrixWorld.copy(i.matrixWorld), t.lastGather.localCameraPosition.copy(i.localCameraPosition.value)));
633
+ opacity: r.opacity,
634
+ matrixWorld: o.matrixWorld.clone(),
635
+ localCameraPosition: o.localCameraPosition.value.clone()
636
+ } : (r.lastGather.activeCount = o.activeCount, r.lastGather.contentRevision = o.contentRevision, r.lastGather.offset = d, r.lastGather.opacity = r.opacity, r.lastGather.matrixWorld.copy(o.matrixWorld), r.lastGather.localCameraPosition.copy(o.localCameraPosition.value)));
629
637
  }
630
- let k = m.length !== this.previousLayout.length || v !== this.previousAdmittedTotal;
631
- if (this.previousAdmittedTotal = v, !k)
632
- for (let t = 0; t < m.length; t++) {
633
- const i = m[t], d = this.previousLayout[t];
634
- if (d.source !== i.source || d.offset !== i.offset || d.activeCount !== i.view.activeCount) {
635
- k = !0;
638
+ let P = y.length !== this.previousLayout.length || p !== this.previousAdmittedTotal;
639
+ if (this.previousAdmittedTotal = p, !P)
640
+ for (let r = 0; r < y.length; r++) {
641
+ const o = y[r], d = this.previousLayout[r];
642
+ if (d.source !== o.source || d.offset !== o.offset || d.activeCount !== o.view.activeCount) {
643
+ P = !0;
636
644
  break;
637
645
  }
638
646
  }
639
- if (k) {
640
- this.previousLayout = m.map((t) => ({
641
- source: t.source,
642
- offset: t.offset,
643
- activeCount: t.view.activeCount
647
+ if (P) {
648
+ this.previousLayout = y.map((r) => ({
649
+ source: r.source,
650
+ offset: r.offset,
651
+ activeCount: r.view.activeCount
644
652
  })), this.previousLayoutBySource.clear();
645
- for (const t of this.previousLayout) this.previousLayoutBySource.set(t.source, t);
653
+ for (const r of this.previousLayout) this.previousLayoutBySource.set(r.source, r);
646
654
  }
647
- if ((A || k) && this.sortScheduler.invalidateContent(), v > 0) {
648
- const t = performance.now(), i = b.matrixWorldInverse;
649
- (a || this.sortScheduler.shouldSubmit(i, this.lastSortedModelView, v, t)) && this.sorter.sort(i, v, this.bounds) && (this.lastSortedModelView.copy(i), this.sortScheduler.markAccepted(t));
655
+ if ((M || P) && this.sortScheduler.invalidateContent(), p > 0) {
656
+ const r = performance.now(), o = B.matrixWorldInverse;
657
+ (a || this.sortScheduler.shouldSubmit(o, this.lastSortedModelView, p, r)) && this.sorter.sort(o, p, this.bounds) && (this.lastSortedModelView.copy(o), this.sortScheduler.markAccepted(r));
650
658
  }
651
- this.geometry.instanceCount = v, this.mirrors.settled || this.mirrors.release(this.renderer);
659
+ this.geometry.instanceCount = p, this.mirrors.settled || this.mirrors.release(this.renderer);
652
660
  }
653
661
  dispose() {
654
662
  if (!this.disposed) {
655
663
  this.disposed = !0;
656
664
  for (const e of this.sources)
657
665
  e.gather.dispose(), e.source.visible = e.originalVisible, e.source.setUnifiedPickVisibility(null), e.lastGather = null;
658
- this.sources.length = 0, this.previousLayout = [], this.previousLayoutBySource.clear(), this.candidateScratch.length = 0, this.admittedScratch.length = 0, this.sourceMaxStdDev = null, this.sourceAntialias = null, this.sourceProjectedFilterProfile = null, this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.relightPlaceholder.dispose(), ct(this.renderer, [
666
+ this.sources.length = 0, this.previousLayout = [], this.previousLayoutBySource.clear(), this.candidateScratch.length = 0, this.admittedScratch.length = 0, this.sourceMaxStdDev = null, this.sourceAntialias = null, this.sourceProjectedFilterProfile = null, this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.relightPlaceholder.dispose(), lt(this.renderer, [
659
667
  this.workBuffer.centers,
660
668
  this.workBuffer.colors,
661
669
  this.workBuffer.covarianceA,
@@ -674,7 +682,7 @@ class Ct extends l.Mesh {
674
682
  /** Rebuilds the EWA draw material when the relight map identity changes. */
675
683
  rebuildDrawMaterial() {
676
684
  const e = this.material;
677
- this.material = Pe({
685
+ this.material = ke({
678
686
  capacity: this.workBuffer.capacity,
679
687
  centers: this.workBuffer.centers,
680
688
  colors: this.workBuffer.colors,
@@ -700,12 +708,12 @@ class Ct extends l.Mesh {
700
708
  }), e.dispose();
701
709
  }
702
710
  createGather(e) {
703
- const o = this.buildGather(e);
704
- return o.warmUp(this.renderer).catch(() => {
705
- }), o;
711
+ const i = this.buildGather(e);
712
+ return i.warmUp(this.renderer).catch(() => {
713
+ }), i;
706
714
  }
707
715
  buildGather(e) {
708
- return new ht({
716
+ return new ft({
709
717
  capacity: this.workBuffer.capacity,
710
718
  sourceCapacity: e.capacity,
711
719
  sourceIndex: e.sourceIndex,
@@ -727,12 +735,12 @@ class Ct extends l.Mesh {
727
735
  }
728
736
  }
729
737
  export {
730
- Ct as UnifiedSplatMesh,
731
- pt as WORK_BUFFER_BYTES_PER_SLOT,
732
- ft as WORK_BUFFER_CENTERS_BYTES_PER_SPLAT,
733
- mt as estimateLargestStorageBufferBytes,
734
- vt as estimateUnifiedWorkBufferBytes,
735
- Mt as estimateUnifiedWorkBufferPeakBytes,
736
- Se as supportsUnifiedSplatMesh
738
+ Pt as UnifiedSplatMesh,
739
+ mt as WORK_BUFFER_BYTES_PER_SLOT,
740
+ pt as WORK_BUFFER_CENTERS_BYTES_PER_SPLAT,
741
+ vt as estimateLargestStorageBufferBytes,
742
+ gt as estimateUnifiedWorkBufferBytes,
743
+ Ct as estimateUnifiedWorkBufferPeakBytes,
744
+ xe as supportsUnifiedSplatMesh
737
745
  };
738
746
  //# sourceMappingURL=unified.js.map