@onerjs/core 8.51.6 → 8.51.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/Cameras/inputMapper.js +13 -9
  2. package/Cameras/inputMapper.js.map +1 -1
  3. package/Engines/AbstractEngine/abstractEngine.views.pure.js.map +1 -1
  4. package/Engines/AbstractEngine/abstractEngine.views.types.d.ts +2 -1
  5. package/Engines/AbstractEngine/abstractEngine.views.types.js.map +1 -1
  6. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.d.ts +5 -0
  7. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js +8 -0
  8. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js.map +1 -0
  9. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.d.ts +278 -0
  10. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js +718 -0
  11. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js.map +1 -0
  12. package/Materials/GaussianSplatting/pure.d.ts +1 -0
  13. package/Materials/GaussianSplatting/pure.js +1 -0
  14. package/Materials/GaussianSplatting/pure.js.map +1 -1
  15. package/Materials/Textures/internalTexture.js +7 -0
  16. package/Materials/Textures/internalTexture.js.map +1 -1
  17. package/Materials/index.d.ts +1 -0
  18. package/Materials/index.js +1 -0
  19. package/Materials/index.js.map +1 -1
  20. package/Materials/pure.d.ts +1 -0
  21. package/Materials/pure.js +1 -0
  22. package/Materials/pure.js.map +1 -1
  23. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.d.ts +7 -0
  24. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js +8 -0
  25. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js.map +1 -0
  26. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.d.ts +147 -0
  27. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js +257 -0
  28. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js.map +1 -0
  29. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +11 -0
  30. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +31 -0
  31. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  32. package/Meshes/GaussianSplatting/pure.d.ts +1 -0
  33. package/Meshes/GaussianSplatting/pure.js +1 -0
  34. package/Meshes/GaussianSplatting/pure.js.map +1 -1
  35. package/Meshes/abstractMesh.pure.js +3 -0
  36. package/Meshes/abstractMesh.pure.js.map +1 -1
  37. package/Meshes/index.d.ts +1 -0
  38. package/Meshes/index.js +1 -0
  39. package/Meshes/index.js.map +1 -1
  40. package/Meshes/pure.d.ts +1 -0
  41. package/Meshes/pure.js +1 -0
  42. package/Meshes/pure.js.map +1 -1
  43. package/Shaders/ShadersInclude/gaussianSplatting.js +33 -10
  44. package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
  45. package/Shaders/gaussianSplatting.vertex.js +20 -1
  46. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  47. package/Shaders/picking.fragment.js +4 -1
  48. package/Shaders/picking.fragment.js.map +1 -1
  49. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +33 -10
  50. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
  51. package/ShadersWGSL/gaussianSplatting.vertex.js +21 -2
  52. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  53. package/package.json +1 -1
  54. package/scene.pure.js.map +1 -1
@@ -0,0 +1,718 @@
1
+ /** This file must only contain pure code and pure imports */
2
+ import { MaterialDefines } from "../materialDefines.js";
3
+ import { MaterialPluginBase } from "../materialPluginBase.pure.js";
4
+ import { RegisterClass } from "../../Misc/typeStore.js";
5
+ import { Logger } from "../../Misc/logger.js";
6
+ import { GetGaussianSplattingMaxPartCount } from "./gaussianSplattingMaterial.pure.js";
7
+ import { RawTexture } from "../Textures/rawTexture.js";
8
+
9
+ /** @internal */
10
+ class GaussianSplattingDebugDefines extends MaterialDefines {
11
+ constructor() {
12
+ super(...arguments);
13
+ /** Defines whether any debug feature is active */
14
+ this.GS_DBG_ENABLED = false;
15
+ /** Defines whether world-space clipping box is enabled (0: off, 1: on) */
16
+ this.GS_DBG_CLIP = 0;
17
+ /** Defines whether opacity culling is enabled (0: off, 1: on) */
18
+ this.GS_DBG_CULL_OPACITY = 0;
19
+ /** Defines whether size culling is enabled (0: off, 1: on) */
20
+ this.GS_DBG_CULL_SIZE = 0;
21
+ /** Defines whether per-splat opacity scaling is enabled (0: off, 1: on) */
22
+ this.GS_DBG_OPACITY_SCALE = 0;
23
+ /** Defines whether opacity saturation (flat disk) is enabled (0: off, 1: on) */
24
+ this.GS_DBG_OPACITY_SATURATE = 0;
25
+ /** Defines whether the DC (base) SH color is included (0: off, 1: on) */
26
+ this.GS_DBG_SH_DC = 1;
27
+ /** Defines whether SH band 1 contribution is included (0: off, 1: on) */
28
+ this.GS_DBG_SH_ORDER1 = 1;
29
+ /** Defines whether SH band 2 contribution is included (0: off, 1: on) */
30
+ this.GS_DBG_SH_ORDER2 = 1;
31
+ /** Defines whether SH band 3 contribution is included (0: off, 1: on) */
32
+ this.GS_DBG_SH_ORDER3 = 1;
33
+ /** Defines whether SH band 4 contribution is included (0: off, 1: on) */
34
+ this.GS_DBG_SH_ORDER4 = 1;
35
+ }
36
+ }
37
+ /**
38
+ * Debug plugin for GaussianSplattingMaterial.
39
+ * Provides runtime controls for clipping, opacity/size culling, opacity scaling,
40
+ * opacity saturation, and per-SH-order toggling. All features are gated behind
41
+ * the GS_DBG_ENABLED shader define — when every option is at its default value
42
+ * the define is absent and the shader compiles to identical code as without the plugin.
43
+ *
44
+ * In compound mode (partCount \> 0), per-part overrides can be set via setPartOptions().
45
+ * Global settings act as defaults; per-part settings override them for that part index.
46
+ */
47
+ export class GaussianSplattingDebugMaterialPlugin extends MaterialPluginBase {
48
+ /**
49
+ * Creates a new GaussianSplattingDebugMaterialPlugin.
50
+ * @param material The GaussianSplattingMaterial to attach the plugin to.
51
+ */
52
+ constructor(material) {
53
+ super(material, "GaussianSplattingDebug", 200, new GaussianSplattingDebugDefines(), true, true);
54
+ this._clippingBox = null;
55
+ this._opacityCulling = null;
56
+ this._sizeCulling = null;
57
+ this._opacityScale = 1.0;
58
+ this._opacitySaturate = false;
59
+ this._shDc = true;
60
+ this._shOrder1 = true;
61
+ this._shOrder2 = true;
62
+ this._shOrder3 = true;
63
+ this._shOrder4 = true;
64
+ // Per-part state (only populated when partCount > 0)
65
+ this._partCount = 0;
66
+ this._partClippingBoxes = [];
67
+ this._partOpacityCullings = [];
68
+ this._partSizeCullings = [];
69
+ this._partOpacityScales = [];
70
+ this._partOpacitySaturates = [];
71
+ this._partShDcs = [];
72
+ this._partShOrder1s = [];
73
+ this._partShOrder2s = [];
74
+ this._partShOrder3s = [];
75
+ this._partShOrder4s = [];
76
+ // Per-part debug LUT: MAX_PART_COUNT × 5 RGBA float texture (dbgPartData)
77
+ this._dbgPartDataTexture = null;
78
+ this._textureDirty = false;
79
+ this._maxPartCount = 0;
80
+ }
81
+ _isAnyFeatureActive() {
82
+ return (this._clippingBox !== null ||
83
+ this._opacityCulling !== null ||
84
+ this._sizeCulling !== null ||
85
+ this._opacityScale !== 1.0 ||
86
+ this._opacitySaturate ||
87
+ !this._shDc ||
88
+ !this._shOrder1 ||
89
+ !this._shOrder2 ||
90
+ !this._shOrder3 ||
91
+ !this._shOrder4 ||
92
+ this._partClippingBoxes.some((b) => b !== null) ||
93
+ this._partOpacityCullings.some((b) => b !== null) ||
94
+ this._partSizeCullings.some((b) => b !== null) ||
95
+ this._partOpacityScales.some((s) => s !== null) ||
96
+ this._partOpacitySaturates.some((s) => s !== null) ||
97
+ this._partShDcs.some((s) => s !== null) ||
98
+ this._partShOrder1s.some((s) => s !== null) ||
99
+ this._partShOrder2s.some((s) => s !== null) ||
100
+ this._partShOrder3s.some((s) => s !== null) ||
101
+ this._partShOrder4s.some((s) => s !== null));
102
+ }
103
+ _markDirty() {
104
+ this.markAllDefinesAsDirty();
105
+ this._textureDirty = true;
106
+ }
107
+ // ----- Public API -----
108
+ /**
109
+ * Number of parts in compound mode. Set automatically by GaussianSplattingDebugger.addMesh().
110
+ * When 0 (non-compound), setPartOptions() logs an error.
111
+ * @returns the part count
112
+ */
113
+ get partCount() {
114
+ return this._partCount;
115
+ }
116
+ set partCount(count) {
117
+ if (this._partCount !== count) {
118
+ this._partCount = count;
119
+ this._markDirty();
120
+ }
121
+ }
122
+ /**
123
+ * Sets per-part debug overrides for the given part index.
124
+ * Only valid on compound meshes (partCount \> 0); logs an error otherwise.
125
+ * @param partIndex The zero-based part index.
126
+ * @param options Partial set of debug options to override for this part.
127
+ */
128
+ setPartOptions(partIndex, options) {
129
+ if (this._partCount === 0) {
130
+ Logger.Error("GaussianSplattingDebugMaterialPlugin.setPartOptions: called on a non-compound mesh. partCount is 0.");
131
+ return;
132
+ }
133
+ if (options.clippingBox !== undefined) {
134
+ this._partClippingBoxes[partIndex] = options.clippingBox;
135
+ }
136
+ if (options.opacityCulling !== undefined) {
137
+ this._partOpacityCullings[partIndex] = options.opacityCulling;
138
+ }
139
+ if (options.sizeCulling !== undefined) {
140
+ this._partSizeCullings[partIndex] = options.sizeCulling;
141
+ }
142
+ if (options.opacityScale !== undefined) {
143
+ this._partOpacityScales[partIndex] = options.opacityScale;
144
+ }
145
+ if (options.opacitySaturate !== undefined) {
146
+ this._partOpacitySaturates[partIndex] = options.opacitySaturate;
147
+ }
148
+ if (options.shDc !== undefined) {
149
+ this._partShDcs[partIndex] = options.shDc;
150
+ }
151
+ if (options.shOrder1 !== undefined) {
152
+ this._partShOrder1s[partIndex] = options.shOrder1;
153
+ }
154
+ if (options.shOrder2 !== undefined) {
155
+ this._partShOrder2s[partIndex] = options.shOrder2;
156
+ }
157
+ if (options.shOrder3 !== undefined) {
158
+ this._partShOrder3s[partIndex] = options.shOrder3;
159
+ }
160
+ if (options.shOrder4 !== undefined) {
161
+ this._partShOrder4s[partIndex] = options.shOrder4;
162
+ }
163
+ this._markDirty();
164
+ }
165
+ /**
166
+ * Clears all per-part debug overrides for the given part index,
167
+ * falling back to global settings.
168
+ * @param partIndex The zero-based part index.
169
+ */
170
+ clearPartOptions(partIndex) {
171
+ this._partClippingBoxes[partIndex] = null;
172
+ this._partOpacityCullings[partIndex] = null;
173
+ this._partSizeCullings[partIndex] = null;
174
+ this._partOpacityScales[partIndex] = null;
175
+ this._partOpacitySaturates[partIndex] = null;
176
+ this._partShDcs[partIndex] = null;
177
+ this._partShOrder1s[partIndex] = null;
178
+ this._partShOrder2s[partIndex] = null;
179
+ this._partShOrder3s[partIndex] = null;
180
+ this._partShOrder4s[partIndex] = null;
181
+ this._markDirty();
182
+ }
183
+ /**
184
+ * World-space axis-aligned clipping box. Splats outside are not rendered.
185
+ * Set to null to disable clipping.
186
+ * Example: `{ min: new Vector3(-2,-2,-2), max: new Vector3(2,2,2) }`
187
+ */
188
+ get clippingBox() {
189
+ return this._clippingBox;
190
+ }
191
+ set clippingBox(value) {
192
+ this._clippingBox = value;
193
+ this._markDirty();
194
+ }
195
+ /**
196
+ * Opacity culling range [0..1]. Splats whose stored opacity falls outside this
197
+ * range are not rendered. Set to null to disable.
198
+ */
199
+ get opacityCulling() {
200
+ return this._opacityCulling;
201
+ }
202
+ set opacityCulling(value) {
203
+ this._opacityCulling = value;
204
+ this._markDirty();
205
+ }
206
+ /**
207
+ * Size culling range. Size is pow(|det(Σ)|, 1/6) of the 3D covariance matrix,
208
+ * equal to the geometric mean of the principal radii. Use GaussianSplattingMeshBase.splatSizeRange
209
+ * to find the asset's range. Set to null to disable.
210
+ */
211
+ get sizeCulling() {
212
+ return this._sizeCulling;
213
+ }
214
+ set sizeCulling(value) {
215
+ this._sizeCulling = value;
216
+ this._markDirty();
217
+ }
218
+ /**
219
+ * Scalar multiplier applied to every splat's opacity after all other modifiers.
220
+ * 1.0 (default) = no change.
221
+ */
222
+ get opacityScale() {
223
+ return this._opacityScale;
224
+ }
225
+ set opacityScale(value) {
226
+ this._opacityScale = value;
227
+ this._markDirty();
228
+ }
229
+ /**
230
+ * When true, replaces the Gaussian spatial falloff with a flat uniform opacity,
231
+ * making each splat appear as a solid disk with its raw alpha value.
232
+ */
233
+ get opacitySaturate() {
234
+ return this._opacitySaturate;
235
+ }
236
+ set opacitySaturate(value) {
237
+ this._opacitySaturate = value;
238
+ this._markDirty();
239
+ }
240
+ /** Include the DC (base) color from colorsTexture. Default: true. */
241
+ get shDc() {
242
+ return this._shDc;
243
+ }
244
+ set shDc(value) {
245
+ this._shDc = value;
246
+ this._markDirty();
247
+ }
248
+ /** Include SH band 1 contribution. Default: true. */
249
+ get shOrder1() {
250
+ return this._shOrder1;
251
+ }
252
+ set shOrder1(value) {
253
+ this._shOrder1 = value;
254
+ this._markDirty();
255
+ }
256
+ /** Include SH band 2 contribution. Default: true. */
257
+ get shOrder2() {
258
+ return this._shOrder2;
259
+ }
260
+ set shOrder2(value) {
261
+ this._shOrder2 = value;
262
+ this._markDirty();
263
+ }
264
+ /** Include SH band 3 contribution. Default: true. */
265
+ get shOrder3() {
266
+ return this._shOrder3;
267
+ }
268
+ set shOrder3(value) {
269
+ this._shOrder3 = value;
270
+ this._markDirty();
271
+ }
272
+ /** Include SH band 4 contribution. Default: true. */
273
+ get shOrder4() {
274
+ return this._shOrder4;
275
+ }
276
+ set shOrder4(value) {
277
+ this._shOrder4 = value;
278
+ this._markDirty();
279
+ }
280
+ // ----- Plugin overrides -----
281
+ /**
282
+ * Adds the per-part debug data texture name to the sampler list so the effect can bind it.
283
+ * @param samplers the sampler list to populate
284
+ */
285
+ getSamplers(samplers) {
286
+ samplers.push("dbgPartData");
287
+ }
288
+ /** @returns the class name of this plugin */
289
+ getClassName() {
290
+ return "GaussianSplattingDebugMaterialPlugin";
291
+ }
292
+ /**
293
+ * @param shaderLanguage the shader language to check
294
+ * @returns true for GLSL and WGSL
295
+ */
296
+ isCompatible(shaderLanguage) {
297
+ switch (shaderLanguage) {
298
+ case 0 /* ShaderLanguage.GLSL */:
299
+ case 1 /* ShaderLanguage.WGSL */:
300
+ return true;
301
+ default:
302
+ return false;
303
+ }
304
+ }
305
+ /**
306
+ * Always ready — no async resources.
307
+ * @param _defines unused
308
+ * @param _scene unused
309
+ * @param _engine unused
310
+ * @param _subMesh unused
311
+ * @returns true
312
+ */
313
+ isReadyForSubMesh(_defines, _scene, _engine, _subMesh) {
314
+ return true;
315
+ }
316
+ /**
317
+ * Sets shader defines from current property state. GS_DBG_ENABLED is set to true
318
+ * only when at least one feature is non-default, ensuring zero overhead otherwise.
319
+ * Sub-flags also check per-part arrays so compound-only overrides activate the correct
320
+ * code paths even when the global setting is at its default.
321
+ * @param defines the defines object
322
+ */
323
+ prepareDefines(defines) {
324
+ defines.GS_DBG_ENABLED = this._isAnyFeatureActive();
325
+ defines.GS_DBG_CLIP = this._clippingBox !== null || this._partClippingBoxes.some((b) => b !== null) ? 1 : 0;
326
+ defines.GS_DBG_CULL_OPACITY = this._opacityCulling !== null || this._partOpacityCullings.some((b) => b !== null) ? 1 : 0;
327
+ defines.GS_DBG_CULL_SIZE = this._sizeCulling !== null || this._partSizeCullings.some((b) => b !== null) ? 1 : 0;
328
+ defines.GS_DBG_OPACITY_SCALE = this._opacityScale !== 1.0 || this._partOpacityScales.some((s) => s !== null) ? 1 : 0;
329
+ defines.GS_DBG_OPACITY_SATURATE = this._opacitySaturate || this._partOpacitySaturates.some((s) => s !== null) ? 1 : 0;
330
+ defines.GS_DBG_SH_DC = !this._shDc || this._partShDcs.some((s) => s !== null) ? 0 : 1;
331
+ defines.GS_DBG_SH_ORDER1 = !this._shOrder1 || this._partShOrder1s.some((s) => s !== null) ? 0 : 1;
332
+ defines.GS_DBG_SH_ORDER2 = !this._shOrder2 || this._partShOrder2s.some((s) => s !== null) ? 0 : 1;
333
+ defines.GS_DBG_SH_ORDER3 = !this._shOrder3 || this._partShOrder3s.some((s) => s !== null) ? 0 : 1;
334
+ defines.GS_DBG_SH_ORDER4 = !this._shOrder4 || this._partShOrder4s.some((s) => s !== null) ? 0 : 1;
335
+ }
336
+ /**
337
+ * Returns shader code injections for the debug features.
338
+ * @param shaderType "vertex" or "fragment"
339
+ * @param shaderLanguage GLSL or WGSL
340
+ * @returns map of injection-point name to injected code, or null
341
+ */
342
+ getCustomCode(shaderType, shaderLanguage = 0 /* ShaderLanguage.GLSL */) {
343
+ if (shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
344
+ return this._getCustomCodeWGSL(shaderType);
345
+ }
346
+ return this._getCustomCodeGLSL(shaderType);
347
+ }
348
+ _getCustomCodeGLSL(shaderType) {
349
+ if (shaderType === "vertex") {
350
+ return {
351
+ CUSTOM_VERTEX_DEFINITIONS: `
352
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CLIP == 1 && !defined(IS_COMPOUND)
353
+ uniform vec3 dbgClipMin;
354
+ uniform vec3 dbgClipMax;
355
+ #endif
356
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_OPACITY == 1 && !defined(IS_COMPOUND)
357
+ uniform float dbgMinOpacity;
358
+ uniform float dbgMaxOpacity;
359
+ #endif
360
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_SIZE == 1 && !defined(IS_COMPOUND)
361
+ uniform float dbgMinSize;
362
+ uniform float dbgMaxSize;
363
+ #endif
364
+ #if defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SCALE == 1 && !defined(IS_COMPOUND)
365
+ uniform float dbgOpacityScale;
366
+ #endif
367
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
368
+ uniform sampler2D dbgPartData;
369
+ varying float vPartIndex;
370
+ #endif
371
+ `,
372
+ CUSTOM_VERTEX_UPDATE: `
373
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CLIP == 1 && !defined(IS_COMPOUND)
374
+ if (worldPos.x < dbgClipMin.x || worldPos.x > dbgClipMax.x ||
375
+ worldPos.y < dbgClipMin.y || worldPos.y > dbgClipMax.y ||
376
+ worldPos.z < dbgClipMin.z || worldPos.z > dbgClipMax.z) {
377
+ scale = vec2(0.0);
378
+ }
379
+ #endif
380
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_OPACITY == 1 && !defined(IS_COMPOUND)
381
+ if (splat.color.w < dbgMinOpacity || splat.color.w > dbgMaxOpacity) {
382
+ scale = vec2(0.0);
383
+ }
384
+ #endif
385
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_SIZE == 1 && !defined(IS_COMPOUND)
386
+ {
387
+ float _d0 = splat.covA.x; float _d1 = splat.covA.y; float _d2 = splat.covA.z;
388
+ float _d3 = splat.covA.w; float _d4 = splat.covB.x; float _d5 = splat.covB.y;
389
+ float _det = _d0*(_d3*_d5 - _d4*_d4) - _d1*(_d1*_d5 - _d4*_d2) + _d2*(_d1*_d4 - _d3*_d2);
390
+ float _sz = pow(abs(_det), 1.0/6.0);
391
+ if (_sz < dbgMinSize || _sz > dbgMaxSize) {
392
+ scale = vec2(0.0);
393
+ }
394
+ }
395
+ #endif
396
+ #if defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SCALE == 1 && !defined(IS_COMPOUND)
397
+ vColor.w *= dbgOpacityScale;
398
+ #endif
399
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
400
+ {
401
+ int _pIdx = int(splat.partIndex);
402
+ vPartIndex = float(splat.partIndex);
403
+ vec4 _row0 = texelFetch(dbgPartData, ivec2(_pIdx, 0), 0);
404
+ vec4 _row1 = texelFetch(dbgPartData, ivec2(_pIdx, 1), 0);
405
+ vec4 _row2 = texelFetch(dbgPartData, ivec2(_pIdx, 2), 0);
406
+ vec3 _clipMin = _row0.xyz;
407
+ vec3 _clipMax = vec3(_row0.w, _row1.xy);
408
+ float _minOp = _row1.z;
409
+ float _maxOp = _row1.w;
410
+ float _minSz = _row2.x;
411
+ float _maxSz = _row2.y;
412
+ float _opSc = _row2.z;
413
+ #if GS_DBG_CLIP == 1
414
+ if (worldPos.x < _clipMin.x || worldPos.x > _clipMax.x ||
415
+ worldPos.y < _clipMin.y || worldPos.y > _clipMax.y ||
416
+ worldPos.z < _clipMin.z || worldPos.z > _clipMax.z) {
417
+ scale = vec2(0.0);
418
+ }
419
+ #endif
420
+ #if GS_DBG_CULL_OPACITY == 1
421
+ if (splat.color.w < _minOp || splat.color.w > _maxOp) {
422
+ scale = vec2(0.0);
423
+ }
424
+ #endif
425
+ #if GS_DBG_CULL_SIZE == 1
426
+ {
427
+ float _d0 = splat.covA.x; float _d1 = splat.covA.y; float _d2 = splat.covA.z;
428
+ float _d3 = splat.covA.w; float _d4 = splat.covB.x; float _d5 = splat.covB.y;
429
+ float _det = _d0*(_d3*_d5 - _d4*_d4) - _d1*(_d1*_d5 - _d4*_d2) + _d2*(_d1*_d4 - _d3*_d2);
430
+ float _sz = pow(abs(_det), 1.0/6.0);
431
+ if (_sz < _minSz || _sz > _maxSz) {
432
+ scale = vec2(0.0);
433
+ }
434
+ }
435
+ #endif
436
+ #if GS_DBG_OPACITY_SCALE == 1
437
+ vColor.w *= _opSc;
438
+ #endif
439
+ }
440
+ #endif
441
+ `,
442
+ };
443
+ }
444
+ else if (shaderType === "fragment") {
445
+ return {
446
+ CUSTOM_FRAGMENT_DEFINITIONS: `
447
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
448
+ uniform sampler2D dbgPartData;
449
+ varying float vPartIndex;
450
+ #endif
451
+ `,
452
+ CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: `
453
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
454
+ if (texelFetch(dbgPartData, ivec2(int(vPartIndex + 0.5), 2), 0).w > 0.5) { finalColor.a = vColor.a; }
455
+ #elif defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SATURATE == 1
456
+ finalColor.a = vColor.a;
457
+ #endif
458
+ `,
459
+ };
460
+ }
461
+ return null;
462
+ }
463
+ _getCustomCodeWGSL(shaderType) {
464
+ if (shaderType === "vertex") {
465
+ return {
466
+ CUSTOM_VERTEX_DEFINITIONS: `
467
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CLIP == 1 && !defined(IS_COMPOUND)
468
+ uniform dbgClipMin: vec3f;
469
+ uniform dbgClipMax: vec3f;
470
+ #endif
471
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_OPACITY == 1 && !defined(IS_COMPOUND)
472
+ uniform dbgMinOpacity: f32;
473
+ uniform dbgMaxOpacity: f32;
474
+ #endif
475
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_SIZE == 1 && !defined(IS_COMPOUND)
476
+ uniform dbgMinSize: f32;
477
+ uniform dbgMaxSize: f32;
478
+ #endif
479
+ #if defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SCALE == 1 && !defined(IS_COMPOUND)
480
+ uniform dbgOpacityScale: f32;
481
+ #endif
482
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
483
+ var dbgPartData: texture_2d<f32>;
484
+ varying vPartIndex: f32;
485
+ #endif
486
+ `,
487
+ CUSTOM_VERTEX_UPDATE: `
488
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CLIP == 1 && !defined(IS_COMPOUND)
489
+ if (worldPos.x < uniforms.dbgClipMin.x || worldPos.x > uniforms.dbgClipMax.x ||
490
+ worldPos.y < uniforms.dbgClipMin.y || worldPos.y > uniforms.dbgClipMax.y ||
491
+ worldPos.z < uniforms.dbgClipMin.z || worldPos.z > uniforms.dbgClipMax.z) {
492
+ scale = vec2f(0.0);
493
+ }
494
+ #endif
495
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_OPACITY == 1 && !defined(IS_COMPOUND)
496
+ if (splat.color.w < uniforms.dbgMinOpacity || splat.color.w > uniforms.dbgMaxOpacity) {
497
+ scale = vec2f(0.0);
498
+ }
499
+ #endif
500
+ #if defined(GS_DBG_ENABLED) && GS_DBG_CULL_SIZE == 1 && !defined(IS_COMPOUND)
501
+ {
502
+ let _d0 = splat.covA.x; let _d1 = splat.covA.y; let _d2 = splat.covA.z;
503
+ let _d3 = splat.covA.w; let _d4 = splat.covB.x; let _d5 = splat.covB.y;
504
+ let _det = _d0*(_d3*_d5 - _d4*_d4) - _d1*(_d1*_d5 - _d4*_d2) + _d2*(_d1*_d4 - _d3*_d2);
505
+ let _sz = pow(abs(_det), 1.0/6.0);
506
+ if (_sz < uniforms.dbgMinSize || _sz > uniforms.dbgMaxSize) {
507
+ scale = vec2f(0.0);
508
+ }
509
+ }
510
+ #endif
511
+ #if defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SCALE == 1 && !defined(IS_COMPOUND)
512
+ vertexOutputs.vColor.w *= uniforms.dbgOpacityScale;
513
+ #endif
514
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
515
+ {
516
+ let _pIdx = i32(splat.partIndex);
517
+ vertexOutputs.vPartIndex = f32(splat.partIndex);
518
+ let _row0 = textureLoad(dbgPartData, vec2i(_pIdx, 0), 0);
519
+ let _row1 = textureLoad(dbgPartData, vec2i(_pIdx, 1), 0);
520
+ let _row2 = textureLoad(dbgPartData, vec2i(_pIdx, 2), 0);
521
+ let _clipMin = _row0.xyz;
522
+ let _clipMax = vec3f(_row0.w, _row1.xy);
523
+ let _minOp = _row1.z;
524
+ let _maxOp = _row1.w;
525
+ let _minSz = _row2.x;
526
+ let _maxSz = _row2.y;
527
+ let _opSc = _row2.z;
528
+ #if GS_DBG_CLIP == 1
529
+ if (worldPos.x < _clipMin.x || worldPos.x > _clipMax.x ||
530
+ worldPos.y < _clipMin.y || worldPos.y > _clipMax.y ||
531
+ worldPos.z < _clipMin.z || worldPos.z > _clipMax.z) {
532
+ scale = vec2f(0.0);
533
+ }
534
+ #endif
535
+ #if GS_DBG_CULL_OPACITY == 1
536
+ if (splat.color.w < _minOp || splat.color.w > _maxOp) {
537
+ scale = vec2f(0.0);
538
+ }
539
+ #endif
540
+ #if GS_DBG_CULL_SIZE == 1
541
+ {
542
+ let _d0 = splat.covA.x; let _d1 = splat.covA.y; let _d2 = splat.covA.z;
543
+ let _d3 = splat.covA.w; let _d4 = splat.covB.x; let _d5 = splat.covB.y;
544
+ let _det = _d0*(_d3*_d5 - _d4*_d4) - _d1*(_d1*_d5 - _d4*_d2) + _d2*(_d1*_d4 - _d3*_d2);
545
+ let _sz = pow(abs(_det), 1.0/6.0);
546
+ if (_sz < _minSz || _sz > _maxSz) {
547
+ scale = vec2f(0.0);
548
+ }
549
+ }
550
+ #endif
551
+ #if GS_DBG_OPACITY_SCALE == 1
552
+ vertexOutputs.vColor.w *= _opSc;
553
+ #endif
554
+ }
555
+ #endif
556
+ `,
557
+ };
558
+ }
559
+ else if (shaderType === "fragment") {
560
+ return {
561
+ CUSTOM_FRAGMENT_DEFINITIONS: `
562
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
563
+ var dbgPartData: texture_2d<f32>;
564
+ varying vPartIndex: f32;
565
+ #endif
566
+ `,
567
+ CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: `
568
+ #if defined(GS_DBG_ENABLED) && IS_COMPOUND
569
+ if (textureLoad(dbgPartData, vec2i(i32(fragmentInputs.vPartIndex + 0.5), 2), 0).w > 0.5) {
570
+ let _gsdbgA: f32 = -dot(fragmentInputs.vPosition, fragmentInputs.vPosition);
571
+ if (_gsdbgA > -4.0) { finalColor.a = fragmentInputs.vColor.a; }
572
+ }
573
+ #elif defined(GS_DBG_ENABLED) && GS_DBG_OPACITY_SATURATE == 1
574
+ {
575
+ let _gsdbgA: f32 = -dot(fragmentInputs.vPosition, fragmentInputs.vPosition);
576
+ if (_gsdbgA > -4.0) {
577
+ finalColor.a = fragmentInputs.vColor.a;
578
+ }
579
+ }
580
+ #endif
581
+ `,
582
+ };
583
+ }
584
+ return null;
585
+ }
586
+ /**
587
+ * Declares the non-compound scalar debug uniform names as external so the Effect can
588
+ * resolve their locations. WGSL uniforms are declared inline in getCustomCode() injections.
589
+ * @returns uniform descriptor with externalUniforms list
590
+ */
591
+ getUniforms() {
592
+ return {
593
+ externalUniforms: ["dbgClipMin", "dbgClipMax", "dbgMinOpacity", "dbgMaxOpacity", "dbgMinSize", "dbgMaxSize", "dbgOpacityScale"],
594
+ };
595
+ }
596
+ _buildTextureData(partCount) {
597
+ const maxPartCount = this._maxPartCount;
598
+ const data = new Float32Array(maxPartCount * 5 * 4);
599
+ for (let i = 0; i < maxPartCount; i++) {
600
+ const r0 = i * 4;
601
+ const r1 = (maxPartCount + i) * 4;
602
+ const r2 = (maxPartCount * 2 + i) * 4;
603
+ const r3 = (maxPartCount * 3 + i) * 4;
604
+ const r4 = (maxPartCount * 4 + i) * 4;
605
+ // Row 0: clipMin.xyz, clipMax.x — Row 1: clipMax.yz, minOpacity, maxOpacity
606
+ const box = i < partCount ? (this._partClippingBoxes[i] ?? this._clippingBox) : this._clippingBox;
607
+ if (box) {
608
+ data[r0] = box.min.x;
609
+ data[r0 + 1] = box.min.y;
610
+ data[r0 + 2] = box.min.z;
611
+ data[r0 + 3] = box.max.x;
612
+ data[r1] = box.max.y;
613
+ data[r1 + 1] = box.max.z;
614
+ }
615
+ else {
616
+ data[r0] = -1e9;
617
+ data[r0 + 1] = -1e9;
618
+ data[r0 + 2] = -1e9;
619
+ data[r0 + 3] = 1e9;
620
+ data[r1] = 1e9;
621
+ data[r1 + 1] = 1e9;
622
+ }
623
+ const opCull = i < partCount ? (this._partOpacityCullings[i] ?? this._opacityCulling) : this._opacityCulling;
624
+ data[r1 + 2] = opCull ? opCull.min : 0.0;
625
+ data[r1 + 3] = opCull ? opCull.max : 1.0;
626
+ // Row 2: minSize, maxSize, opacityScale, opacitySaturate
627
+ const szCull = i < partCount ? (this._partSizeCullings[i] ?? this._sizeCulling) : this._sizeCulling;
628
+ data[r2] = szCull ? szCull.min : 0.0;
629
+ data[r2 + 1] = szCull ? szCull.max : 1e9;
630
+ data[r2 + 2] = i < partCount ? (this._partOpacityScales[i] ?? this._opacityScale) : this._opacityScale;
631
+ const sat = i < partCount ? (this._partOpacitySaturates[i] ?? this._opacitySaturate) : this._opacitySaturate;
632
+ data[r2 + 3] = sat ? 1.0 : 0.0;
633
+ // Row 3: shDc, shOrder1, shOrder2, shOrder3
634
+ data[r3] = (i < partCount ? (this._partShDcs[i] ?? this._shDc) : this._shDc) ? 1.0 : 0.0;
635
+ data[r3 + 1] = (i < partCount ? (this._partShOrder1s[i] ?? this._shOrder1) : this._shOrder1) ? 1.0 : 0.0;
636
+ data[r3 + 2] = (i < partCount ? (this._partShOrder2s[i] ?? this._shOrder2) : this._shOrder2) ? 1.0 : 0.0;
637
+ data[r3 + 3] = (i < partCount ? (this._partShOrder3s[i] ?? this._shOrder3) : this._shOrder3) ? 1.0 : 0.0;
638
+ // Row 4: shOrder4, padding
639
+ data[r4] = (i < partCount ? (this._partShOrder4s[i] ?? this._shOrder4) : this._shOrder4) ? 1.0 : 0.0;
640
+ }
641
+ return data;
642
+ }
643
+ _updateOrCreateTexture(scene) {
644
+ if (!this._maxPartCount) {
645
+ this._maxPartCount = GetGaussianSplattingMaxPartCount(scene.getEngine());
646
+ }
647
+ const data = this._buildTextureData(this._partCount);
648
+ if (!this._dbgPartDataTexture) {
649
+ this._dbgPartDataTexture = RawTexture.CreateRGBATexture(data, this._maxPartCount, 5, scene, false, false, 1, 1);
650
+ }
651
+ else {
652
+ this._dbgPartDataTexture.update(data);
653
+ }
654
+ this._textureDirty = false;
655
+ }
656
+ /**
657
+ * Binds uniform values each frame. Scalar uniforms are uploaded for non-compound mode;
658
+ * the per-part data texture is updated and bound for compound mode.
659
+ * @param _uniformBuffer unused
660
+ * @param _scene the current scene
661
+ * @param _engine unused
662
+ * @param subMesh the submesh being rendered
663
+ */
664
+ bindForSubMesh(_uniformBuffer, _scene, _engine, subMesh) {
665
+ const effect = subMesh.effect;
666
+ if (!effect) {
667
+ return;
668
+ }
669
+ if (this._partCount > 0 && this._isAnyFeatureActive()) {
670
+ // Compound mode: pack per-part data into a texture (only when the debug path is active)
671
+ if (this._textureDirty || !this._dbgPartDataTexture) {
672
+ this._updateOrCreateTexture(_scene);
673
+ }
674
+ if (this._dbgPartDataTexture) {
675
+ effect.setTexture("dbgPartData", this._dbgPartDataTexture);
676
+ }
677
+ }
678
+ else if (this._partCount === 0) {
679
+ // Non-compound: upload scalar uniforms
680
+ if (this._clippingBox) {
681
+ effect.setVector3("dbgClipMin", this._clippingBox.min);
682
+ effect.setVector3("dbgClipMax", this._clippingBox.max);
683
+ }
684
+ if (this._opacityCulling) {
685
+ effect.setFloat("dbgMinOpacity", this._opacityCulling.min);
686
+ effect.setFloat("dbgMaxOpacity", this._opacityCulling.max);
687
+ }
688
+ if (this._sizeCulling) {
689
+ effect.setFloat("dbgMinSize", this._sizeCulling.min);
690
+ effect.setFloat("dbgMaxSize", this._sizeCulling.max);
691
+ }
692
+ if (this._opacityScale !== 1.0) {
693
+ effect.setFloat("dbgOpacityScale", this._opacityScale);
694
+ }
695
+ }
696
+ }
697
+ /**
698
+ * Disposes the per-part data texture.
699
+ * @param _forceDisposeTextures unused; the LUT texture is always disposed as it is owned by this plugin
700
+ */
701
+ dispose(_forceDisposeTextures) {
702
+ this._dbgPartDataTexture?.dispose();
703
+ this._dbgPartDataTexture = null;
704
+ }
705
+ }
706
+ let _Registered = false;
707
+ /**
708
+ * Register side effects for GaussianSplattingDebugMaterialPlugin.
709
+ * Safe to call multiple times; only the first call has an effect.
710
+ */
711
+ export function RegisterGaussianSplattingDebugMaterialPlugin() {
712
+ if (_Registered) {
713
+ return;
714
+ }
715
+ _Registered = true;
716
+ RegisterClass("BABYLON.GaussianSplattingDebugMaterialPlugin", GaussianSplattingDebugMaterialPlugin);
717
+ }
718
+ //# sourceMappingURL=gaussianSplattingDebugMaterialPlugin.pure.js.map