@voluma/vlam 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/chunk-loader-DlNwggfG.js.map +1 -1
- package/dist/{index.d.ts → core/index.d.ts} +1 -1
- package/dist/{splat-budget.d.ts → core/splat-budget.d.ts} +1 -1
- package/dist/{splat-data.d.ts → core/splat-data.d.ts} +1 -1
- package/dist/{splat-mesh-types.d.ts → core/splat-mesh-types.d.ts} +5 -2
- package/dist/{effects.d.ts → effects/index.d.ts} +3 -3
- package/dist/effects.js.map +1 -1
- package/dist/formats/ksplat/parse-ksplat.d.ts +1 -1
- package/dist/formats/ksplat.js.map +1 -1
- package/dist/formats/lcc/collision-mesh.d.ts +2 -2
- package/dist/formats/lcc/collision-partition.d.ts +1 -1
- package/dist/formats/lcc/lcc.d.ts +3 -3
- package/dist/formats/lcc/lcc2.d.ts +2 -2
- package/dist/formats/lcc/parse-lcc.d.ts +1 -1
- package/dist/formats/lcc.js.map +1 -1
- package/dist/formats/ply/parse-compressed-ply.d.ts +2 -2
- package/dist/formats/ply/parse-splat-ply.d.ts +2 -2
- package/dist/formats/ply.js.map +1 -1
- package/dist/formats/rad/frontier-worker-protocol.d.ts +8 -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-foveated-source.d.ts +3 -3
- package/dist/formats/rad/rad.d.ts +5 -5
- package/dist/formats/rad.js.map +1 -1
- package/dist/formats/sog/parse-sog.d.ts +2 -2
- package/dist/formats/sog.js.map +1 -1
- package/dist/formats/splat/parse-splat.d.ts +1 -1
- package/dist/formats/splat.js.map +1 -1
- package/dist/formats/spz/parse-spz.d.ts +1 -1
- package/dist/formats/spz.js.map +1 -1
- package/dist/half-float-Cs4FDq8Q.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/{chunk-loader.d.ts → loaders/chunk-loader.d.ts} +2 -2
- package/dist/{load-splat-data.d.ts → loaders/load-splat-data.d.ts} +1 -1
- package/dist/{load-worker-protocol.d.ts → loaders/load-worker-protocol.d.ts} +2 -2
- package/dist/loaders.js.map +1 -1
- package/dist/loading-wLo8vRbA.js.map +1 -1
- package/dist/lod-scheduler-B0a_uBlv.js.map +1 -1
- package/dist/logging-BfPdd7NJ.js.map +1 -1
- package/dist/ply-header-B9WllbPg.js.map +1 -1
- package/dist/{radix-sorter-R0FCSqKu.js → radix-sorter-BrbUg_CV.js} +2 -2
- package/dist/radix-sorter-BrbUg_CV.js.map +1 -0
- package/dist/{relighting-CSQF3UcL.js → relighting-Tiwep8yd.js} +302 -294
- package/dist/relighting-Tiwep8yd.js.map +1 -0
- package/dist/{selection-volume.d.ts → selection/selection-volume.d.ts} +1 -1
- package/dist/{splat-partition.d.ts → selection/splat-partition.d.ts} +1 -1
- package/dist/selection.js.map +1 -1
- package/dist/sh-pack-D5wAe5gg.js.map +1 -1
- package/dist/splat-budget-DuVZspPQ.js.map +1 -1
- package/dist/splat-data-BZM5dhhx.js.map +1 -1
- package/dist/{splat-mesh-aQdcWA6v.js → splat-mesh-CsLOQb08.js} +3 -3
- package/dist/splat-mesh-CsLOQb08.js.map +1 -0
- package/dist/splat-mesh-types-BZIko-_9.js.map +1 -1
- package/dist/{static-lod-splat-mesh.d.ts → static-lod/static-lod-splat-mesh.d.ts} +2 -2
- package/dist/{static-lod-worker-protocol.d.ts → static-lod/static-lod-worker-protocol.d.ts} +1 -1
- package/dist/{static-lod.d.ts → static-lod/static-lod.d.ts} +1 -1
- package/dist/static-lod.js +1 -1
- package/dist/static-lod.js.map +1 -1
- package/dist/{dataset-source.d.ts → streaming/dataset-source.d.ts} +1 -1
- package/dist/{streaming.d.ts → streaming/index.d.ts} +3 -3
- package/dist/{lod-source.d.ts → streaming/lod-source.d.ts} +4 -4
- package/dist/{streamed-splat-mesh-utils.d.ts → streaming/streamed-splat-mesh-utils.d.ts} +2 -2
- package/dist/{streamed-splat-mesh.d.ts → streaming/streamed-splat-mesh.d.ts} +45 -5
- package/dist/streaming.js +844 -810
- package/dist/streaming.js.map +1 -1
- package/dist/{unified-splat-mesh.d.ts → unified/unified-splat-mesh.d.ts} +13 -6
- package/dist/{work-buffer-gather.d.ts → unified/work-buffer-gather.d.ts} +5 -5
- package/dist/{work-buffer-material.d.ts → unified/work-buffer-material.d.ts} +1 -1
- package/dist/unified.js +280 -272
- package/dist/unified.js.map +1 -1
- package/dist/webgpu-limits-Y3CI_6_6.js.map +1 -1
- package/package.json +9 -9
- package/dist/radix-sorter-R0FCSqKu.js.map +0 -1
- package/dist/relighting-CSQF3UcL.js.map +0 -1
- package/dist/splat-mesh-aQdcWA6v.js.map +0 -1
- /package/dist/{compute-sorter.d.ts → core/compute-sorter.d.ts} +0 -0
- /package/dist/{create-splat-renderer.d.ts → core/create-splat-renderer.d.ts} +0 -0
- /package/dist/{depth-of-field.d.ts → core/depth-of-field.d.ts} +0 -0
- /package/dist/{half-float.d.ts → core/half-float.d.ts} +0 -0
- /package/dist/{logging.d.ts → core/logging.d.ts} +0 -0
- /package/dist/{merged-splat-mesh.d.ts → core/merged-splat-mesh.d.ts} +0 -0
- /package/dist/{orientation.d.ts → core/orientation.d.ts} +0 -0
- /package/dist/{radix-sort.d.ts → core/radix-sort.d.ts} +0 -0
- /package/dist/{radix-sorter.d.ts → core/radix-sorter.d.ts} +0 -0
- /package/dist/{relighting-pass.d.ts → core/relighting-pass.d.ts} +0 -0
- /package/dist/{relighting.d.ts → core/relighting.d.ts} +0 -0
- /package/dist/{sh-pack.d.ts → core/sh-pack.d.ts} +0 -0
- /package/dist/{sort-scheduler.d.ts → core/sort-scheduler.d.ts} +0 -0
- /package/dist/{sort-worker-protocol.d.ts → core/sort-worker-protocol.d.ts} +0 -0
- /package/dist/{sorter.d.ts → core/sorter.d.ts} +0 -0
- /package/dist/{source-transform.d.ts → core/source-transform.d.ts} +0 -0
- /package/dist/{splat-depth-pack.d.ts → core/splat-depth-pack.d.ts} +0 -0
- /package/dist/{splat-mesh-material.d.ts → core/splat-mesh-material.d.ts} +0 -0
- /package/dist/{splat-mesh-picking.d.ts → core/splat-mesh-picking.d.ts} +0 -0
- /package/dist/{splat-mesh-pool.d.ts → core/splat-mesh-pool.d.ts} +0 -0
- /package/dist/{splat-mesh.d.ts → core/splat-mesh.d.ts} +0 -0
- /package/dist/{splat-modifier-stack.d.ts → core/splat-modifier-stack.d.ts} +0 -0
- /package/dist/{splat-modifier.d.ts → core/splat-modifier.d.ts} +0 -0
- /package/dist/{splat-query.d.ts → core/splat-query.d.ts} +0 -0
- /package/dist/{splat-sort-bounds.d.ts → core/splat-sort-bounds.d.ts} +0 -0
- /package/dist/{storage-attribute-mirror.d.ts → core/storage-attribute-mirror.d.ts} +0 -0
- /package/dist/{webgpu-limits.d.ts → core/webgpu-limits.d.ts} +0 -0
- /package/dist/{worker-sorter.d.ts → core/worker-sorter.d.ts} +0 -0
- /package/dist/{xr-view.d.ts → core/xr-view.d.ts} +0 -0
- /package/dist/{loaders.d.ts → loaders/index.d.ts} +0 -0
- /package/dist/{loading.d.ts → loaders/loading.d.ts} +0 -0
- /package/dist/{ply-header.d.ts → loaders/ply-header.d.ts} +0 -0
- /package/dist/{selection.d.ts → selection/index.d.ts} +0 -0
- /package/dist/{static-lod-entry.d.ts → static-lod/index.d.ts} +0 -0
- /package/dist/{budget-governor.d.ts → streaming/budget-governor.d.ts} +0 -0
- /package/dist/{camera-budget-governor.d.ts → streaming/camera-budget-governor.d.ts} +0 -0
- /package/dist/{chunk-cache-budget.d.ts → streaming/chunk-cache-budget.d.ts} +0 -0
- /package/dist/{chunk-fetch-scheduler.d.ts → streaming/chunk-fetch-scheduler.d.ts} +0 -0
- /package/dist/{lod-manifest.d.ts → streaming/lod-manifest.d.ts} +0 -0
- /package/dist/{lod-scheduler.d.ts → streaming/lod-scheduler.d.ts} +0 -0
- /package/dist/{unified.d.ts → unified/index.d.ts} +0 -0
- /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
|
|
3
|
-
var s = (
|
|
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
|
|
6
|
-
import { S as
|
|
7
|
-
import { RadixSorter as
|
|
8
|
-
import { i as
|
|
9
|
-
import { a as
|
|
10
|
-
const
|
|
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
|
|
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 +
|
|
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
|
|
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(
|
|
61
|
-
let
|
|
62
|
-
class
|
|
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",
|
|
77
|
-
s(this, "targetOffset",
|
|
78
|
-
s(this, "sourceMatrix",
|
|
79
|
-
s(this, "cameraViewMatrix",
|
|
80
|
-
s(this, "opacity",
|
|
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:
|
|
84
|
+
sourceCapacity: i,
|
|
85
85
|
sourceIndex: a,
|
|
86
86
|
centersTexture: c,
|
|
87
|
-
colorsTexture:
|
|
88
|
-
covarianceATexture:
|
|
87
|
+
colorsTexture: S,
|
|
88
|
+
covarianceATexture: B,
|
|
89
89
|
covarianceBTexture: u,
|
|
90
|
-
dataTextureWidth:
|
|
91
|
-
} = n,
|
|
92
|
-
this.workBuffer = n.workBuffer ?? new
|
|
93
|
-
const
|
|
94
|
-
this.pass =
|
|
95
|
-
ze(
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
),
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
109
|
-
|
|
108
|
+
m,
|
|
109
|
+
g.sub(y).normalize()
|
|
110
110
|
)
|
|
111
111
|
).clamp(0, 1),
|
|
112
|
-
|
|
113
|
-
),
|
|
114
|
-
index:
|
|
115
|
-
localCenter:
|
|
116
|
-
color:
|
|
117
|
-
makeWorldCenter: () =>
|
|
118
|
-
makeViewCenter: () => this.cameraViewMatrix.mul(
|
|
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
|
|
121
|
-
return
|
|
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: (
|
|
124
|
-
const
|
|
125
|
-
if (!
|
|
123
|
+
makeChannel: (U) => {
|
|
124
|
+
const X = T.get(U);
|
|
125
|
+
if (!X)
|
|
126
126
|
throw new Error(
|
|
127
|
-
`UnifiedSplatMesh: source modifier reads undefined channel "${
|
|
127
|
+
`UnifiedSplatMesh: source modifier reads undefined channel "${U}".`
|
|
128
128
|
);
|
|
129
|
-
return ee(
|
|
129
|
+
return ee(X.texture, m).r;
|
|
130
130
|
}
|
|
131
|
-
}),
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
const U = h.isotropicVarianceScale ?? A(Ye);
|
|
141
|
+
z = Ze(
|
|
142
|
+
z,
|
|
143
|
+
R(0, 0, 1),
|
|
142
144
|
h.isotropicCovarianceMix,
|
|
143
|
-
|
|
145
|
+
U
|
|
144
146
|
);
|
|
145
147
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
h.isotropicCovarianceMix === null ?
|
|
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(
|
|
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,
|
|
155
|
-
if (e < 0 ||
|
|
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 =
|
|
158
|
-
const
|
|
159
|
-
this.cameraViewMatrix.value.copy(
|
|
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 :
|
|
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
|
|
191
|
-
const n = new l.NodeMaterial(), e =
|
|
192
|
-
return n.vertexNode =
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
),
|
|
200
|
-
|
|
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
|
-
|
|
203
|
-
),
|
|
204
|
+
t.focal.x.negate().mul(o.x).mul(v)
|
|
205
|
+
), G = R(
|
|
204
206
|
0,
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
),
|
|
208
|
-
V.assign(
|
|
209
|
-
const
|
|
210
|
-
let
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
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
|
-
|
|
217
|
-
u.element(
|
|
218
|
-
|
|
218
|
+
K,
|
|
219
|
+
u.element(p),
|
|
220
|
+
t.maxStdDev
|
|
219
221
|
);
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
J.sqrt().mul(
|
|
225
|
-
),
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
),
|
|
230
|
-
return
|
|
231
|
-
})(), n.fragmentNode =
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
),
|
|
239
|
-
return
|
|
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
|
|
243
|
-
function
|
|
244
|
-
if (!Number.isFinite(
|
|
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
|
|
248
|
-
return
|
|
249
|
+
function vt(t) {
|
|
250
|
+
return Te(t), Math.floor(t) * pt;
|
|
249
251
|
}
|
|
250
|
-
function
|
|
251
|
-
return
|
|
252
|
+
function gt(t) {
|
|
253
|
+
return Te(t), Math.floor(t) * mt;
|
|
252
254
|
}
|
|
253
|
-
function
|
|
254
|
-
return
|
|
255
|
+
function Ct(t) {
|
|
256
|
+
return gt(t) * 2;
|
|
255
257
|
}
|
|
256
|
-
function
|
|
258
|
+
function xe(t) {
|
|
257
259
|
var n;
|
|
258
|
-
return ((n =
|
|
260
|
+
return ((n = t.backend) == null ? void 0 : n.isWebGPUBackend) === !0;
|
|
259
261
|
}
|
|
260
|
-
class
|
|
261
|
-
constructor(e,
|
|
262
|
-
if (!
|
|
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
|
-
|
|
267
|
-
const c = new
|
|
268
|
-
|
|
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
|
-
),
|
|
273
|
+
), b.instanceCount = 0;
|
|
272
274
|
super(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
capacity:
|
|
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:
|
|
283
|
-
focal:
|
|
284
|
-
viewport:
|
|
284
|
+
order: w,
|
|
285
|
+
focal: S,
|
|
286
|
+
viewport: B,
|
|
285
287
|
maxStdDev: u,
|
|
286
|
-
minSplatSizePx:
|
|
287
|
-
antialias:
|
|
288
|
+
minSplatSizePx: f,
|
|
289
|
+
antialias: D,
|
|
288
290
|
projectedLowPassVariance: V,
|
|
289
|
-
compensateProjectedLowPass:
|
|
290
|
-
dofFocusDistance:
|
|
291
|
-
dofAperture:
|
|
292
|
-
relightMap:
|
|
293
|
-
relightBlend:
|
|
294
|
-
relightBrightness:
|
|
295
|
-
relightBackground:
|
|
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
|
|
363
|
-
for (let
|
|
364
|
-
this.workBuffer = c, this.focal =
|
|
365
|
-
const
|
|
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:
|
|
369
|
+
capacity: i,
|
|
368
370
|
centersBuffer: c.centers,
|
|
369
|
-
splatIndexAttribute:
|
|
371
|
+
splatIndexAttribute: w,
|
|
370
372
|
sourceIndexAttribute: this.workSourceIndex
|
|
371
373
|
};
|
|
372
|
-
this.sorter = a.sortStrategy === "exact" ? new
|
|
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,
|
|
380
|
-
if (this.assertNotDisposed("addSource"), this.sources.some((
|
|
381
|
-
const a = e.getUnifiedSourceView(), c =
|
|
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
|
|
403
|
-
this.projectedLowPassVariance.value =
|
|
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:
|
|
411
|
-
opacity:
|
|
412
|
+
priority: i.priority ?? 0,
|
|
413
|
+
opacity: i.opacity ?? 1,
|
|
412
414
|
visible: c,
|
|
413
|
-
cacheModifiers:
|
|
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
|
|
432
|
-
return
|
|
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
|
-
/**
|
|
443
|
-
|
|
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 =
|
|
455
|
+
a.opacity = i;
|
|
448
456
|
}
|
|
449
457
|
/** Shows or hides a source without changing its residency. */
|
|
450
|
-
setSourceVisible(e,
|
|
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 =
|
|
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
|
|
463
|
-
this.dofFocusDistance.value =
|
|
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
|
|
483
|
-
this.relightBlend.value =
|
|
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,
|
|
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
|
|
522
|
+
const S = await Promise.all(
|
|
515
523
|
c.map(async (u) => {
|
|
516
|
-
const
|
|
517
|
-
return
|
|
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
|
|
522
|
-
for (const u of
|
|
529
|
+
let B = null;
|
|
530
|
+
for (const u of S) {
|
|
523
531
|
if (u === null) continue;
|
|
524
|
-
const
|
|
525
|
-
|
|
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
|
|
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
|
|
533
|
-
if (
|
|
534
|
-
const [a] = this.sources.splice(
|
|
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,
|
|
554
|
+
renderView(e, i, a = null) {
|
|
547
555
|
if (this.disposed) return;
|
|
548
|
-
if (
|
|
556
|
+
if (i !== this.renderer)
|
|
549
557
|
throw new Error("UnifiedSplatMesh: renderView must use its construction renderer.");
|
|
550
|
-
if (!
|
|
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
|
|
564
|
+
const S = i.getRenderTarget();
|
|
557
565
|
try {
|
|
558
|
-
|
|
566
|
+
i.setRenderTarget(a), i.render(this, e);
|
|
559
567
|
} finally {
|
|
560
|
-
|
|
568
|
+
i.setRenderTarget(S), this.sortScheduler.invalidate();
|
|
561
569
|
}
|
|
562
570
|
}
|
|
563
|
-
prepare(e,
|
|
564
|
-
if (!
|
|
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 =
|
|
570
|
-
|
|
571
|
-
const
|
|
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
|
|
574
|
-
this.focal.value.set(
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
for (let
|
|
578
|
-
const
|
|
579
|
-
|
|
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
|
-
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
let
|
|
585
|
-
for (const
|
|
586
|
-
const
|
|
587
|
-
if (
|
|
588
|
-
const d = this.createGather(
|
|
589
|
-
|
|
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 (!
|
|
592
|
-
|
|
599
|
+
if (!r.visible) {
|
|
600
|
+
r.lastGather = null;
|
|
593
601
|
continue;
|
|
594
602
|
}
|
|
595
|
-
if (
|
|
596
|
-
|
|
603
|
+
if (o.activeCount === 0) {
|
|
604
|
+
r.lastGather = null;
|
|
597
605
|
continue;
|
|
598
606
|
}
|
|
599
|
-
if (
|
|
600
|
-
this.overflowedSourceCount++, this.overflowedSplatCount +=
|
|
607
|
+
if (p + o.activeCount > this.workBuffer.capacity) {
|
|
608
|
+
this.overflowedSourceCount++, this.overflowedSplatCount += o.activeCount, r.lastGather = null;
|
|
601
609
|
continue;
|
|
602
610
|
}
|
|
603
|
-
|
|
611
|
+
r.offset = p, y.push(r), this.bounds.union(o.worldBounds), p += o.activeCount;
|
|
604
612
|
}
|
|
605
|
-
let
|
|
606
|
-
for (const
|
|
607
|
-
const
|
|
608
|
-
|
|
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
|
-
(
|
|
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
|
-
!
|
|
622
|
+
!o.hasSourcePlacement || (r.gather.gather(
|
|
615
623
|
this.renderer,
|
|
616
|
-
|
|
624
|
+
o.activeCount,
|
|
617
625
|
d,
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
),
|
|
622
|
-
activeCount:
|
|
623
|
-
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:
|
|
626
|
-
matrixWorld:
|
|
627
|
-
localCameraPosition:
|
|
628
|
-
} : (
|
|
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
|
|
631
|
-
if (this.previousAdmittedTotal =
|
|
632
|
-
for (let
|
|
633
|
-
const
|
|
634
|
-
if (d.source !==
|
|
635
|
-
|
|
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 (
|
|
640
|
-
this.previousLayout =
|
|
641
|
-
source:
|
|
642
|
-
offset:
|
|
643
|
-
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
|
|
653
|
+
for (const r of this.previousLayout) this.previousLayoutBySource.set(r.source, r);
|
|
646
654
|
}
|
|
647
|
-
if ((
|
|
648
|
-
const
|
|
649
|
-
(a || this.sortScheduler.shouldSubmit(
|
|
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 =
|
|
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(),
|
|
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 =
|
|
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
|
|
704
|
-
return
|
|
705
|
-
}),
|
|
711
|
+
const i = this.buildGather(e);
|
|
712
|
+
return i.warmUp(this.renderer).catch(() => {
|
|
713
|
+
}), i;
|
|
706
714
|
}
|
|
707
715
|
buildGather(e) {
|
|
708
|
-
return new
|
|
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
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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
|