@babylonjs/core 9.3.0 → 9.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/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/engine.d.ts +49 -1118
- package/FlowGraph/flowGraph.d.ts +11 -0
- package/FlowGraph/flowGraph.js +20 -0
- package/FlowGraph/flowGraph.js.map +1 -1
- package/FlowGraph/flowGraphContext.d.ts +30 -0
- package/FlowGraph/flowGraphContext.js +42 -0
- package/FlowGraph/flowGraphContext.js.map +1 -1
- package/FlowGraph/flowGraphParser.js +13 -0
- package/FlowGraph/flowGraphParser.js.map +1 -1
- package/FlowGraph/typeDefinitions.d.ts +16 -0
- package/FlowGraph/typeDefinitions.js.map +1 -1
- package/Layers/thinSelectionOutlineLayer.js +25 -1
- package/Layers/thinSelectionOutlineLayer.js.map +1 -1
- package/Lights/Clustered/clusteredLightContainer.d.ts +1 -0
- package/Lights/Clustered/clusteredLightContainer.js +19 -0
- package/Lights/Clustered/clusteredLightContainer.js.map +1 -1
- package/Lights/light.d.ts +6 -0
- package/Lights/light.js +8 -0
- package/Lights/light.js.map +1 -1
- package/Lights/spotLight.d.ts +2 -0
- package/Lights/spotLight.js +10 -0
- package/Lights/spotLight.js.map +1 -1
- package/Materials/Background/backgroundMaterial.js +4 -1
- package/Materials/Background/backgroundMaterial.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.d.ts +18 -0
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +116 -3
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
- package/Materials/Node/Blocks/Dual/lightBlock.d.ts +8 -0
- package/Materials/Node/Blocks/Dual/lightBlock.js +16 -0
- package/Materials/Node/Blocks/Dual/lightBlock.js.map +1 -1
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.js +3 -0
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.js.map +1 -1
- package/Materials/Node/nodeMaterial.js +4 -1
- package/Materials/Node/nodeMaterial.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.js +4 -1
- package/Materials/PBR/openpbrMaterial.js.map +1 -1
- package/Materials/PBR/pbrBaseMaterial.js +4 -1
- package/Materials/PBR/pbrBaseMaterial.js.map +1 -1
- package/Materials/Textures/baseTexture.d.ts +1 -0
- package/Materials/Textures/baseTexture.js +1 -0
- package/Materials/Textures/baseTexture.js.map +1 -1
- package/Materials/materialHelper.functions.d.ts +12 -0
- package/Materials/materialHelper.functions.js +24 -0
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Materials/standardMaterial.js +4 -1
- package/Materials/standardMaterial.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +18 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +40 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.d.ts +27 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js +241 -10
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js.map +1 -1
- package/Misc/tools.js +1 -1
- package/Misc/tools.js.map +1 -1
- package/Particles/IParticleSystem.d.ts +7 -1
- package/Particles/IParticleSystem.js.map +1 -1
- package/Particles/baseParticleSystem.d.ts +18 -2
- package/Particles/baseParticleSystem.js +53 -11
- package/Particles/baseParticleSystem.js.map +1 -1
- package/Particles/computeShaderParticleSystem.js +16 -0
- package/Particles/computeShaderParticleSystem.js.map +1 -1
- package/Particles/gpuParticleSystem.d.ts +14 -72
- package/Particles/gpuParticleSystem.js +130 -106
- package/Particles/gpuParticleSystem.js.map +1 -1
- package/Particles/particleSystem.d.ts +0 -80
- package/Particles/particleSystem.functions.d.ts +16 -0
- package/Particles/particleSystem.functions.js +18 -0
- package/Particles/particleSystem.functions.js.map +1 -1
- package/Particles/particleSystem.js +0 -114
- package/Particles/particleSystem.js.map +1 -1
- package/Particles/webgl2ParticleSystem.js +12 -0
- package/Particles/webgl2ParticleSystem.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js +17 -0
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.d.ts +10 -0
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js +146 -24
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js.map +1 -1
- package/Rendering/depthRenderer.d.ts +8 -0
- package/Rendering/depthRenderer.js +48 -13
- package/Rendering/depthRenderer.js.map +1 -1
- package/Rendering/depthRendererSceneComponent.d.ts +1 -0
- package/Rendering/depthRendererSceneComponent.js +26 -0
- package/Rendering/depthRendererSceneComponent.js.map +1 -1
- package/Rendering/objectRenderer.d.ts +2 -0
- package/Rendering/objectRenderer.js +10 -0
- package/Rendering/objectRenderer.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +21 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/gaussianSplattingVoxel.fragment.d.ts +5 -0
- package/Shaders/gaussianSplattingVoxel.fragment.js +27 -0
- package/Shaders/gaussianSplattingVoxel.fragment.js.map +1 -0
- package/Shaders/gaussianSplattingVoxel.vertex.d.ts +8 -0
- package/Shaders/gaussianSplattingVoxel.vertex.js +31 -0
- package/Shaders/gaussianSplattingVoxel.vertex.js.map +1 -0
- package/Shaders/gpuUpdateParticles.vertex.js +13 -0
- package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +21 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/gaussianSplattingVoxel.fragment.d.ts +5 -0
- package/ShadersWGSL/gaussianSplattingVoxel.fragment.js +22 -0
- package/ShadersWGSL/gaussianSplattingVoxel.fragment.js.map +1 -0
- package/ShadersWGSL/gaussianSplattingVoxel.vertex.d.ts +8 -0
- package/ShadersWGSL/gaussianSplattingVoxel.vertex.js +42 -0
- package/ShadersWGSL/gaussianSplattingVoxel.vertex.js.map +1 -0
- package/ShadersWGSL/gpuUpdateParticles.compute.js +19 -0
- package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
- package/XR/features/WebXRBodyTracking.d.ts +952 -0
- package/XR/features/WebXRBodyTracking.js +2221 -0
- package/XR/features/WebXRBodyTracking.js.map +1 -0
- package/XR/features/index.d.ts +1 -0
- package/XR/features/index.js +1 -0
- package/XR/features/index.js.map +1 -1
- package/XR/webXRFeaturesManager.d.ts +7 -0
- package/XR/webXRFeaturesManager.js +4 -0
- package/XR/webXRFeaturesManager.js.map +1 -1
- package/package.json +1 -1
- package/sceneComponent.d.ts +1 -0
- package/sceneComponent.js +1 -0
- package/sceneComponent.js.map +1 -1
|
@@ -221,10 +221,19 @@ export declare class GaussianSplattingMeshBase extends Mesh {
|
|
|
221
221
|
private _depthMix;
|
|
222
222
|
protected _canPostToWorker: boolean;
|
|
223
223
|
private _readyToDisplay;
|
|
224
|
+
private _sortRequestId;
|
|
225
|
+
private _hasRenderedOnce;
|
|
224
226
|
protected _covariancesATexture: Nullable<BaseTexture>;
|
|
225
227
|
protected _covariancesBTexture: Nullable<BaseTexture>;
|
|
226
228
|
protected _centersTexture: Nullable<BaseTexture>;
|
|
227
229
|
protected _colorsTexture: Nullable<BaseTexture>;
|
|
230
|
+
protected _rotationsATexture: Nullable<BaseTexture>;
|
|
231
|
+
protected _rotationsBTexture: Nullable<BaseTexture>;
|
|
232
|
+
protected _rotationScaleTexture: Nullable<BaseTexture>;
|
|
233
|
+
private _rotationDataA;
|
|
234
|
+
private _rotationDataB;
|
|
235
|
+
private _rotationScaleData;
|
|
236
|
+
protected _needsRotationScaleTextures: boolean;
|
|
228
237
|
protected _splatPositions: Nullable<Float32Array>;
|
|
229
238
|
private _splatIndex;
|
|
230
239
|
protected _shTextures: Nullable<BaseTexture[]>;
|
|
@@ -313,6 +322,23 @@ export declare class GaussianSplattingMeshBase extends Mesh {
|
|
|
313
322
|
* Gets the colors texture
|
|
314
323
|
*/
|
|
315
324
|
get colorsTexture(): Nullable<BaseTexture>;
|
|
325
|
+
/**
|
|
326
|
+
* Gets the rotation matrix A texture (rotation elements m[0],m[1],m[2],m[4])
|
|
327
|
+
*/
|
|
328
|
+
get rotationsATexture(): Nullable<BaseTexture>;
|
|
329
|
+
/**
|
|
330
|
+
* Gets the rotation matrix B texture (rotation elements m[5],m[6],m[8],m[9])
|
|
331
|
+
*/
|
|
332
|
+
get rotationsBTexture(): Nullable<BaseTexture>;
|
|
333
|
+
/**
|
|
334
|
+
* Gets the rotation scale texture (rotation element m[10] followed by scale diagonal sx,sy,sz)
|
|
335
|
+
*/
|
|
336
|
+
get rotationScaleTexture(): Nullable<BaseTexture>;
|
|
337
|
+
/**
|
|
338
|
+
* Enables or disables generation of rotation and scale matrix textures, required for voxel-based IBL shadows.
|
|
339
|
+
*/
|
|
340
|
+
get needsRotationScaleTextures(): boolean;
|
|
341
|
+
set needsRotationScaleTextures(value: boolean);
|
|
316
342
|
/**
|
|
317
343
|
* Gets the SH textures
|
|
318
344
|
*/
|
|
@@ -368,6 +394,7 @@ export declare class GaussianSplattingMeshBase extends Mesh {
|
|
|
368
394
|
*/
|
|
369
395
|
isReady(completeCheck?: boolean): boolean;
|
|
370
396
|
_getCameraDirection(camera: Camera): Vector3;
|
|
397
|
+
private _isSortStateDirty;
|
|
371
398
|
/** @internal */
|
|
372
399
|
_postToWorker(forced?: boolean): void;
|
|
373
400
|
/**
|
|
@@ -282,6 +282,45 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
282
282
|
get colorsTexture() {
|
|
283
283
|
return this._colorsTexture;
|
|
284
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Gets the rotation matrix A texture (rotation elements m[0],m[1],m[2],m[4])
|
|
287
|
+
*/
|
|
288
|
+
get rotationsATexture() {
|
|
289
|
+
return this._rotationsATexture;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Gets the rotation matrix B texture (rotation elements m[5],m[6],m[8],m[9])
|
|
293
|
+
*/
|
|
294
|
+
get rotationsBTexture() {
|
|
295
|
+
return this._rotationsBTexture;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Gets the rotation scale texture (rotation element m[10] followed by scale diagonal sx,sy,sz)
|
|
299
|
+
*/
|
|
300
|
+
get rotationScaleTexture() {
|
|
301
|
+
return this._rotationScaleTexture;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Enables or disables generation of rotation and scale matrix textures, required for voxel-based IBL shadows.
|
|
305
|
+
*/
|
|
306
|
+
get needsRotationScaleTextures() {
|
|
307
|
+
return this._needsRotationScaleTextures;
|
|
308
|
+
}
|
|
309
|
+
set needsRotationScaleTextures(value) {
|
|
310
|
+
if (this._needsRotationScaleTextures === value) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this._needsRotationScaleTextures = value;
|
|
314
|
+
if (value && this._covariancesATexture) {
|
|
315
|
+
if (this._splatsData) {
|
|
316
|
+
this.updateData(this._splatsData, this._shData ?? undefined, { flipY: false });
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
Logger.Error("GaussianSplattingMeshBase: needsRotationScaleTextures was enabled after the mesh was already loaded, but the splat data is not kept in RAM. " +
|
|
320
|
+
"The rotation and scale matrix textures cannot be initialized. Please reload the mesh data via updateData() or construct with keepInRam=true.");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
285
324
|
/**
|
|
286
325
|
* Gets the SH textures
|
|
287
326
|
*/
|
|
@@ -354,10 +393,19 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
354
393
|
this._modelViewProjectionMatrix = Matrix.Identity();
|
|
355
394
|
this._canPostToWorker = true;
|
|
356
395
|
this._readyToDisplay = false;
|
|
396
|
+
this._sortRequestId = 0;
|
|
397
|
+
this._hasRenderedOnce = false;
|
|
357
398
|
this._covariancesATexture = null;
|
|
358
399
|
this._covariancesBTexture = null;
|
|
359
400
|
this._centersTexture = null;
|
|
360
401
|
this._colorsTexture = null;
|
|
402
|
+
this._rotationsATexture = null;
|
|
403
|
+
this._rotationsBTexture = null;
|
|
404
|
+
this._rotationScaleTexture = null;
|
|
405
|
+
this._rotationDataA = null;
|
|
406
|
+
this._rotationDataB = null;
|
|
407
|
+
this._rotationScaleData = null;
|
|
408
|
+
this._needsRotationScaleTextures = false;
|
|
361
409
|
this._splatPositions = null;
|
|
362
410
|
this._splatIndex = null;
|
|
363
411
|
this._shTextures = null;
|
|
@@ -450,6 +498,66 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
450
498
|
this._postToWorker(true);
|
|
451
499
|
return false;
|
|
452
500
|
}
|
|
501
|
+
// Before the first successful render, apply strict sort-state checks to ensure
|
|
502
|
+
// the first rendered frame uses correct splat ordering. Once the mesh has been
|
|
503
|
+
// rendered at least once, skip these checks — the render loop will continuously
|
|
504
|
+
// re-sort as the camera/world changes via _postToWorker() in render().
|
|
505
|
+
if (!this._hasRenderedOnce && !this._disableDepthSort) {
|
|
506
|
+
const cameras = this._scene.activeCameras?.length ? this._scene.activeCameras : [this._scene.activeCamera];
|
|
507
|
+
const worldMatrix = this.computeWorldMatrix(true);
|
|
508
|
+
let anyDirty = false;
|
|
509
|
+
for (const camera of cameras) {
|
|
510
|
+
if (!camera) {
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
const cameraViewInfo = this._cameraViewInfos.get(camera.uniqueId);
|
|
514
|
+
if (!cameraViewInfo || !cameraViewInfo.splatIndexBufferSet) {
|
|
515
|
+
anyDirty = true;
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
// Wait for the most recently requested sort to be applied so that the splat indices
|
|
519
|
+
// match the latest world/camera state.
|
|
520
|
+
if (cameraViewInfo.sortAppliedId !== cameraViewInfo.sortRequestId) {
|
|
521
|
+
anyDirty = true;
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
// Also detect drift: if the world or camera state has changed since the last post,
|
|
525
|
+
// mark dirty so the next render does not silently queue a new sort that completes
|
|
526
|
+
// after isReady has reported true.
|
|
527
|
+
if (this._isSortStateDirty(cameraViewInfo, worldMatrix, camera)) {
|
|
528
|
+
anyDirty = true;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
if (anyDirty) {
|
|
532
|
+
// Try to post any pending sort so subsequent polling iterations make progress.
|
|
533
|
+
this._postToWorker(true);
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Attach the splat geometry to the GS top mesh so that the shadow generator (which renders
|
|
538
|
+
// shadow casters via the top mesh's subMeshes, NOT through this mesh's render() override)
|
|
539
|
+
// has valid geometry on the very first shadow pass. Without this, the first shadow render
|
|
540
|
+
// happens before render() is called and the GS produces no shadow caster output.
|
|
541
|
+
if (!this._geometry && this._cameraViewInfos.size) {
|
|
542
|
+
this._geometry = this._cameraViewInfos.values().next().value.mesh.geometry;
|
|
543
|
+
}
|
|
544
|
+
// If the material declares a shadow depth wrapper, make sure its effect is compiled for
|
|
545
|
+
// each subMesh against the scene's shadow generators. Otherwise the first shadow pass
|
|
546
|
+
// would be skipped (ShadowGenerator.isReady would return false) and we'd miss the shadow
|
|
547
|
+
// on a renderCount=1 capture.
|
|
548
|
+
if (this.material && this.material.shadowDepthWrapper) {
|
|
549
|
+
for (const light of this._scene.lights) {
|
|
550
|
+
const shadowGenerator = light.getShadowGenerator();
|
|
551
|
+
if (!shadowGenerator) {
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
for (const subMesh of this.subMeshes) {
|
|
555
|
+
if (!shadowGenerator.isReady(subMesh, true, false)) {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
453
561
|
return true;
|
|
454
562
|
}
|
|
455
563
|
_getCameraDirection(camera) {
|
|
@@ -457,7 +565,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
457
565
|
const cameraProjectionMatrix = camera.getProjectionMatrix();
|
|
458
566
|
const cameraViewProjectionMatrix = TmpVectors.Matrix[0];
|
|
459
567
|
cameraViewMatrix.multiplyToRef(cameraProjectionMatrix, cameraViewProjectionMatrix);
|
|
460
|
-
const modelMatrix = this.
|
|
568
|
+
const modelMatrix = this.computeWorldMatrix(true);
|
|
461
569
|
const modelViewMatrix = TmpVectors.Matrix[1];
|
|
462
570
|
modelMatrix.multiplyToRef(cameraViewMatrix, modelViewMatrix);
|
|
463
571
|
modelMatrix.multiplyToRef(cameraViewProjectionMatrix, this._modelViewProjectionMatrix);
|
|
@@ -467,6 +575,25 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
467
575
|
localDirection.normalize();
|
|
468
576
|
return localDirection;
|
|
469
577
|
}
|
|
578
|
+
_isSortStateDirty(cameraViewInfo, worldMatrix, camera) {
|
|
579
|
+
const world = worldMatrix.m;
|
|
580
|
+
const previousWorld = cameraViewInfo.sortWorldMatrix.m;
|
|
581
|
+
for (let i = 0; i < previousWorld.length; i++) {
|
|
582
|
+
if (!Scalar.WithinEpsilon(previousWorld[i], world[i], this.viewUpdateThreshold)) {
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const cameraViewMatrix = camera.getViewMatrix();
|
|
587
|
+
if (!Scalar.WithinEpsilon(cameraViewInfo.sortCameraForward.x, cameraViewMatrix.m[2], this.viewUpdateThreshold) ||
|
|
588
|
+
!Scalar.WithinEpsilon(cameraViewInfo.sortCameraForward.y, cameraViewMatrix.m[6], this.viewUpdateThreshold) ||
|
|
589
|
+
!Scalar.WithinEpsilon(cameraViewInfo.sortCameraForward.z, cameraViewMatrix.m[10], this.viewUpdateThreshold)) {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
const cameraPosition = camera.globalPosition;
|
|
593
|
+
return (!Scalar.WithinEpsilon(cameraViewInfo.sortCameraPosition.x, cameraPosition.x, this.viewUpdateThreshold) ||
|
|
594
|
+
!Scalar.WithinEpsilon(cameraViewInfo.sortCameraPosition.y, cameraPosition.y, this.viewUpdateThreshold) ||
|
|
595
|
+
!Scalar.WithinEpsilon(cameraViewInfo.sortCameraPosition.z, cameraPosition.z, this.viewUpdateThreshold));
|
|
596
|
+
}
|
|
470
597
|
/** @internal */
|
|
471
598
|
_postToWorker(forced = false) {
|
|
472
599
|
const scene = this._scene;
|
|
@@ -513,6 +640,11 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
513
640
|
const newViewInfos = {
|
|
514
641
|
camera: camera,
|
|
515
642
|
cameraDirection: new Vector3(0, 0, 0),
|
|
643
|
+
sortWorldMatrix: Matrix.Identity(),
|
|
644
|
+
sortCameraForward: new Vector3(0, 0, 0),
|
|
645
|
+
sortCameraPosition: new Vector3(0, 0, 0),
|
|
646
|
+
sortRequestId: 0,
|
|
647
|
+
sortAppliedId: 0,
|
|
516
648
|
mesh: cameraMesh,
|
|
517
649
|
frameIdLastUpdate: frameId,
|
|
518
650
|
splatIndexBufferSet: false,
|
|
@@ -521,28 +653,39 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
521
653
|
this._cameraViewInfos.set(cameraId, newViewInfos);
|
|
522
654
|
}
|
|
523
655
|
});
|
|
524
|
-
// sort view infos
|
|
525
|
-
|
|
656
|
+
// sort view infos: cameras without an initial splat-index buffer come first so they don't get starved
|
|
657
|
+
// by a `forced` re-sort of an already-initialized camera (which would consume `_canPostToWorker`).
|
|
658
|
+
// Among initialized cameras, the least recently updated comes first.
|
|
659
|
+
activeViewInfos.sort((a, b) => {
|
|
660
|
+
if (a.splatIndexBufferSet !== b.splatIndexBufferSet) {
|
|
661
|
+
return a.splatIndexBufferSet ? 1 : -1;
|
|
662
|
+
}
|
|
663
|
+
return a.frameIdLastUpdate - b.frameIdLastUpdate;
|
|
664
|
+
});
|
|
526
665
|
const hasSortFunction = this._worker || Native?.sortSplats || this._disableDepthSort;
|
|
527
666
|
if ((forced || outdated) && hasSortFunction && (this._scene.activeCameras?.length || this._scene.activeCamera) && this._canPostToWorker) {
|
|
667
|
+
const worldMatrix = this.computeWorldMatrix(true);
|
|
528
668
|
// view infos sorted by least recent updated frame id
|
|
529
669
|
activeViewInfos.forEach((cameraViewInfos) => {
|
|
530
670
|
const camera = cameraViewInfos.camera;
|
|
531
671
|
const cameraDirection = this._getCameraDirection(camera);
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if ((forced || Math.abs(dot - 1) >= this.viewUpdateThreshold) && this._canPostToWorker) {
|
|
672
|
+
if ((forced || this._isSortStateDirty(cameraViewInfos, worldMatrix, camera)) && this._canPostToWorker) {
|
|
673
|
+
const cameraViewMatrix = camera.getViewMatrix();
|
|
535
674
|
cameraViewInfos.cameraDirection.copyFrom(cameraDirection);
|
|
675
|
+
cameraViewInfos.sortWorldMatrix.copyFrom(worldMatrix);
|
|
676
|
+
cameraViewInfos.sortCameraForward.set(cameraViewMatrix.m[2], cameraViewMatrix.m[6], cameraViewMatrix.m[10]);
|
|
677
|
+
cameraViewInfos.sortCameraPosition.copyFrom(camera.globalPosition);
|
|
678
|
+
cameraViewInfos.sortRequestId = ++this._sortRequestId;
|
|
536
679
|
cameraViewInfos.frameIdLastUpdate = frameId;
|
|
537
680
|
this._canPostToWorker = false;
|
|
538
681
|
if (this._worker) {
|
|
539
|
-
const cameraViewMatrix = camera.getViewMatrix();
|
|
540
682
|
this._worker.postMessage({
|
|
541
|
-
worldMatrix:
|
|
683
|
+
worldMatrix: worldMatrix.m,
|
|
542
684
|
cameraForward: [cameraViewMatrix.m[2], cameraViewMatrix.m[6], cameraViewMatrix.m[10]],
|
|
543
685
|
cameraPosition: [camera.globalPosition.x, camera.globalPosition.y, camera.globalPosition.z],
|
|
544
686
|
depthMix: this._depthMix,
|
|
545
687
|
cameraId: camera.uniqueId,
|
|
688
|
+
sortRequestId: cameraViewInfos.sortRequestId,
|
|
546
689
|
}, [this._depthMix.buffer]);
|
|
547
690
|
}
|
|
548
691
|
else if (Native?.sortSplats) {
|
|
@@ -554,6 +697,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
554
697
|
cameraViewInfos.mesh.thinInstanceSetBuffer("splatIndex", this._splatIndex, 16, false);
|
|
555
698
|
cameraViewInfos.splatIndexBufferSet = true;
|
|
556
699
|
}
|
|
700
|
+
cameraViewInfos.sortAppliedId = cameraViewInfos.sortRequestId;
|
|
557
701
|
this._canPostToWorker = true;
|
|
558
702
|
this._readyToDisplay = true;
|
|
559
703
|
}
|
|
@@ -604,6 +748,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
604
748
|
mesh.setMaterialForRenderPass(renderPassId, renderPassMaterial);
|
|
605
749
|
}
|
|
606
750
|
const ret = mesh.render(subMesh, enableAlphaMode, effectiveMeshReplacement);
|
|
751
|
+
this._hasRenderedOnce = true;
|
|
607
752
|
// Clean up the temporary override to avoid affecting other render passes
|
|
608
753
|
if (renderPassMaterial) {
|
|
609
754
|
mesh.setMaterialForRenderPass(renderPassId, undefined);
|
|
@@ -1355,6 +1500,15 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1355
1500
|
shTexture.dispose();
|
|
1356
1501
|
}
|
|
1357
1502
|
}
|
|
1503
|
+
this._rotationsATexture?.dispose();
|
|
1504
|
+
this._rotationsBTexture?.dispose();
|
|
1505
|
+
this._rotationScaleTexture?.dispose();
|
|
1506
|
+
this._rotationsATexture = null;
|
|
1507
|
+
this._rotationsBTexture = null;
|
|
1508
|
+
this._rotationScaleTexture = null;
|
|
1509
|
+
this._rotationDataA = null;
|
|
1510
|
+
this._rotationDataB = null;
|
|
1511
|
+
this._rotationScaleData = null;
|
|
1358
1512
|
this._covariancesATexture = null;
|
|
1359
1513
|
this._covariancesBTexture = null;
|
|
1360
1514
|
this._centersTexture = null;
|
|
@@ -1384,6 +1538,11 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1384
1538
|
this._shTextures?.push(shTexture.clone());
|
|
1385
1539
|
}
|
|
1386
1540
|
}
|
|
1541
|
+
if (source._rotationsATexture) {
|
|
1542
|
+
this._rotationsATexture = source._rotationsATexture.clone();
|
|
1543
|
+
this._rotationsBTexture = source._rotationsBTexture?.clone();
|
|
1544
|
+
this._rotationScaleTexture = source._rotationScaleTexture?.clone();
|
|
1545
|
+
}
|
|
1387
1546
|
}
|
|
1388
1547
|
/**
|
|
1389
1548
|
* Returns a new Mesh object generated from the current mesh properties.
|
|
@@ -1399,6 +1558,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1399
1558
|
newGS._modelViewProjectionMatrix = Matrix.Identity();
|
|
1400
1559
|
newGS._splatPositions = this._splatPositions;
|
|
1401
1560
|
newGS._readyToDisplay = false;
|
|
1561
|
+
newGS._hasRenderedOnce = false;
|
|
1402
1562
|
newGS._disableDepthSort = this._disableDepthSort;
|
|
1403
1563
|
newGS._instantiateWorker();
|
|
1404
1564
|
const binfo = this.getBoundingInfo();
|
|
@@ -1452,6 +1612,30 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1452
1612
|
quaternion.normalize();
|
|
1453
1613
|
quaternion.toRotationMatrix(matrixRotation);
|
|
1454
1614
|
Matrix.ScalingToRef(fBuffer[8 * srcIndex + 3 + 0] * 2, fBuffer[8 * srcIndex + 3 + 1] * 2, fBuffer[8 * srcIndex + 3 + 2] * 2, matrixScale);
|
|
1615
|
+
if (this._needsRotationScaleTextures) {
|
|
1616
|
+
if (!this._rotationDataA || this._rotationDataA.length < covA.length) {
|
|
1617
|
+
this._rotationDataA = new Uint16Array(covA.length);
|
|
1618
|
+
this._rotationDataB = new Uint16Array(covA.length);
|
|
1619
|
+
this._rotationScaleData = new Uint16Array(covA.length);
|
|
1620
|
+
}
|
|
1621
|
+
const rotDataA = this._rotationDataA;
|
|
1622
|
+
const rotDataB = this._rotationDataB;
|
|
1623
|
+
const rotScaleData = this._rotationScaleData;
|
|
1624
|
+
const rm = matrixRotation.m;
|
|
1625
|
+
const sm = matrixScale.m;
|
|
1626
|
+
rotDataA[dstIndex * 4 + 0] = ToHalfFloat(rm[0]);
|
|
1627
|
+
rotDataA[dstIndex * 4 + 1] = ToHalfFloat(rm[1]);
|
|
1628
|
+
rotDataA[dstIndex * 4 + 2] = ToHalfFloat(rm[2]);
|
|
1629
|
+
rotDataA[dstIndex * 4 + 3] = ToHalfFloat(rm[4]);
|
|
1630
|
+
rotDataB[dstIndex * 4 + 0] = ToHalfFloat(rm[5]);
|
|
1631
|
+
rotDataB[dstIndex * 4 + 1] = ToHalfFloat(rm[6]);
|
|
1632
|
+
rotDataB[dstIndex * 4 + 2] = ToHalfFloat(rm[8]);
|
|
1633
|
+
rotDataB[dstIndex * 4 + 3] = ToHalfFloat(rm[9]);
|
|
1634
|
+
rotScaleData[dstIndex * 4 + 0] = ToHalfFloat(rm[10]);
|
|
1635
|
+
rotScaleData[dstIndex * 4 + 1] = ToHalfFloat(sm[0]);
|
|
1636
|
+
rotScaleData[dstIndex * 4 + 2] = ToHalfFloat(sm[5]);
|
|
1637
|
+
rotScaleData[dstIndex * 4 + 3] = ToHalfFloat(sm[10]);
|
|
1638
|
+
}
|
|
1455
1639
|
const m = matrixRotation.multiplyToRef(matrixScale, TmpVectors.Matrix[0]).m;
|
|
1456
1640
|
const covariances = this._tmpCovariances;
|
|
1457
1641
|
covariances[0] = m[0] * m[0] + m[1] * m[1] + m[2] * m[2];
|
|
@@ -1544,6 +1728,25 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1544
1728
|
this._shTextures.push(shTexture);
|
|
1545
1729
|
}
|
|
1546
1730
|
}
|
|
1731
|
+
if (this._needsRotationScaleTextures && this._rotationDataA) {
|
|
1732
|
+
if (this._rotationsATexture) {
|
|
1733
|
+
this._updateTextureFromData(this._rotationsATexture, this._rotationDataA, textureSize.x, 0, textureSize.y);
|
|
1734
|
+
this._updateTextureFromData(this._rotationsBTexture, this._rotationDataB, textureSize.x, 0, textureSize.y);
|
|
1735
|
+
this._updateTextureFromData(this._rotationScaleTexture, this._rotationScaleData, textureSize.x, 0, textureSize.y);
|
|
1736
|
+
}
|
|
1737
|
+
else {
|
|
1738
|
+
// Rotation textures not yet created (needsRotationScaleTextures was enabled after initial load).
|
|
1739
|
+
this._rotationsATexture = createTextureFromDataF16(this._rotationDataA, textureSize.x, textureSize.y, 5);
|
|
1740
|
+
this._rotationsBTexture = createTextureFromDataF16(this._rotationDataB, textureSize.x, textureSize.y, 5);
|
|
1741
|
+
this._rotationScaleTexture = createTextureFromDataF16(this._rotationScaleData, textureSize.x, textureSize.y, 5);
|
|
1742
|
+
this._rotationsATexture.wrapU = 0;
|
|
1743
|
+
this._rotationsATexture.wrapV = 0;
|
|
1744
|
+
this._rotationsBTexture.wrapU = 0;
|
|
1745
|
+
this._rotationsBTexture.wrapV = 0;
|
|
1746
|
+
this._rotationScaleTexture.wrapU = 0;
|
|
1747
|
+
this._rotationScaleTexture.wrapV = 0;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1547
1750
|
this._onUpdateTextures(textureSize);
|
|
1548
1751
|
this._postToWorker(true);
|
|
1549
1752
|
}
|
|
@@ -1563,6 +1766,23 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1563
1766
|
this._shTextures.push(shTexture);
|
|
1564
1767
|
}
|
|
1565
1768
|
}
|
|
1769
|
+
if (this._needsRotationScaleTextures) {
|
|
1770
|
+
const rotDataA = this._rotationDataA ?? new Uint16Array(covA.length);
|
|
1771
|
+
const rotDataB = this._rotationDataB ?? new Uint16Array(covA.length);
|
|
1772
|
+
const rotScaleData = this._rotationScaleData ?? new Uint16Array(covA.length);
|
|
1773
|
+
this._rotationsATexture?.dispose();
|
|
1774
|
+
this._rotationsBTexture?.dispose();
|
|
1775
|
+
this._rotationScaleTexture?.dispose();
|
|
1776
|
+
this._rotationsATexture = createTextureFromDataF16(rotDataA, textureSize.x, textureSize.y, 5);
|
|
1777
|
+
this._rotationsBTexture = createTextureFromDataF16(rotDataB, textureSize.x, textureSize.y, 5);
|
|
1778
|
+
this._rotationScaleTexture = createTextureFromDataF16(rotScaleData, textureSize.x, textureSize.y, 5);
|
|
1779
|
+
this._rotationsATexture.wrapU = 0;
|
|
1780
|
+
this._rotationsATexture.wrapV = 0;
|
|
1781
|
+
this._rotationsBTexture.wrapU = 0;
|
|
1782
|
+
this._rotationsBTexture.wrapV = 0;
|
|
1783
|
+
this._rotationScaleTexture.wrapU = 0;
|
|
1784
|
+
this._rotationScaleTexture.wrapV = 0;
|
|
1785
|
+
}
|
|
1566
1786
|
this._onUpdateTextures(textureSize);
|
|
1567
1787
|
if (firstTime) {
|
|
1568
1788
|
this._instantiateWorker();
|
|
@@ -1800,6 +2020,14 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1800
2020
|
this._updateTextureFromData(this._covariancesBTexture, covBView, textureSize.x, lineStart, lineCount);
|
|
1801
2021
|
this._updateTextureFromData(this._centersTexture, centersView, textureSize.x, lineStart, lineCount);
|
|
1802
2022
|
this._updateTextureFromData(this._colorsTexture, colorsView, textureSize.x, lineStart, lineCount);
|
|
2023
|
+
if (this._rotationsATexture && this._rotationDataA) {
|
|
2024
|
+
const rotAView = new Uint16Array(this._rotationDataA.buffer, texelStart * 4 * Uint16Array.BYTES_PER_ELEMENT, texelCount * 4);
|
|
2025
|
+
const rotBView = new Uint16Array(this._rotationDataB.buffer, texelStart * 4 * Uint16Array.BYTES_PER_ELEMENT, texelCount * 4);
|
|
2026
|
+
const rotScaleView = new Uint16Array(this._rotationScaleData.buffer, texelStart * 4 * Uint16Array.BYTES_PER_ELEMENT, texelCount * 4);
|
|
2027
|
+
this._updateTextureFromData(this._rotationsATexture, rotAView, textureSize.x, lineStart, lineCount);
|
|
2028
|
+
this._updateTextureFromData(this._rotationsBTexture, rotBView, textureSize.x, lineStart, lineCount);
|
|
2029
|
+
this._updateTextureFromData(this._rotationScaleTexture, rotScaleView, textureSize.x, lineStart, lineCount);
|
|
2030
|
+
}
|
|
1803
2031
|
if (sh) {
|
|
1804
2032
|
for (let i = 0; i < sh.length; i++) {
|
|
1805
2033
|
const componentCount = 4;
|
|
@@ -1848,6 +2076,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1848
2076
|
}
|
|
1849
2077
|
this._depthMix = e.data.depthMix;
|
|
1850
2078
|
const cameraId = e.data.cameraId;
|
|
2079
|
+
const sortRequestId = e.data.sortRequestId;
|
|
1851
2080
|
const indexMix = new Uint32Array(e.data.depthMix.buffer);
|
|
1852
2081
|
if (this._splatIndex) {
|
|
1853
2082
|
for (let j = 0; j < vertexCountPadded; j++) {
|
|
@@ -1869,6 +2098,7 @@ export class GaussianSplattingMeshBase extends Mesh {
|
|
|
1869
2098
|
cameraViewInfos.mesh.thinInstanceSetBuffer("splatIndex", this._splatIndex, 16, false);
|
|
1870
2099
|
cameraViewInfos.splatIndexBufferSet = true;
|
|
1871
2100
|
}
|
|
2101
|
+
cameraViewInfos.sortAppliedId = sortRequestId;
|
|
1872
2102
|
}
|
|
1873
2103
|
this._canPostToWorker = true;
|
|
1874
2104
|
this._readyToDisplay = true;
|
|
@@ -2056,13 +2286,14 @@ GaussianSplattingMeshBase._CreateWorker = function (self) {
|
|
|
2056
2286
|
// update on view changed
|
|
2057
2287
|
else {
|
|
2058
2288
|
const cameraId = e.data.cameraId;
|
|
2289
|
+
const sortRequestId = e.data.sortRequestId;
|
|
2059
2290
|
const globalWorldMatrix = e.data.worldMatrix;
|
|
2060
2291
|
const cameraForward = e.data.cameraForward;
|
|
2061
2292
|
const cameraPosition = e.data.cameraPosition;
|
|
2062
2293
|
depthMix = e.data.depthMix;
|
|
2063
2294
|
if (!positions || !cameraForward) {
|
|
2064
2295
|
// Sort request arrived before positions were initialized — return the buffer unchanged so the main thread can unlock _canPostToWorker.
|
|
2065
|
-
self.postMessage({ depthMix, cameraId }, [depthMix.buffer]);
|
|
2296
|
+
self.postMessage({ depthMix, cameraId, sortRequestId }, [depthMix.buffer]);
|
|
2066
2297
|
return;
|
|
2067
2298
|
}
|
|
2068
2299
|
const vertexCountPadded = (positions.length / 4 + 15) & ~0xf;
|
|
@@ -2115,7 +2346,7 @@ GaussianSplattingMeshBase._CreateWorker = function (self) {
|
|
|
2115
2346
|
// eslint-disable-next-line no-console
|
|
2116
2347
|
console.error("Gaussian splat sort worker encountered an error (will retry next frame):", sortError);
|
|
2117
2348
|
}
|
|
2118
|
-
self.postMessage({ depthMix, cameraId }, [depthMix.buffer]);
|
|
2349
|
+
self.postMessage({ depthMix, cameraId, sortRequestId }, [depthMix.buffer]);
|
|
2119
2350
|
}
|
|
2120
2351
|
};
|
|
2121
2352
|
};
|