@voluma/vlam 0.2.3 → 0.3.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 +3 -2
- package/dist/budget-governor.d.ts +4 -4
- package/dist/camera-budget-governor.d.ts +11 -11
- package/dist/chunk-cache-budget.d.ts +5 -5
- package/dist/chunk-fetch-scheduler.d.ts +4 -4
- package/dist/chunk-loader-DlNwggfG.js +1859 -0
- package/dist/chunk-loader-DlNwggfG.js.map +1 -0
- package/dist/chunk-loader.d.ts +2 -2
- package/dist/compute-sorter.d.ts +1 -1
- package/dist/effects.d.ts +26 -16
- package/dist/effects.js +199 -165
- package/dist/effects.js.map +1 -1
- package/dist/formats/ksplat/index.d.ts +1 -1
- package/dist/formats/lcc/collision-mesh.d.ts +2 -2
- package/dist/formats/lcc.js +17 -16
- package/dist/formats/lcc.js.map +1 -1
- package/dist/formats/ply/index.d.ts +1 -1
- package/dist/formats/ply/parse-splat-ply.d.ts +2 -2
- package/dist/formats/ply.js +1 -1
- package/dist/formats/ply.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/rad.d.ts +2 -2
- package/dist/formats/rad.js +3 -3
- package/dist/formats/rad.js.map +1 -1
- package/dist/formats/sog/index.d.ts +1 -1
- package/dist/formats/sog/parse-sog.d.ts +4 -4
- package/dist/formats/sog.js.map +1 -1
- package/dist/formats/splat/index.d.ts +1 -1
- package/dist/formats/spz/index.d.ts +1 -1
- package/dist/index.d.ts +16 -25
- package/dist/index.js +253 -9047
- package/dist/index.js.map +1 -1
- package/dist/{load-scene.d.ts → load-splat-data.d.ts} +15 -13
- package/dist/loaders.d.ts +15 -0
- package/dist/loaders.js +26 -0
- package/dist/loaders.js.map +1 -0
- package/dist/loading-wLo8vRbA.js.map +1 -1
- package/dist/loading.d.ts +8 -8
- package/dist/{splat-mesh-types-CTN_duw2.js → lod-scheduler-B0a_uBlv.js} +133 -140
- package/dist/lod-scheduler-B0a_uBlv.js.map +1 -0
- package/dist/lod-scheduler.d.ts +1 -1
- package/dist/lod-source.d.ts +5 -5
- package/dist/{splat-scene.d.ts → merged-splat-mesh.d.ts} +14 -15
- package/dist/orientation.d.ts +7 -7
- package/dist/{ply-header-BwgExCn-.js → ply-header-B9WllbPg.js} +3 -3
- package/dist/{ply-header-BwgExCn-.js.map → ply-header-B9WllbPg.js.map} +1 -1
- package/dist/radix-sorter-R0FCSqKu.js +178 -0
- package/dist/radix-sorter-R0FCSqKu.js.map +1 -0
- package/dist/relighting-CSQF3UcL.js +969 -0
- package/dist/relighting-CSQF3UcL.js.map +1 -0
- package/dist/relighting.d.ts +1 -1
- package/dist/selection.d.ts +13 -0
- package/dist/selection.js +137 -0
- package/dist/selection.js.map +1 -0
- package/dist/source-transform.d.ts +4 -4
- package/dist/{splat-budget-DXew_86c.js → splat-budget-DuVZspPQ.js} +7 -7
- package/dist/{splat-budget-DXew_86c.js.map → splat-budget-DuVZspPQ.js.map} +1 -1
- package/dist/splat-budget.d.ts +1 -1
- package/dist/splat-data-BZM5dhhx.js.map +1 -1
- package/dist/splat-data.d.ts +4 -4
- package/dist/splat-mesh-aQdcWA6v.js +1942 -0
- package/dist/splat-mesh-aQdcWA6v.js.map +1 -0
- package/dist/splat-mesh-material.d.ts +2 -2
- package/dist/splat-mesh-types-BZIko-_9.js +18 -0
- package/dist/splat-mesh-types-BZIko-_9.js.map +1 -0
- package/dist/splat-mesh-types.d.ts +14 -8
- package/dist/splat-mesh.d.ts +4 -4
- package/dist/splat-modifier.d.ts +5 -5
- package/dist/splat-partition.d.ts +1 -1
- package/dist/static-lod-entry.d.ts +12 -0
- package/dist/static-lod-splat-mesh.d.ts +2 -2
- package/dist/{static-lod-worker-D2fyqQZO.js → static-lod-worker-DktKnJkR.js} +46 -46
- package/dist/{static-lod-worker-D2fyqQZO.js.map → static-lod-worker-DktKnJkR.js.map} +1 -1
- package/dist/static-lod.js +148 -0
- package/dist/static-lod.js.map +1 -0
- package/dist/streamed-splat-mesh.d.ts +21 -27
- package/dist/streaming.d.ts +23 -0
- package/dist/streaming.js +2877 -0
- package/dist/streaming.js.map +1 -0
- package/dist/{unified-splat-renderer.d.ts → unified-splat-mesh.d.ts} +10 -10
- package/dist/unified-work-buffer.d.ts +66 -0
- package/dist/unified.d.ts +11 -0
- package/dist/unified.js +738 -0
- package/dist/unified.js.map +1 -0
- package/dist/webgpu-limits-Y3CI_6_6.js +43 -0
- package/dist/webgpu-limits-Y3CI_6_6.js.map +1 -0
- package/dist/webgpu-limits.d.ts +0 -59
- package/dist/work-buffer-gather.d.ts +1 -1
- package/package.json +24 -4
- package/dist/splat-mesh-types-CTN_duw2.js.map +0 -1
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
var St = Object.defineProperty;
|
|
2
|
+
var Tt = (s, e, t) => e in s ? St(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
|
|
3
|
+
var l = (s, e, t) => Tt(s, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import * as h from "three/webgpu";
|
|
5
|
+
import { bool as yt, mat3 as Te, vec3 as S, float as v, modelViewMatrix as $e, vec4 as K, modelWorldMatrix as At, int as L, attribute as Mt, ivec2 as je, textureLoad as O, varying as he, colorSpaceToWorking as Ct, positionGeometry as _e, Fn as G, cameraProjectionMatrix as Pt, If as pe, mix as oe, vec2 as J, Discard as Ne, texture as ve, screenUV as Se, uniform as fe, uint as C, storage as ne, atomicStore as qe, instanceIndex as E, atomicAdd as rt, Loop as We, atomicLoad as it } from "three/tsl";
|
|
6
|
+
import { w as kt } from "./logging-BfPdd7NJ.js";
|
|
7
|
+
function Rt(s, e, t) {
|
|
8
|
+
if (s.length === 0)
|
|
9
|
+
return {
|
|
10
|
+
color: t.color,
|
|
11
|
+
offset: null,
|
|
12
|
+
scaleSquared: null,
|
|
13
|
+
rotation: null,
|
|
14
|
+
visible: null,
|
|
15
|
+
isotropicCovarianceMix: null,
|
|
16
|
+
isotropicVarianceScale: null,
|
|
17
|
+
isotropicScreenRadiusPx: null
|
|
18
|
+
};
|
|
19
|
+
const o = e, a = {
|
|
20
|
+
color: t.color,
|
|
21
|
+
offset: S(0, 0, 0),
|
|
22
|
+
scale: v(1),
|
|
23
|
+
rotation: Te(S(1, 0, 0), S(0, 1, 0), S(0, 0, 1)),
|
|
24
|
+
visible: yt(!0)
|
|
25
|
+
}, n = { offset: !1, scale: !1, rotation: !1, visible: !1 };
|
|
26
|
+
let r = null, i = null, d = null, c = null, T = null, D = null;
|
|
27
|
+
const y = /* @__PURE__ */ new Map(), q = {
|
|
28
|
+
index: t.index,
|
|
29
|
+
localCenter: t.localCenter,
|
|
30
|
+
sourceCenter: t.sourceCenter ?? t.localCenter,
|
|
31
|
+
sourceToLocal: t.sourceToLocal ?? a.rotation,
|
|
32
|
+
cameraLocal: o,
|
|
33
|
+
baseColor: t.color,
|
|
34
|
+
get worldCenter() {
|
|
35
|
+
return c ?? (c = t.makeWorldCenter ? t.makeWorldCenter() : At.mul(K(t.localCenter, 1)).xyz);
|
|
36
|
+
},
|
|
37
|
+
get viewCenter() {
|
|
38
|
+
return T ?? (T = t.makeViewCenter ? t.makeViewCenter() : $e.mul(K(t.localCenter, 1)).xyz);
|
|
39
|
+
},
|
|
40
|
+
get normal() {
|
|
41
|
+
return D ?? (D = t.makeNormal());
|
|
42
|
+
},
|
|
43
|
+
channel(M) {
|
|
44
|
+
let m = y.get(M);
|
|
45
|
+
return m || (m = t.makeChannel(M), y.set(M, m)), m;
|
|
46
|
+
},
|
|
47
|
+
get color() {
|
|
48
|
+
return a.color;
|
|
49
|
+
},
|
|
50
|
+
get offset() {
|
|
51
|
+
return a.offset;
|
|
52
|
+
},
|
|
53
|
+
get scale() {
|
|
54
|
+
return a.scale;
|
|
55
|
+
},
|
|
56
|
+
get rotation() {
|
|
57
|
+
return a.rotation;
|
|
58
|
+
},
|
|
59
|
+
get visible() {
|
|
60
|
+
return a.visible;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
for (const M of s) {
|
|
64
|
+
const m = M(q);
|
|
65
|
+
m.color && (a.color = m.color), m.offset && (a.offset = m.offset, n.offset = !0), m.scale && (a.scale = m.scale, n.scale = !0), m.rotation && (a.rotation = m.rotation, n.rotation = !0), m.visible && (a.visible = m.visible, n.visible = !0), m.isotropicCovarianceMix !== void 0 && (r = m.isotropicCovarianceMix), m.isotropicVarianceScale !== void 0 && (i = m.isotropicVarianceScale), m.isotropicScreenRadiusPx !== void 0 && (d = m.isotropicScreenRadiusPx);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
color: a.color,
|
|
69
|
+
offset: n.offset ? a.offset : null,
|
|
70
|
+
scaleSquared: n.scale ? a.scale.mul(a.scale) : null,
|
|
71
|
+
rotation: n.rotation ? a.rotation : null,
|
|
72
|
+
visible: n.visible ? a.visible : null,
|
|
73
|
+
isotropicCovarianceMix: r,
|
|
74
|
+
isotropicVarianceScale: i,
|
|
75
|
+
isotropicScreenRadiusPx: d
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const De = 2048;
|
|
79
|
+
function Bt(s, e, t) {
|
|
80
|
+
let o = -1;
|
|
81
|
+
for (let a = 0; a < s.length; a++) {
|
|
82
|
+
const n = s[a];
|
|
83
|
+
if (!(n.count < e) && ((o === -1 || n.count < s[o].count) && (o = a), n.count === e))
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
if (o !== -1) {
|
|
87
|
+
const a = s[o], n = a.start;
|
|
88
|
+
return a.start += e, a.count -= e, a.count === 0 && s.splice(o, 1), n;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(
|
|
91
|
+
`SplatMesh capacity exceeded: no contiguous space for ${e} rows (${De} splats each) in a ${t}-row pool.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function It(s, e, t) {
|
|
95
|
+
s.push({ start: e, count: t }), s.sort((a, n) => a.start - n.start);
|
|
96
|
+
const o = [];
|
|
97
|
+
for (const a of s) {
|
|
98
|
+
const n = o[o.length - 1];
|
|
99
|
+
if (n && n.start + n.count > a.start)
|
|
100
|
+
throw new Error(
|
|
101
|
+
`SplatMesh pool released rows [${e}, ${e + t}) overlap an already-free span.`
|
|
102
|
+
);
|
|
103
|
+
n && n.start + n.count === a.start ? n.count += a.count : o.push(a);
|
|
104
|
+
}
|
|
105
|
+
return o;
|
|
106
|
+
}
|
|
107
|
+
class is {
|
|
108
|
+
constructor(e) {
|
|
109
|
+
l(this, "width", De);
|
|
110
|
+
l(this, "rows");
|
|
111
|
+
l(this, "floatTextures");
|
|
112
|
+
l(this, "packedShBands");
|
|
113
|
+
l(this, "backing");
|
|
114
|
+
l(this, "centersTexture");
|
|
115
|
+
l(this, "colorsTexture");
|
|
116
|
+
l(this, "covarianceATexture");
|
|
117
|
+
l(this, "covarianceBTexture");
|
|
118
|
+
l(this, "shPackedTextures");
|
|
119
|
+
/** Free row spans, sorted by start row. Mutated in place by the allocator. */
|
|
120
|
+
l(this, "freeRowSpans");
|
|
121
|
+
l(this, "tenants", /* @__PURE__ */ new Set());
|
|
122
|
+
/**
|
|
123
|
+
* Pool index → its owner's packed active-list slot, valid only while that
|
|
124
|
+
* pool index is active.
|
|
125
|
+
*
|
|
126
|
+
* Pool-owned rather than per-mesh because it is keyed by *pool* index: a
|
|
127
|
+
* per-mesh copy would have to span the whole pool, so N meshes sharing one
|
|
128
|
+
* pool would each pay 4 B per pool splat (a 4 M-splat pool shared by 13
|
|
129
|
+
* meshes = ~200 MB of reverse maps). One array is safe because a row belongs
|
|
130
|
+
* to exactly one tenant at a time, so no two tenants ever write the same
|
|
131
|
+
* entry - the slot numbers in it are simply read back by whoever owns
|
|
132
|
+
* the row.
|
|
133
|
+
*/
|
|
134
|
+
l(this, "activeSlotByPoolIndex");
|
|
135
|
+
l(this, "poolIndexTemplate", null);
|
|
136
|
+
if (!(e.capacity > 0)) throw new Error("SplatPool capacity must be positive.");
|
|
137
|
+
this.rows = Math.ceil(e.capacity / this.width), Dt(this.rows, e.maxTextureSize ?? 0, this.width);
|
|
138
|
+
const t = this.width * this.rows;
|
|
139
|
+
this.floatTextures = e.floatTextures === "float16" ? "float16" : "float32", this.packedShBands = e.packedShBands ?? 0;
|
|
140
|
+
const o = this.floatTextures === "float16" ? h.HalfFloatType : h.FloatType;
|
|
141
|
+
this.backing = {
|
|
142
|
+
centers: new Float32Array(t * 4),
|
|
143
|
+
colors: new Uint8Array(t * 4),
|
|
144
|
+
covarianceA: new Float32Array(t * 4),
|
|
145
|
+
covarianceB: new Float32Array(t * 4),
|
|
146
|
+
// One RGBA32UI texel per splat per texture; sharing the pool's row
|
|
147
|
+
// geometry lets the whole partial-upload/compaction path reuse the
|
|
148
|
+
// existing row arithmetic unchanged.
|
|
149
|
+
shPacked: Array.from(
|
|
150
|
+
{ length: e.packedShTextureCount ?? 0 },
|
|
151
|
+
() => new Uint32Array(t * 4)
|
|
152
|
+
)
|
|
153
|
+
};
|
|
154
|
+
const a = this.floatTextures === "float16" ? new Uint16Array(t * 4) : this.backing.centers, n = this.floatTextures === "float16" ? new Uint16Array(t * 4) : this.backing.covarianceA;
|
|
155
|
+
this.centersTexture = Ee(a, this.width, this.rows, o), this.colorsTexture = Ee(
|
|
156
|
+
this.backing.colors,
|
|
157
|
+
this.width,
|
|
158
|
+
this.rows,
|
|
159
|
+
h.UnsignedByteType
|
|
160
|
+
), this.covarianceATexture = Ee(n, this.width, this.rows, o), this.covarianceBTexture = Ee(
|
|
161
|
+
this.backing.covarianceB,
|
|
162
|
+
this.width,
|
|
163
|
+
this.rows,
|
|
164
|
+
h.FloatType
|
|
165
|
+
), this.shPackedTextures = this.backing.shPacked.map(
|
|
166
|
+
(r) => Et(r, this.width, this.rows)
|
|
167
|
+
), this.freeRowSpans = [{ start: 0, count: this.rows }], this.activeSlotByPoolIndex = new Uint32Array(t);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* A reusable `0, 1, 2, …` ramp over the pool, used to fill runs of pool
|
|
171
|
+
* indices and active-list slots without a per-element loop. Pool-owned so
|
|
172
|
+
* tenants sharing a pool share the one copy.
|
|
173
|
+
*/
|
|
174
|
+
indexTemplate() {
|
|
175
|
+
if (this.poolIndexTemplate) return this.poolIndexTemplate;
|
|
176
|
+
const e = new Uint32Array(this.capacity);
|
|
177
|
+
for (let t = 0; t < e.length; t++) e[t] = t;
|
|
178
|
+
return this.poolIndexTemplate = e, e;
|
|
179
|
+
}
|
|
180
|
+
/** Splats the pool holds, always a whole number of rows. */
|
|
181
|
+
get capacity() {
|
|
182
|
+
return this.rows * this.width;
|
|
183
|
+
}
|
|
184
|
+
/** Whether `texture` belongs to this pool (and so outlives any one tenant). */
|
|
185
|
+
isPoolTexture(e) {
|
|
186
|
+
return e === this.centersTexture || e === this.colorsTexture || e === this.covarianceATexture || e === this.covarianceBTexture || this.shPackedTextures.includes(e);
|
|
187
|
+
}
|
|
188
|
+
/** The four core textures, in the order the upload path indexes them. */
|
|
189
|
+
get coreTextures() {
|
|
190
|
+
return [
|
|
191
|
+
this.centersTexture,
|
|
192
|
+
this.colorsTexture,
|
|
193
|
+
this.covarianceATexture,
|
|
194
|
+
this.covarianceBTexture
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
/** Rows still free, whether or not they are contiguous. */
|
|
198
|
+
get freeRows() {
|
|
199
|
+
let e = 0;
|
|
200
|
+
for (const t of this.freeRowSpans) e += t.count;
|
|
201
|
+
return e;
|
|
202
|
+
}
|
|
203
|
+
/** Takes `rowCount` contiguous rows; throws when none are left (compact cue). */
|
|
204
|
+
allocateRows(e) {
|
|
205
|
+
return Bt(this.freeRowSpans, e, this.rows);
|
|
206
|
+
}
|
|
207
|
+
/** Returns rows to the free list, coalescing neighbours. */
|
|
208
|
+
releaseRows(e, t) {
|
|
209
|
+
this.freeRowSpans = It(this.freeRowSpans, e, t);
|
|
210
|
+
}
|
|
211
|
+
/** Resets the free list to one span covering the whole pool. */
|
|
212
|
+
resetFreeRows(e = 0) {
|
|
213
|
+
this.freeRowSpans = e < this.rows ? [{ start: e, count: this.rows - e }] : [];
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Adds a mesh that draws from this pool. Registration exists for
|
|
217
|
+
* {@link compact}: packing the pool moves rows that belong to *every*
|
|
218
|
+
* tenant, so each has to be told where its ranges went.
|
|
219
|
+
*/
|
|
220
|
+
register(e) {
|
|
221
|
+
this.tenants.add(e);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Drops a tenant. Release its ranges first: an unregistered tenant is
|
|
225
|
+
* invisible to {@link compact}, which would then treat rows it still holds
|
|
226
|
+
* as free and hand them to someone else. `compact` throws rather than let
|
|
227
|
+
* that happen silently.
|
|
228
|
+
*/
|
|
229
|
+
unregister(e) {
|
|
230
|
+
this.tenants.delete(e);
|
|
231
|
+
}
|
|
232
|
+
/** Number of meshes drawing from this pool. */
|
|
233
|
+
get tenantCount() {
|
|
234
|
+
return this.tenants.size;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Packs every tenant's ranges toward row 0, removing the gaps that add /
|
|
238
|
+
* remove churn leaves behind and restoring a single contiguous free span.
|
|
239
|
+
* Callers reach this when {@link allocateRows} throws despite enough total
|
|
240
|
+
* free rows - row-alignment fragmentation.
|
|
241
|
+
*
|
|
242
|
+
* The CPU backing arrays are authoritative, so nothing is re-fetched; moved
|
|
243
|
+
* rows are re-uploaded on the tenant's next update.
|
|
244
|
+
*
|
|
245
|
+
* Note this is a whole-pool stall: with several tenants, one mesh's
|
|
246
|
+
* fragmentation relocates the others' rows too, and every tenant rebuilds
|
|
247
|
+
* its draw state. (Spark sidesteps the equivalent by allocating fixed-size,
|
|
248
|
+
* interchangeable pages that never need packing; vlam's ranges are variable
|
|
249
|
+
* runs, so it packs instead.)
|
|
250
|
+
*/
|
|
251
|
+
compact() {
|
|
252
|
+
const e = this.width, t = [];
|
|
253
|
+
let o = 0;
|
|
254
|
+
for (const n of this.tenants)
|
|
255
|
+
for (const r of n.poolRanges())
|
|
256
|
+
t.push({ tenant: n, range: r }), o += r.rowCount;
|
|
257
|
+
if (o + this.freeRows !== this.rows)
|
|
258
|
+
throw new Error(
|
|
259
|
+
`SplatPool compaction found ${this.rows - o - this.freeRows} unaccounted row(s): ${o} held by ${this.tenants.size} tenant(s), ${this.freeRows} free, ${this.rows} total. Release a tenant's ranges before unregistering it.`
|
|
260
|
+
);
|
|
261
|
+
t.sort((n, r) => n.range.startRow - r.range.startRow);
|
|
262
|
+
let a = 0;
|
|
263
|
+
for (const { tenant: n, range: r } of t) {
|
|
264
|
+
if (r.startRow !== a) {
|
|
265
|
+
const i = r.startRow * e * 4, d = a * e * 4, c = r.rowCount * e * 4;
|
|
266
|
+
this.backing.centers.copyWithin(d, i, i + c), this.backing.colors.copyWithin(d, i, i + c), this.backing.covarianceA.copyWithin(d, i, i + c), this.backing.covarianceB.copyWithin(d, i, i + c);
|
|
267
|
+
for (const T of this.backing.shPacked) T.copyWithin(d, i, i + c);
|
|
268
|
+
n.relocatePoolRange(r, a);
|
|
269
|
+
}
|
|
270
|
+
a += r.rowCount;
|
|
271
|
+
}
|
|
272
|
+
this.resetFreeRows(a);
|
|
273
|
+
for (const n of this.tenants) n.onPoolCompacted();
|
|
274
|
+
}
|
|
275
|
+
dispose() {
|
|
276
|
+
for (const e of this.coreTextures) e.dispose();
|
|
277
|
+
for (const e of this.shPackedTextures) e.dispose();
|
|
278
|
+
this.tenants.clear();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function Ee(s, e, t, o) {
|
|
282
|
+
const a = new h.DataTexture(s, e, t, h.RGBAFormat, o);
|
|
283
|
+
return a.needsUpdate = !0, a;
|
|
284
|
+
}
|
|
285
|
+
function Et(s, e, t) {
|
|
286
|
+
const o = new h.DataTexture(
|
|
287
|
+
s,
|
|
288
|
+
e,
|
|
289
|
+
t,
|
|
290
|
+
h.RGBAIntegerFormat,
|
|
291
|
+
h.UnsignedIntType
|
|
292
|
+
);
|
|
293
|
+
return o.magFilter = h.NearestFilter, o.minFilter = h.NearestFilter, o.generateMipmaps = !1, o.needsUpdate = !0, o;
|
|
294
|
+
}
|
|
295
|
+
function cs(s) {
|
|
296
|
+
var a, n;
|
|
297
|
+
const e = s.backend, t = (n = (a = e == null ? void 0 : e.device) == null ? void 0 : a.limits) == null ? void 0 : n.maxTextureDimension2D;
|
|
298
|
+
if (typeof t == "number" && t > 0) return t;
|
|
299
|
+
const o = e == null ? void 0 : e.gl;
|
|
300
|
+
if (o) {
|
|
301
|
+
const r = o.getParameter(o.MAX_TEXTURE_SIZE);
|
|
302
|
+
if (typeof r == "number" && r > 0) return r;
|
|
303
|
+
}
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
function Dt(s, e, t = De) {
|
|
307
|
+
if (!(!(e > 0) || s <= e))
|
|
308
|
+
throw new Error(
|
|
309
|
+
`SplatPool: this scene needs a ${t}×${s} data texture, but this device caps texture dimensions at ${e} (about ${(e * t).toLocaleString("en-US")} pool splats). Lower the splat budget, or raise maxTextureDimension2D in the renderer's requiredLimits if the adapter advertises more.`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
function ls(s, e, t) {
|
|
313
|
+
let o = e, a = e + t;
|
|
314
|
+
const n = [];
|
|
315
|
+
for (const r of s.updateRanges) {
|
|
316
|
+
const i = r.start + r.count;
|
|
317
|
+
if (i < o || r.start > a) {
|
|
318
|
+
n.push(r);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
o = Math.min(o, r.start), a = Math.max(a, i);
|
|
322
|
+
}
|
|
323
|
+
n.push({ start: o, count: a - o }), n.sort((r, i) => r.start - i.start), s.clearUpdateRanges();
|
|
324
|
+
for (const r of n) s.addUpdateRange(r.start, r.count);
|
|
325
|
+
}
|
|
326
|
+
const ct = 24, dt = ct * ct;
|
|
327
|
+
function Ft(s, e) {
|
|
328
|
+
const t = Math.max(0, s);
|
|
329
|
+
if (t <= 0) return 0;
|
|
330
|
+
const o = Math.max(1e-4, e);
|
|
331
|
+
return 2 * Math.atan(0.5 * t / o);
|
|
332
|
+
}
|
|
333
|
+
function us(s) {
|
|
334
|
+
const e = Math.max(1e-4, s.depth), t = Math.max(1e-4, s.focusDistance), o = Ft(s.aperture, t);
|
|
335
|
+
if (o <= 0 || !(s.focalPx > 0)) return 0;
|
|
336
|
+
const a = Math.abs(e - t) / e, n = s.focalPx * Math.tan(0.5 * o), r = a * n, i = r * r, d = s.maxVariance ?? dt;
|
|
337
|
+
return Math.min(i, d);
|
|
338
|
+
}
|
|
339
|
+
function ds(s, e) {
|
|
340
|
+
return Math.sqrt(Math.max(0, s) / Math.max(1e-9, e));
|
|
341
|
+
}
|
|
342
|
+
function ms(s, e = { focusDistance: 10, aperture: 0 }) {
|
|
343
|
+
const t = typeof s.focusDistance == "number" && Number.isFinite(s.focusDistance) ? Math.max(1e-4, s.focusDistance) : e.focusDistance, o = typeof s.aperture == "number" && Number.isFinite(s.aperture) ? Math.max(0, s.aperture) : e.aperture;
|
|
344
|
+
return { focusDistance: t, aperture: o };
|
|
345
|
+
}
|
|
346
|
+
const lt = 1024, zt = 1e30, Ut = 0.35 * 0.35;
|
|
347
|
+
function Vt(s, e, t, o) {
|
|
348
|
+
const a = S(1, 0, 0), n = S(0, 1, 0), r = S(0, 0, 1), i = s.mul(a), d = s.mul(n), c = s.mul(r), T = i.x, D = d.y, y = c.z, q = i.cross(d), M = d.cross(c), m = c.cross(i), w = q.length(), V = M.length(), X = m.length(), xe = w.greaterThanEqual(V).and(w.greaterThanEqual(X)), ae = V.greaterThan(w).and(V.greaterThanEqual(X)), re = xe.select(q, ae.select(M, m)), u = re.div(re.length().max(1e-12)), x = u.dot(s.mul(u)), F = T.min(D).min(y).min(x).max(1e-12).mul(o), $ = Te(S(F, 0, 0), S(0, F, 0), S(0, 0, F));
|
|
349
|
+
return s.mul(v(1).sub(t)).add($.mul(t));
|
|
350
|
+
}
|
|
351
|
+
function Ot(s, e, t) {
|
|
352
|
+
const o = s.min(e);
|
|
353
|
+
return {
|
|
354
|
+
lambda1: oe(s, o, t),
|
|
355
|
+
lambda2: oe(e, o, t)
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function Lt(s, e, t, o, a) {
|
|
359
|
+
const n = o.div(a).pow(2), r = s.min(e).min(n), i = oe(s, r, t), d = oe(e, r, t), c = o.greaterThan(0);
|
|
360
|
+
return {
|
|
361
|
+
lambda1: c.select(i, s),
|
|
362
|
+
lambda2: c.select(d, e)
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function hs(s) {
|
|
366
|
+
return s;
|
|
367
|
+
}
|
|
368
|
+
function fs() {
|
|
369
|
+
return fe(new h.Vector3());
|
|
370
|
+
}
|
|
371
|
+
function mt(s, e, t) {
|
|
372
|
+
const o = e.mul(L(4)), a = s.element(o), n = s.element(o.add(L(1))), r = s.element(o.add(L(2))), i = s.element(o.add(L(3))), d = a.xyz.mul(t.x).add(n.xyz.mul(t.y)).add(r.xyz.mul(t.z)).add(i.xyz), c = Te(a.xyz, n.xyz, r.xyz);
|
|
373
|
+
return { worldCenter: d, linear: c };
|
|
374
|
+
}
|
|
375
|
+
function _t(s) {
|
|
376
|
+
return [0, 3, 8, 15][s] ?? 0;
|
|
377
|
+
}
|
|
378
|
+
function ht(s, e, t) {
|
|
379
|
+
if (s.mode === "palette") {
|
|
380
|
+
const n = O(e.covarianceBTexture, t).z.toInt(), r = n.mod(L(64)).mul(L(_t(s.bands))), i = n.div(L(64));
|
|
381
|
+
return (d) => O(s.paletteTexture, je(r.add(L(d)), i)).xyz;
|
|
382
|
+
}
|
|
383
|
+
const o = s.textures.map(
|
|
384
|
+
(n) => O(n, t).toVar()
|
|
385
|
+
), a = s.range.max.sub(s.range.min);
|
|
386
|
+
return (n) => {
|
|
387
|
+
const r = o[n >> 2], i = [r.x, r.y, r.z, r.w][n & 3], d = S(
|
|
388
|
+
i.bitAnd(C(2047)).toFloat().div(2047),
|
|
389
|
+
i.shiftRight(C(11)).bitAnd(C(1023)).toFloat().div(1023),
|
|
390
|
+
i.shiftRight(C(21)).bitAnd(C(2047)).toFloat().div(2047)
|
|
391
|
+
);
|
|
392
|
+
return s.range.min.add(a.mul(d));
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
const ge = 0.4886025119029199, H = [
|
|
396
|
+
1.0925484305920792,
|
|
397
|
+
-1.0925484305920792,
|
|
398
|
+
0.31539156525252005,
|
|
399
|
+
-1.0925484305920792,
|
|
400
|
+
0.5462742152960396
|
|
401
|
+
], U = [
|
|
402
|
+
-0.5900435899266435,
|
|
403
|
+
2.890611442640554,
|
|
404
|
+
-0.4570457994644658,
|
|
405
|
+
0.3731763325901154,
|
|
406
|
+
-0.4570457994644658,
|
|
407
|
+
1.445305721320277,
|
|
408
|
+
-0.5900435899266435
|
|
409
|
+
];
|
|
410
|
+
function ps(s, e, t, o) {
|
|
411
|
+
const a = o.x, n = o.y, r = o.z, i = ht(s, e, t), d = i(0).mul(n.mul(-ge)).add(i(1).mul(r.mul(ge))).add(i(2).mul(a.mul(-ge)));
|
|
412
|
+
if (s.bands === 1) return d;
|
|
413
|
+
const c = a.mul(a), T = n.mul(n), D = r.mul(r), y = d.add(i(3).mul(a.mul(n).mul(H[0]))).add(i(4).mul(n.mul(r).mul(H[1]))).add(i(5).mul(D.mul(2).sub(c).sub(T).mul(H[2]))).add(i(6).mul(a.mul(r).mul(H[3]))).add(i(7).mul(c.sub(T).mul(H[4])));
|
|
414
|
+
return s.bands === 2 ? y : y.add(i(8).mul(n.mul(c.mul(3).sub(T)).mul(U[0]))).add(i(9).mul(a.mul(n).mul(r).mul(U[1]))).add(i(10).mul(n.mul(D.mul(4).sub(c).sub(T)).mul(U[2]))).add(i(11).mul(r.mul(D.mul(2).sub(c.mul(3)).sub(T.mul(3))).mul(U[3]))).add(i(12).mul(a.mul(D.mul(4).sub(c).sub(T)).mul(U[4]))).add(i(13).mul(r.mul(c.sub(T)).mul(U[5]))).add(i(14).mul(a.mul(c.sub(T.mul(3))).mul(U[6])));
|
|
415
|
+
}
|
|
416
|
+
function gs(s, e, t) {
|
|
417
|
+
const { textures: o, sh: a, uniforms: n, settings: r, pick: i } = t, d = L(De), c = v(lt), T = -0.5 * r.maxStdDev * r.maxStdDev, D = Mt("splatIndex", "float").toInt(), y = je(D.mod(d), D.div(d)), q = O(o.colorsTexture, y), M = O(o.centersTexture, y).xyz, m = t.sourcePlacement, w = m ? mt(
|
|
418
|
+
m.columns,
|
|
419
|
+
O(m.sourceIdTexture, y).r.toInt(),
|
|
420
|
+
M
|
|
421
|
+
) : null, V = w ? w.worldCenter : M, X = a === null ? null : (() => {
|
|
422
|
+
const b = w ? w.linear.inverse().mul(V.sub(n.localCameraPosition)).normalize() : V.sub(n.localCameraPosition).normalize(), f = b.x, g = b.y, B = b.z, p = ht(a, o, y), z = p(0).mul(g.mul(-ge)).add(p(1).mul(B.mul(ge))).add(p(2).mul(f.mul(-ge)));
|
|
423
|
+
if (a.bands === 1) return z;
|
|
424
|
+
const A = f.mul(f), I = g.mul(g), P = B.mul(B), _ = z.add(p(3).mul(f.mul(g).mul(H[0]))).add(p(4).mul(g.mul(B).mul(H[1]))).add(p(5).mul(P.mul(2).sub(A).sub(I).mul(H[2]))).add(p(6).mul(f.mul(B).mul(H[3]))).add(p(7).mul(A.sub(I).mul(H[4])));
|
|
425
|
+
return a.bands === 2 ? _ : _.add(p(8).mul(g.mul(A.mul(3).sub(I)).mul(U[0]))).add(p(9).mul(f.mul(g).mul(B).mul(U[1]))).add(p(10).mul(g.mul(P.mul(4).sub(A).sub(I)).mul(U[2]))).add(
|
|
426
|
+
p(11).mul(
|
|
427
|
+
B.mul(P.mul(2).sub(A.mul(3)).sub(I.mul(3))).mul(U[3])
|
|
428
|
+
)
|
|
429
|
+
).add(p(12).mul(f.mul(P.mul(4).sub(A).sub(I)).mul(U[4]))).add(p(13).mul(B.mul(A.sub(I)).mul(U[5]))).add(p(14).mul(f.mul(A.sub(I.mul(3))).mul(U[6])));
|
|
430
|
+
})(), xe = X === null ? q : K(q.rgb.add(X).clamp(0, 1), q.a), ae = () => {
|
|
431
|
+
const b = O(o.covarianceATexture, y), f = O(o.covarianceBTexture, y), g = Te(
|
|
432
|
+
S(b.x.add(1e-8), b.y, b.z),
|
|
433
|
+
S(b.y, b.w.add(1e-8), f.x),
|
|
434
|
+
S(b.z, f.x, f.y.add(1e-8))
|
|
435
|
+
), p = (w ? w.linear.mul(g).mul(w.linear.transpose()) : g).inverse(), z = n.localCameraPosition.sub(V), A = p.mul(p.mul(z)).normalize();
|
|
436
|
+
return A.mul(A.dot(z).sign());
|
|
437
|
+
}, re = (b) => {
|
|
438
|
+
const f = t.channels.get(b);
|
|
439
|
+
if (!f)
|
|
440
|
+
throw new Error(
|
|
441
|
+
`SplatMesh: a modifier reads channel "${b}", which is not defined. Call defineChannel("${b}") before assigning the modifier.`
|
|
442
|
+
);
|
|
443
|
+
return O(f.texture, y).r;
|
|
444
|
+
}, u = Rt(t.modifiers, n.localCameraPosition, {
|
|
445
|
+
index: D,
|
|
446
|
+
localCenter: V,
|
|
447
|
+
sourceCenter: M,
|
|
448
|
+
sourceToLocal: w == null ? void 0 : w.linear,
|
|
449
|
+
color: xe,
|
|
450
|
+
makeNormal: ae,
|
|
451
|
+
makeChannel: re
|
|
452
|
+
}), x = he(
|
|
453
|
+
r.srgbOutput ? u.color : Ct(u.color, h.SRGBColorSpace)
|
|
454
|
+
), R = he(_e.xy), F = e === "pick" ? he(v(0), "pickViewDepth") : null, $ = he(v(1), "vOpacityCompensation"), Z = r.lodAlpha ? he(v(r.maxStdDev), "vAdjustedStdDev") : null, ie = r.lodAlpha ? he(v(1), "vAlpha2") : null;
|
|
455
|
+
if (s.vertexNode = G(() => {
|
|
456
|
+
const b = u.offset === null ? V : V.add(u.offset), f = $e.mul(K(b, 1)).toVar(), g = Pt.mul(f).toVar(), B = K(0, 0, 2, 1).toVar(), p = e === "pick" ? 1.2 + 2 * lt : 1.2, z = g.w.mul(p), A = g.z.greaterThan(z.negate()).and(g.x.abs().lessThan(z)).and(g.y.abs().lessThan(z)), I = u.visible === null ? A : A.and(u.visible);
|
|
457
|
+
return pe(I, () => {
|
|
458
|
+
F && F.assign(f.z.negate());
|
|
459
|
+
const P = O(o.covarianceATexture, y), _ = O(o.covarianceBTexture, y), ce = Te(
|
|
460
|
+
S(P.x, P.y, P.z),
|
|
461
|
+
S(P.y, P.w, _.x),
|
|
462
|
+
S(P.z, _.x, _.y)
|
|
463
|
+
), be = w ? w.linear.mul(ce).mul(w.linear.transpose()) : ce;
|
|
464
|
+
let Y = u.rotation === null ? be : u.rotation.mul(be).mul(u.rotation.transpose());
|
|
465
|
+
if (u.isotropicCovarianceMix !== null) {
|
|
466
|
+
const k = u.isotropicVarianceScale ?? v(Ut);
|
|
467
|
+
Y = Vt(
|
|
468
|
+
Y,
|
|
469
|
+
S(0, 0, 1),
|
|
470
|
+
u.isotropicCovarianceMix,
|
|
471
|
+
k
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
const le = v(1).div(f.z), ye = le.mul(le), Ae = S(
|
|
475
|
+
n.focal.x.mul(le),
|
|
476
|
+
0,
|
|
477
|
+
n.focal.x.negate().mul(f.x).mul(ye)
|
|
478
|
+
), Fe = S(
|
|
479
|
+
0,
|
|
480
|
+
n.focal.y.mul(le),
|
|
481
|
+
n.focal.y.negate().mul(f.y).mul(ye)
|
|
482
|
+
), Me = $e.toMat3().transpose(), ue = Me.mul(Ae), de = Me.mul(Fe), Ce = ue.dot(Y.mul(ue)), Pe = de.dot(Y.mul(de)), He = ue.dot(Y.mul(de)), ze = u.scaleSquared === null ? Ce : Ce.mul(u.scaleSquared), Ue = u.scaleSquared === null ? Pe : Pe.mul(u.scaleSquared), we = u.scaleSquared === null ? He : He.mul(u.scaleSquared), Ke = f.z.negate().max(1e-4), Xe = n.dofFocusDistance.max(1e-4), ft = n.dofAperture.max(0).mul(0.5).div(Xe).atan(), pt = Ke.sub(Xe).abs().div(Ke), gt = n.focal.x.mul(ft.tan()), Ze = pt.mul(gt), Qe = Ze.mul(Ze).min(v(dt)), ke = r.projectedFilterProfile === "lcc" ? 0.1 : 0.3, Re = ze.add(ke).add(Qe), Ve = Ue.add(ke).add(Qe), Be = we, xt = Re.mul(Ve).sub(Be.mul(Be)).max(1e-9), Je = (r.antialias || r.projectedFilterProfile === "lcc" ? ze.mul(Ue).sub(we.mul(we)).max(0) : ze.add(ke).mul(Ue.add(ke)).sub(we.mul(we)).max(1e-9)).div(xt).sqrt();
|
|
483
|
+
$.assign(
|
|
484
|
+
u.isotropicCovarianceMix === null ? Je : oe(Je, v(1), u.isotropicCovarianceMix)
|
|
485
|
+
);
|
|
486
|
+
const Ye = Re.add(Ve).mul(0.5), et = J(Re.sub(Ve).mul(0.5), Be).length();
|
|
487
|
+
let Q = Ye.add(et), me = Ye.sub(et).max(0);
|
|
488
|
+
if (u.isotropicCovarianceMix !== null) {
|
|
489
|
+
const k = Ot(
|
|
490
|
+
Q,
|
|
491
|
+
me,
|
|
492
|
+
u.isotropicCovarianceMix
|
|
493
|
+
);
|
|
494
|
+
if (Q = k.lambda1, me = k.lambda2, u.isotropicScreenRadiusPx !== null) {
|
|
495
|
+
const N = Lt(
|
|
496
|
+
Q,
|
|
497
|
+
me,
|
|
498
|
+
u.isotropicCovarianceMix,
|
|
499
|
+
u.isotropicScreenRadiusPx,
|
|
500
|
+
v(r.maxStdDev)
|
|
501
|
+
);
|
|
502
|
+
Q = N.lambda1, me = N.lambda2;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const Oe = J(Be, Q.sub(Re)).add(J(1e-6, 0)).normalize();
|
|
506
|
+
let Ie = v(r.maxStdDev);
|
|
507
|
+
if (r.lodAlpha && Z && ie) {
|
|
508
|
+
const k = u.color.a.mul(2), N = k.mul(4).sub(3).min(5);
|
|
509
|
+
Ie = k.greaterThan(1).select(
|
|
510
|
+
v(r.maxStdDev).add(N.sub(1).mul(0.7)),
|
|
511
|
+
v(r.maxStdDev)
|
|
512
|
+
), Z.assign(Ie), ie.assign(k);
|
|
513
|
+
}
|
|
514
|
+
const bt = r.maxAspect && r.maxAspect > 0 ? Q.min(me.mul(r.maxAspect * r.maxAspect)) : Q, tt = v(r.minSplatSizePx ?? 0), st = Oe.mul(
|
|
515
|
+
bt.sqrt().mul(Ie).min(c).max(tt)
|
|
516
|
+
), nt = J(Oe.y, Oe.x.negate()).mul(
|
|
517
|
+
me.sqrt().mul(Ie).min(c).max(tt)
|
|
518
|
+
), Le = () => {
|
|
519
|
+
const k = st.mul(_e.x).add(nt.mul(_e.y)), N = g.xy.div(g.w);
|
|
520
|
+
B.assign(
|
|
521
|
+
K(
|
|
522
|
+
N.add(k.mul(2).div(n.viewport)),
|
|
523
|
+
g.z.div(g.w),
|
|
524
|
+
1
|
|
525
|
+
)
|
|
526
|
+
);
|
|
527
|
+
};
|
|
528
|
+
let ee;
|
|
529
|
+
if (r.foveationMode === "page-table")
|
|
530
|
+
ee = null;
|
|
531
|
+
else if (r.foveationMode === "frontier") {
|
|
532
|
+
const k = f.z.negate(), te = P.x.add(P.w).add(_.y).max(0).mul(1 / 3).sqrt().mul(2), W = _.w, se = W.lessThan(0), ot = W.abs(), wt = ot.equal(0).select(v(zt), ot), at = n.pixelScaleLimit.mul(k), vt = se.select(v(0), te);
|
|
533
|
+
ee = wt.greaterThan(at).and(vt.lessThanEqual(at));
|
|
534
|
+
} else {
|
|
535
|
+
const k = r.maxScreenRadiusPx ?? 0, N = r.minScreenRadiusPx ?? 0, te = Q.sqrt().mul(r.maxStdDev);
|
|
536
|
+
let W = null;
|
|
537
|
+
if (k > 0 && (W = te.lessThanEqual(n.screenBandMax)), N > 0) {
|
|
538
|
+
const se = te.greaterThan(n.screenBandMin);
|
|
539
|
+
W = W ? W.and(se) : se;
|
|
540
|
+
}
|
|
541
|
+
ee = W;
|
|
542
|
+
}
|
|
543
|
+
if (r.performanceProfile === "smooth") {
|
|
544
|
+
const k = st.length(), N = nt.length(), te = u.color.a, W = te.greaterThanEqual(1 / 255).and(k.max(N).mul(2).greaterThanEqual(2)).and(te.mul(k).mul(N).greaterThanEqual(3)), se = u.isotropicCovarianceMix === null ? W : W.or(u.isotropicCovarianceMix.greaterThan(0));
|
|
545
|
+
pe(ee ? se.and(ee) : se, Le);
|
|
546
|
+
} else ee ? pe(ee, Le) : Le();
|
|
547
|
+
}), B;
|
|
548
|
+
})(), e === "display")
|
|
549
|
+
s.fragmentNode = G(() => {
|
|
550
|
+
const b = R.dot(R);
|
|
551
|
+
Ne(b.greaterThan(1));
|
|
552
|
+
let f;
|
|
553
|
+
if (r.lodAlpha && Z && ie) {
|
|
554
|
+
const ue = b.mul(Z.mul(Z).mul(-0.5)).exp(), de = ie.mul(4).sub(3).min(5), Ce = de.mul(de).sub(1).mul(1 / Math.E).exp(), Pe = ue.oneMinus().pow(Ce).oneMinus();
|
|
555
|
+
f = ie.greaterThan(1).select(Pe, ue.mul(ie));
|
|
556
|
+
} else
|
|
557
|
+
f = b.mul(T).exp().mul(x.a);
|
|
558
|
+
const g = f.mul($), B = ve(n.relightMap, Se), p = n.relightSoftness.div(n.viewport.x.max(1)), z = n.relightSoftness.div(n.viewport.y.max(1)), A = B, I = ve(n.relightMap, Se.add(J(p, 0))), P = ve(n.relightMap, Se.add(J(p.negate(), 0))), _ = ve(n.relightMap, Se.add(J(0, z))), ce = ve(n.relightMap, Se.add(J(0, z.negate()))), be = A.a.add(I.a).add(P.a).add(_.a).add(ce.a).max(1e-4), Y = A.rgb.mul(A.a).add(I.rgb.mul(I.a)).add(P.rgb.mul(P.a)).add(_.rgb.mul(_.a)).add(ce.rgb.mul(ce.a)).div(be), le = be.mul(0.2), ye = K(Y, le), Ae = n.relightSoftness.greaterThan(0.5).select(ye, B), Fe = oe(
|
|
559
|
+
S(n.relightBackground),
|
|
560
|
+
Ae.rgb.mul(n.relightBrightness),
|
|
561
|
+
Ae.a
|
|
562
|
+
), Me = oe(x.rgb, x.rgb.mul(Fe), n.relightBlend);
|
|
563
|
+
return K(Me.mul(g), g);
|
|
564
|
+
})(), s.transparent = !0, s.depthTest = !0, s.depthWrite = !1, s.side = h.DoubleSide, s.blending = h.CustomBlending, s.blendSrc = h.OneFactor, s.blendDst = h.OneMinusSrcAlphaFactor, s.blendSrcAlpha = h.OneFactor, s.blendDstAlpha = h.OneMinusSrcAlphaFactor, s.toneMapped = !1;
|
|
565
|
+
else {
|
|
566
|
+
if (!i)
|
|
567
|
+
throw new Error("applySplatMaterialGraph in 'pick' mode requires pick uniforms.");
|
|
568
|
+
s.fragmentNode = G(() => {
|
|
569
|
+
const b = R.dot(R);
|
|
570
|
+
Ne(b.greaterThan(1));
|
|
571
|
+
const g = b.mul(T).exp().mul(x.a).mul($);
|
|
572
|
+
Ne(g.lessThan(i.alphaThreshold));
|
|
573
|
+
const p = F.sub(i.near).div(i.far.sub(i.near)).clamp(0, 1).mul(16777215), z = p.div(65536).floor(), A = p.mod(65536).div(256).floor(), I = p.mod(256).floor();
|
|
574
|
+
return K(z.div(255), A.div(255), I.div(255), 1);
|
|
575
|
+
})(), s.transparent = !1, s.depthTest = !0, s.depthWrite = !0, s.side = h.DoubleSide, s.blending = h.NoBlending, s.toneMapped = !1;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
function Nt(s, e) {
|
|
579
|
+
const t = s.elements;
|
|
580
|
+
return e * Math.hypot(t[2], t[6], t[10]);
|
|
581
|
+
}
|
|
582
|
+
function qt(s, e) {
|
|
583
|
+
const t = s.backend;
|
|
584
|
+
return !t || t.isWebGPUBackend !== !0 || typeof t.has != "function" || typeof t.get != "function" || !t.has(e) ? !1 : t.get(e).buffer !== void 0;
|
|
585
|
+
}
|
|
586
|
+
function Wt(s) {
|
|
587
|
+
const e = s.array, t = e.byteLength;
|
|
588
|
+
if (t === 0) return 0;
|
|
589
|
+
const o = e.constructor;
|
|
590
|
+
return s.array = new o(0), t;
|
|
591
|
+
}
|
|
592
|
+
class Gt {
|
|
593
|
+
constructor(e) {
|
|
594
|
+
l(this, "pending");
|
|
595
|
+
/** Released attributes and the `version` they carried when released. */
|
|
596
|
+
l(this, "released", /* @__PURE__ */ new Map());
|
|
597
|
+
l(this, "releasedBytesValue", 0);
|
|
598
|
+
l(this, "warnedDrift", !1);
|
|
599
|
+
this.pending = [...e];
|
|
600
|
+
}
|
|
601
|
+
/** Nothing left to release. */
|
|
602
|
+
get settled() {
|
|
603
|
+
return this.pending.length === 0;
|
|
604
|
+
}
|
|
605
|
+
/** Bytes still mirrored on the JS heap. */
|
|
606
|
+
get pendingBytes() {
|
|
607
|
+
let e = 0;
|
|
608
|
+
for (const t of this.pending) e += t.array.byteLength;
|
|
609
|
+
return e;
|
|
610
|
+
}
|
|
611
|
+
/** Bytes freed so far. Diagnostic. */
|
|
612
|
+
get releasedBytes() {
|
|
613
|
+
return this.releasedBytesValue;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Releases every pending mirror three has uploaded, and checks the ones
|
|
617
|
+
* already released for version drift. Idempotent and cheap once settled.
|
|
618
|
+
*
|
|
619
|
+
* @returns Bytes freed by this call.
|
|
620
|
+
*/
|
|
621
|
+
release(e) {
|
|
622
|
+
if (this.checkDrift(), this.pending.length === 0) return 0;
|
|
623
|
+
let t = 0;
|
|
624
|
+
for (let o = this.pending.length - 1; o >= 0; o--) {
|
|
625
|
+
const a = this.pending[o];
|
|
626
|
+
qt(e, a) && (t += Wt(a), this.released.set(a, a.version), this.pending.splice(o, 1));
|
|
627
|
+
}
|
|
628
|
+
return this.releasedBytesValue += t, t;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* A released attribute whose `version` moved means someone added a CPU write
|
|
632
|
+
* to a buffer this class promised was GPU-only. Three would then upload the
|
|
633
|
+
* zero-length array - a legal no-op - and the data would simply never reach
|
|
634
|
+
* the GPU. Warn once, so that failure is visible rather than a silent wrong
|
|
635
|
+
* render.
|
|
636
|
+
*/
|
|
637
|
+
checkDrift() {
|
|
638
|
+
if (!(this.warnedDrift || this.released.size === 0)) {
|
|
639
|
+
for (const [e, t] of this.released)
|
|
640
|
+
if (e.version !== t) {
|
|
641
|
+
this.warnedDrift = !0, kt(
|
|
642
|
+
`StorageMirrorReleaser: storage attribute "${e.name || "unnamed"}" was written from the CPU after its mirror was released; that write will not reach the GPU. Remove it from the releaser's attribute list.`
|
|
643
|
+
);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
const j = class j {
|
|
650
|
+
constructor(e) {
|
|
651
|
+
l(this, "kind", "counting");
|
|
652
|
+
l(this, "renderer");
|
|
653
|
+
l(this, "clearPass");
|
|
654
|
+
l(this, "histogramPass");
|
|
655
|
+
l(this, "scanBlocksPass");
|
|
656
|
+
l(this, "scanBlockSumsPass");
|
|
657
|
+
l(this, "addBlockSumOffsetsPass");
|
|
658
|
+
l(this, "addOffsetsPass");
|
|
659
|
+
l(this, "scatterPass");
|
|
660
|
+
/** All stages in dependency order, submitted as one WebGPU compute pass. */
|
|
661
|
+
l(this, "sortPasses");
|
|
662
|
+
/** Sorter-owned working buffers, released on {@link dispose}. */
|
|
663
|
+
l(this, "workingAttributes");
|
|
664
|
+
/** Frees the JS mirrors three keeps behind the GPU-only working buffers. */
|
|
665
|
+
l(this, "mirrors");
|
|
666
|
+
/** Set by {@link dispose}; makes a second dispose a no-op. */
|
|
667
|
+
l(this, "disposed", !1);
|
|
668
|
+
/** Row 2 of the model-view matrix; view-space z = row2 · (position, 1). */
|
|
669
|
+
l(this, "viewRow2", fe(new h.Vector4()));
|
|
670
|
+
l(this, "depthMin", fe(0));
|
|
671
|
+
l(this, "depthScale", fe(0));
|
|
672
|
+
/** Active splat count; a float compares exactly for counts < 2²⁴. */
|
|
673
|
+
l(this, "activeCount", fe(0));
|
|
674
|
+
/** Highest bucket index this sort uses; see {@link effectiveBucketCount}. */
|
|
675
|
+
l(this, "bucketMax", fe(0));
|
|
676
|
+
l(this, "viewCenter", new h.Vector3());
|
|
677
|
+
const { renderer: t, capacity: o, centersTexture: a, dataTextureWidth: n, centersBuffer: r, perSource: i } = e, { BUCKET_COUNT: d, BLOCK_SIZE: c } = j;
|
|
678
|
+
if (!a && !r)
|
|
679
|
+
throw new Error("ComputeSorter: provide centersTexture or centersBuffer.");
|
|
680
|
+
if (a && n === void 0)
|
|
681
|
+
throw new Error("ComputeSorter: dataTextureWidth is required with centersTexture.");
|
|
682
|
+
if (r && i)
|
|
683
|
+
throw new Error("ComputeSorter: work-buffer centers are already in world space.");
|
|
684
|
+
this.renderer = t;
|
|
685
|
+
const T = new h.StorageBufferAttribute(new Uint32Array(d), 1), D = new h.StorageBufferAttribute(
|
|
686
|
+
new Uint32Array(d / c),
|
|
687
|
+
1
|
|
688
|
+
), y = new h.StorageBufferAttribute(
|
|
689
|
+
new Uint32Array(d / c / c),
|
|
690
|
+
1
|
|
691
|
+
), q = new h.StorageBufferAttribute(new Uint32Array(o), 1);
|
|
692
|
+
this.workingAttributes = [
|
|
693
|
+
T,
|
|
694
|
+
D,
|
|
695
|
+
y,
|
|
696
|
+
q
|
|
697
|
+
], this.mirrors = new Gt(this.workingAttributes);
|
|
698
|
+
const M = ne(T, "uint", d).toAtomic(), m = ne(D, "uint", d / c), w = ne(
|
|
699
|
+
y,
|
|
700
|
+
"uint",
|
|
701
|
+
d / c / c
|
|
702
|
+
), V = ne(q, "uint", o), X = ne(e.sourceIndexAttribute, "uint", o), xe = ne(e.splatIndexAttribute, "float", o), ae = r ? ne(r, "vec4", o) : null;
|
|
703
|
+
this.clearPass = G(() => {
|
|
704
|
+
qe(M.element(E), C(0));
|
|
705
|
+
})().compute(d, [c]), this.histogramPass = G(() => {
|
|
706
|
+
pe(v(E).lessThan(this.activeCount), () => {
|
|
707
|
+
const u = L(X.element(E)), x = a ? je(
|
|
708
|
+
u.mod(L(n)),
|
|
709
|
+
u.div(L(n))
|
|
710
|
+
) : null, R = ae ? ae.element(u).xyz : O(a, x).xyz, F = i ? mt(
|
|
711
|
+
i.columns,
|
|
712
|
+
L(O(i.sourceIdTexture, x).r),
|
|
713
|
+
R
|
|
714
|
+
).worldCenter : R, Z = this.viewRow2.xyz.dot(F).add(this.viewRow2.w).sub(this.depthMin).mul(this.depthScale).clamp(0, this.bucketMax).toUint();
|
|
715
|
+
V.element(E).assign(Z), rt(M.element(Z), C(1));
|
|
716
|
+
});
|
|
717
|
+
})().compute(o, [c]), this.scanBlocksPass = G(() => {
|
|
718
|
+
const u = E.mul(C(c)).toVar(), x = C(0).toVar();
|
|
719
|
+
We(c, ({ i: R }) => {
|
|
720
|
+
const F = M.element(u.add(C(R))), $ = it(F).toVar();
|
|
721
|
+
qe(F, x), x.addAssign($);
|
|
722
|
+
}), m.element(E).assign(x);
|
|
723
|
+
})().compute(d / c, [64]), this.scanBlockSumsPass = G(() => {
|
|
724
|
+
const u = E.mul(C(c)).toVar(), x = C(0).toVar();
|
|
725
|
+
We(c, ({ i: R }) => {
|
|
726
|
+
const F = m.element(u.add(C(R))), $ = F.toVar();
|
|
727
|
+
F.assign(x), x.addAssign($);
|
|
728
|
+
}), w.element(E).assign(x);
|
|
729
|
+
})().compute(d / c / c, [64]);
|
|
730
|
+
const re = G(() => {
|
|
731
|
+
pe(E.equal(C(0)), () => {
|
|
732
|
+
const u = C(0).toVar();
|
|
733
|
+
We(d / c / c, ({ i: x }) => {
|
|
734
|
+
const R = w.element(x).toVar();
|
|
735
|
+
w.element(x).assign(u), u.addAssign(R);
|
|
736
|
+
});
|
|
737
|
+
});
|
|
738
|
+
})().compute(1, [64]);
|
|
739
|
+
this.addBlockSumOffsetsPass = G(() => {
|
|
740
|
+
m.element(E).addAssign(w.element(E.div(C(c))));
|
|
741
|
+
})().compute(d / c, [c]), this.addOffsetsPass = G(() => {
|
|
742
|
+
const u = M.element(E), x = m.element(E.shiftRight(C(Math.log2(c))));
|
|
743
|
+
qe(u, it(u).add(x));
|
|
744
|
+
})().compute(d, [c]), this.scatterPass = G(() => {
|
|
745
|
+
pe(v(E).lessThan(this.activeCount), () => {
|
|
746
|
+
const u = X.element(E), x = V.element(E), R = rt(M.element(x), C(1));
|
|
747
|
+
xe.element(R).assign(v(u));
|
|
748
|
+
});
|
|
749
|
+
})().compute(o, [c]), this.sortPasses = [
|
|
750
|
+
this.clearPass,
|
|
751
|
+
this.histogramPass,
|
|
752
|
+
this.scanBlocksPass,
|
|
753
|
+
this.scanBlockSumsPass,
|
|
754
|
+
re,
|
|
755
|
+
this.addBlockSumOffsetsPass,
|
|
756
|
+
this.addOffsetsPass,
|
|
757
|
+
this.scatterPass
|
|
758
|
+
];
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Buckets to actually use for `activeCount` splats, rounded up to a power of
|
|
762
|
+
* two so block indexing stays exact.
|
|
763
|
+
*
|
|
764
|
+
* The histogram is allocated once for the pool's worst case, but clearing and
|
|
765
|
+
* scanning all 2²² buckets costs the same whether one splat is resident or
|
|
766
|
+
* four million - a fixed per-sort bill that dominates on a mobile GPU when
|
|
767
|
+
* the pool is only partly filled (a streaming scene ramping up, or any small
|
|
768
|
+
* scene). Sizing the dispatch to the live splat count keeps the design's
|
|
769
|
+
* ~1-bucket-per-splat depth resolution, so ordering is unaffected, while
|
|
770
|
+
* skipping work on buckets no splat can land in.
|
|
771
|
+
*/
|
|
772
|
+
effectiveBucketCount(e) {
|
|
773
|
+
const o = 2 ** Math.ceil(Math.log2(Math.max(1, e)));
|
|
774
|
+
return Math.min(Math.max(o, j.MIN_BUCKET_COUNT), j.BUCKET_COUNT);
|
|
775
|
+
}
|
|
776
|
+
sort(e, t, o) {
|
|
777
|
+
if (t === 0) return !0;
|
|
778
|
+
const a = e.elements;
|
|
779
|
+
this.viewRow2.value.set(a[2], a[6], a[10], a[14]), this.activeCount.value = t;
|
|
780
|
+
const n = this.effectiveBucketCount(t);
|
|
781
|
+
this.viewCenter.copy(o.center).applyMatrix4(e);
|
|
782
|
+
const r = Nt(e, o.radius), i = this.viewCenter.z - r, d = this.viewCenter.z + r;
|
|
783
|
+
this.depthMin.value = i, this.depthScale.value = (n - 1) / (d - i || 1), this.bucketMax.value = n - 1;
|
|
784
|
+
const c = n / j.BLOCK_SIZE;
|
|
785
|
+
return this.histogramPass.count = t, this.scatterPass.count = t, this.clearPass.count = n, this.scanBlocksPass.count = c, this.scanBlockSumsPass.count = c / j.BLOCK_SIZE, this.addBlockSumOffsetsPass.count = c, this.addOffsetsPass.count = n, this.renderer.compute(this.sortPasses), this.mirrors.settled || this.mirrors.release(this.renderer), !0;
|
|
786
|
+
}
|
|
787
|
+
dispose() {
|
|
788
|
+
if (!this.disposed) {
|
|
789
|
+
this.disposed = !0;
|
|
790
|
+
for (const e of this.sortPasses) e.dispose();
|
|
791
|
+
$t(this.renderer, this.workingAttributes);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
l(j, "BUCKET_COUNT", 1 << 22), l(j, "BLOCK_SIZE", 256), /**
|
|
796
|
+
* Smallest bucket count a sort will dispatch. Below this the fixed passes
|
|
797
|
+
* are already cheap, and the floor keeps every block-scan index exact.
|
|
798
|
+
*/
|
|
799
|
+
l(j, "MIN_BUCKET_COUNT", 65536);
|
|
800
|
+
let ut = j;
|
|
801
|
+
function $t(s, e) {
|
|
802
|
+
const t = s._attributes;
|
|
803
|
+
if (t)
|
|
804
|
+
for (const o of e) t.delete(o);
|
|
805
|
+
}
|
|
806
|
+
const jt = 2e6, Ht = 5e6, Kt = 8e6, Xt = 1e-6;
|
|
807
|
+
function Zt(s) {
|
|
808
|
+
if (s !== void 0 && (!Number.isFinite(s) || s < 0))
|
|
809
|
+
throw new RangeError(
|
|
810
|
+
"SplatMesh sortIntervalMs must be a finite number greater than or equal to 0."
|
|
811
|
+
);
|
|
812
|
+
return s;
|
|
813
|
+
}
|
|
814
|
+
function Qt(s, e = !1) {
|
|
815
|
+
return s < jt ? e ? 33 : 0 : s < Ht ? e ? 66 : 50 : s < Kt ? e ? 133 : 100 : 1e3 / 6;
|
|
816
|
+
}
|
|
817
|
+
class xs {
|
|
818
|
+
constructor(e, t = !1) {
|
|
819
|
+
l(this, "sortIntervalMs");
|
|
820
|
+
l(this, "isMobile");
|
|
821
|
+
l(this, "previousModelView", new h.Matrix4());
|
|
822
|
+
l(this, "hasPreviousModelView", !1);
|
|
823
|
+
l(this, "legacyWasMoving", !1);
|
|
824
|
+
l(this, "forcePending", !0);
|
|
825
|
+
l(this, "lastAcceptedAt", -1 / 0);
|
|
826
|
+
l(this, "acceptedCount", 0);
|
|
827
|
+
this.sortIntervalMs = Zt(e), this.isMobile = t;
|
|
828
|
+
}
|
|
829
|
+
/** Forces the next changed or content-invalidated pose to bypass throttling. */
|
|
830
|
+
invalidate() {
|
|
831
|
+
this.forcePending = !0;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Content changes replace pool indices underneath the current draw order.
|
|
835
|
+
* They must bypass cadence so a newly active range never renders through a
|
|
836
|
+
* stale sort while the camera is moving.
|
|
837
|
+
*/
|
|
838
|
+
invalidateContent() {
|
|
839
|
+
this.forcePending = !0;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Whether an invalidation is still waiting for an accepted sort. The WebGL2
|
|
843
|
+
* worker path consults this directly: it has no cadence, but a content swap
|
|
844
|
+
* under a stationary camera must still trigger a re-sort - the swap reset
|
|
845
|
+
* the draw list to unsorted active order, and without this the scene would
|
|
846
|
+
* render in that unsorted order until the camera next moved (visible
|
|
847
|
+
* blend-order flicker on every streaming swap).
|
|
848
|
+
*/
|
|
849
|
+
hasPendingForce() {
|
|
850
|
+
return this.forcePending;
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Returns whether a sort should be submitted at this timestamp.
|
|
854
|
+
*/
|
|
855
|
+
shouldSubmit(e, t, o, a) {
|
|
856
|
+
return this.shouldSubmitLegacy(e, t, o, a);
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Commits timing state only after the sorter accepts a submission.
|
|
860
|
+
*/
|
|
861
|
+
markAccepted(e) {
|
|
862
|
+
this.lastAcceptedAt = e, this.acceptedCount++, this.forcePending = !1;
|
|
863
|
+
}
|
|
864
|
+
/** Internal diagnostics for the demo HUD; it does not alter scheduling. */
|
|
865
|
+
snapshot() {
|
|
866
|
+
return { acceptedCount: this.acceptedCount, lastAcceptedAt: this.lastAcceptedAt };
|
|
867
|
+
}
|
|
868
|
+
shouldSubmitLegacy(e, t, o, a) {
|
|
869
|
+
let n = !1;
|
|
870
|
+
if (this.hasPreviousModelView) {
|
|
871
|
+
const i = Jt(e, this.previousModelView) > Xt;
|
|
872
|
+
n = this.legacyWasMoving && !i, this.legacyWasMoving = i;
|
|
873
|
+
} else
|
|
874
|
+
this.hasPreviousModelView = !0;
|
|
875
|
+
this.previousModelView.copy(e);
|
|
876
|
+
const r = this.sortIntervalMs ?? Qt(o, this.isMobile);
|
|
877
|
+
return this.forcePending ? !0 : e.equals(t) ? !1 : n ? !0 : r === 0 || a - this.lastAcceptedAt >= r;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function Jt(s, e) {
|
|
881
|
+
let t = 0;
|
|
882
|
+
for (let o = 0; o < 16; o++)
|
|
883
|
+
t = Math.max(t, Math.abs(s.elements[o] - e.elements[o]));
|
|
884
|
+
return t;
|
|
885
|
+
}
|
|
886
|
+
const Ge = new h.Vector2();
|
|
887
|
+
function bs(s, e) {
|
|
888
|
+
var d;
|
|
889
|
+
const t = e.xr;
|
|
890
|
+
if ((t == null ? void 0 : t.isPresenting) !== !0 || typeof t.getCamera != "function") return null;
|
|
891
|
+
t.cameraAutoUpdate !== !1 && typeof t.updateCamera == "function" && t.updateCamera(s);
|
|
892
|
+
const o = t.getCamera(), a = (d = o.cameras) == null ? void 0 : d[0];
|
|
893
|
+
if (!a) return null;
|
|
894
|
+
const n = a.viewport;
|
|
895
|
+
let r = (n == null ? void 0 : n.z) ?? 0, i = (n == null ? void 0 : n.w) ?? 0;
|
|
896
|
+
return (!(r > 0) || !(i > 0)) && (e.getDrawingBufferSize(Ge), r = Ge.x, i = Ge.y), { head: o, eye: a, width: r, height: i };
|
|
897
|
+
}
|
|
898
|
+
function ws(s) {
|
|
899
|
+
return s.isArrayCamera === !0;
|
|
900
|
+
}
|
|
901
|
+
function vs(s, e = {}) {
|
|
902
|
+
const t = s.backend.isWebGPUBackend === !0, o = [...e.requiredFeatures ?? [], ...t ? ["webgpu"] : []], a = e.optionalFeatures ?? [];
|
|
903
|
+
return {
|
|
904
|
+
...e,
|
|
905
|
+
...o.length > 0 ? { requiredFeatures: o } : {},
|
|
906
|
+
...a.length > 0 ? { optionalFeatures: a } : {}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
const Yt = 1, es = 2, ts = 1, ss = 0;
|
|
910
|
+
function Ss(s, e = {
|
|
911
|
+
blend: Yt,
|
|
912
|
+
brightness: es,
|
|
913
|
+
background: ts,
|
|
914
|
+
softness: ss
|
|
915
|
+
}) {
|
|
916
|
+
const t = s.blend !== void 0 ? s.blend : e.blend, o = s.brightness !== void 0 ? s.brightness : e.brightness, a = s.background !== void 0 ? s.background : e.background, n = s.softness !== void 0 ? s.softness : e.softness;
|
|
917
|
+
return {
|
|
918
|
+
blend: Number.isFinite(t) ? Math.min(1, Math.max(0, t)) : e.blend,
|
|
919
|
+
brightness: Number.isFinite(o) ? Math.max(0, o) : e.brightness,
|
|
920
|
+
background: Number.isFinite(a) ? Math.max(0, a) : e.background,
|
|
921
|
+
softness: Number.isFinite(n) ? Math.min(8, Math.max(0, n)) : e.softness
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
function Ts() {
|
|
925
|
+
const s = new Uint8Array([255, 255, 255, 255]), e = new h.DataTexture(s, 1, 1);
|
|
926
|
+
return e.needsUpdate = !0, e.magFilter = h.NearestFilter, e.minFilter = h.NearestFilter, e.generateMipmaps = !1, e;
|
|
927
|
+
}
|
|
928
|
+
export {
|
|
929
|
+
gs as A,
|
|
930
|
+
Zt as B,
|
|
931
|
+
ut as C,
|
|
932
|
+
ts as D,
|
|
933
|
+
Ee as E,
|
|
934
|
+
fs as F,
|
|
935
|
+
Bt as G,
|
|
936
|
+
_t as H,
|
|
937
|
+
It as I,
|
|
938
|
+
ls as J,
|
|
939
|
+
ct as M,
|
|
940
|
+
Gt as S,
|
|
941
|
+
xs as W,
|
|
942
|
+
Yt as a,
|
|
943
|
+
es as b,
|
|
944
|
+
ss as c,
|
|
945
|
+
dt as d,
|
|
946
|
+
De as e,
|
|
947
|
+
is as f,
|
|
948
|
+
Ft as g,
|
|
949
|
+
Dt as h,
|
|
950
|
+
ms as i,
|
|
951
|
+
Ss as j,
|
|
952
|
+
us as k,
|
|
953
|
+
ds as l,
|
|
954
|
+
Ts as m,
|
|
955
|
+
cs as n,
|
|
956
|
+
ps as o,
|
|
957
|
+
Rt as p,
|
|
958
|
+
hs as q,
|
|
959
|
+
$t as r,
|
|
960
|
+
Ut as s,
|
|
961
|
+
Vt as t,
|
|
962
|
+
Ot as u,
|
|
963
|
+
Nt as v,
|
|
964
|
+
Lt as w,
|
|
965
|
+
vs as x,
|
|
966
|
+
bs as y,
|
|
967
|
+
ws as z
|
|
968
|
+
};
|
|
969
|
+
//# sourceMappingURL=relighting-CSQF3UcL.js.map
|