@preference-sl/pref-viewer 2.13.0-beta.1 → 2.13.0-beta.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/package.json +1 -1
- package/src/babylonjs-controller.js +234 -101
package/package.json
CHANGED
|
@@ -96,7 +96,13 @@ export default class BabylonJSController {
|
|
|
96
96
|
|
|
97
97
|
#gltfResolver = null; // GLTFResolver instance
|
|
98
98
|
#babylonJSAnimationController = null; // AnimationController instance
|
|
99
|
-
|
|
99
|
+
|
|
100
|
+
#renderPipelines = {
|
|
101
|
+
default: null,
|
|
102
|
+
ssao: null,
|
|
103
|
+
iblShadows: null,
|
|
104
|
+
};
|
|
105
|
+
|
|
100
106
|
#handlers = {
|
|
101
107
|
onKeyUp: null,
|
|
102
108
|
onPointerObservable: null,
|
|
@@ -412,6 +418,43 @@ export default class BabylonJSController {
|
|
|
412
418
|
}
|
|
413
419
|
}
|
|
414
420
|
|
|
421
|
+
/**
|
|
422
|
+
* Detaches and disposes the SSAO render pipeline from the active camera when it exists.
|
|
423
|
+
* Guards against missing scene resources or absent pipelines, returning false when no cleanup is needed.
|
|
424
|
+
* @private
|
|
425
|
+
* @returns {boolean} Returns true when the SSAO pipeline was disabled, false otherwise.
|
|
426
|
+
*/
|
|
427
|
+
#disableAmbientOcclusion() {
|
|
428
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
429
|
+
|
|
430
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
435
|
+
|
|
436
|
+
if (supportedPipelines === undefined) {
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (!this.#renderPipelines.ssao) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const pipelineName = this.#renderPipelines.ssao.name;
|
|
445
|
+
const ssaoPipeline = supportedPipelines ? supportedPipelines.find((pipeline) => pipeline.name === pipelineName) : false;
|
|
446
|
+
|
|
447
|
+
if (ssaoPipeline) {
|
|
448
|
+
pipelineManager.detachCamerasFromRenderPipeline(pipelineName, [this.#scene.activeCamera]);
|
|
449
|
+
ssaoPipeline.dispose();
|
|
450
|
+
pipelineManager.removePipeline(pipelineName);
|
|
451
|
+
pipelineManager.update();
|
|
452
|
+
this.#renderPipelines.ssao = null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
|
|
415
458
|
/**
|
|
416
459
|
* Rebuilds the SSAO post-process pipeline to inject screenspace ambient occlusion on the active camera.
|
|
417
460
|
* Disposes previous SSAO pipelines, instantiates a tuned `SSAORenderingPipeline`, and attaches it to the
|
|
@@ -420,138 +463,166 @@ export default class BabylonJSController {
|
|
|
420
463
|
* @returns {boolean} True if the SSAO pipeline is supported and enabled, otherwise false.
|
|
421
464
|
*/
|
|
422
465
|
#initializeAmbientOcclussion() {
|
|
423
|
-
|
|
466
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
467
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
424
468
|
return false;
|
|
425
469
|
}
|
|
426
470
|
|
|
427
471
|
if (!this.#settings.ambientOcclusionEnabled) {
|
|
428
472
|
return false;
|
|
429
473
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const supportedPipelines = this.#scene.postProcessRenderPipelineManager.supportedPipelines;
|
|
434
|
-
|
|
435
|
-
if (!supportedPipelines) {
|
|
474
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
475
|
+
|
|
476
|
+
if (supportedPipelines === undefined) {
|
|
436
477
|
return false;
|
|
437
478
|
}
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
if (oldSsaoPipeline) {
|
|
442
|
-
oldSsaoPipeline.dispose();
|
|
443
|
-
this.#scene.postProcessRenderPipelineManager.update();
|
|
444
|
-
}
|
|
479
|
+
|
|
480
|
+
const pipelineName = "PrefViewerSSAORenderingPipeline";
|
|
445
481
|
|
|
446
482
|
const ssaoRatio = {
|
|
447
483
|
ssaoRatio: 0.5,
|
|
448
484
|
combineRatio: 1.0
|
|
449
485
|
};
|
|
450
486
|
|
|
451
|
-
|
|
487
|
+
this.#renderPipelines.ssao = new SSAORenderingPipeline(pipelineName, this.#scene, ssaoRatio, [this.#scene.activeCamera]);
|
|
452
488
|
|
|
453
|
-
if (!
|
|
489
|
+
if (!this.#renderPipelines.ssao){
|
|
454
490
|
return false;
|
|
455
491
|
}
|
|
456
492
|
|
|
457
|
-
if (
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
493
|
+
if (this.#renderPipelines.ssao.isSupported) {
|
|
494
|
+
this.#renderPipelines.ssao.fallOff = 0.000001;
|
|
495
|
+
this.#renderPipelines.ssao.area = 1;
|
|
496
|
+
this.#renderPipelines.ssao.radius = 0.0001;
|
|
497
|
+
this.#renderPipelines.ssao.totalStrength = 1;
|
|
498
|
+
this.#renderPipelines.ssao.base = 0.6;
|
|
463
499
|
|
|
464
500
|
// Configure SSAO to calculate only once instead of every frame for better performance
|
|
465
|
-
if (
|
|
466
|
-
|
|
467
|
-
|
|
501
|
+
if (this.#renderPipelines.ssao._ssaoPostProcess) {
|
|
502
|
+
this.#renderPipelines.ssao._ssaoPostProcess.autoClear = false;
|
|
503
|
+
this.#renderPipelines.ssao._ssaoPostProcess.samples = 1;
|
|
504
|
+
}
|
|
505
|
+
if (this.#renderPipelines.ssao._combinePostProcess) {
|
|
506
|
+
this.#renderPipelines.ssao._combinePostProcess.autoClear = false;
|
|
507
|
+
this.#renderPipelines.ssao._combinePostProcess.samples = 1;
|
|
468
508
|
}
|
|
469
509
|
|
|
470
|
-
|
|
510
|
+
pipelineManager.update();
|
|
471
511
|
return true;
|
|
472
512
|
} else {
|
|
473
|
-
|
|
474
|
-
this.#
|
|
513
|
+
this.#renderPipelines.ssao.dispose();
|
|
514
|
+
this.#renderPipelines.ssao = null;
|
|
515
|
+
pipelineManager.update();
|
|
475
516
|
return false;
|
|
476
517
|
}
|
|
477
518
|
}
|
|
478
519
|
|
|
479
520
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
* `DefaultRenderingPipeline` with tuned settings for sharper anti-aliasing and subtle grain.
|
|
521
|
+
* Tears down the default rendering pipeline (MSAA/FXAA/grain) for the active camera when present.
|
|
522
|
+
* Ensures stale pipelines detach cleanly so a fresh one can be installed on the next load.
|
|
483
523
|
* @private
|
|
484
|
-
* @returns {boolean}
|
|
485
|
-
* @see {@link https://doc.babylonjs.com/features/featuresDeepDive/postProcesses/defaultRenderingPipeline|Using the Default Rendering Pipeline | Babylon.js Documentation}
|
|
524
|
+
* @returns {boolean} Returns true when the pipeline was removed, false otherwise.
|
|
486
525
|
*/
|
|
487
|
-
#
|
|
488
|
-
|
|
526
|
+
#disableVisualImprovements() {
|
|
527
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
528
|
+
|
|
529
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
489
530
|
return false;
|
|
490
531
|
}
|
|
491
532
|
|
|
492
|
-
const
|
|
493
|
-
|
|
533
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
534
|
+
|
|
535
|
+
if (supportedPipelines === undefined) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
494
538
|
|
|
495
|
-
if (!
|
|
539
|
+
if (!this.#renderPipelines.default) {
|
|
496
540
|
return false;
|
|
497
541
|
}
|
|
498
542
|
|
|
499
|
-
const
|
|
543
|
+
const pipelineName = this.#renderPipelines.default.name;
|
|
544
|
+
const defaultPipeline = supportedPipelines ? supportedPipelines.find((pipeline) => pipeline.name === pipelineName) : false;
|
|
545
|
+
|
|
546
|
+
if (defaultPipeline) {
|
|
547
|
+
pipelineManager.detachCamerasFromRenderPipeline(pipelineName, [this.#scene.activeCamera]);
|
|
548
|
+
defaultPipeline.dispose();
|
|
549
|
+
pipelineManager.removePipeline(pipelineName);
|
|
550
|
+
pipelineManager.update();
|
|
551
|
+
this.#renderPipelines.default = null;
|
|
552
|
+
}
|
|
500
553
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Rebuilds the custom default rendering pipeline (MSAA, FXAA, film grain) for the active camera.
|
|
559
|
+
* Disposes any previous pipeline instance to avoid duplicates, then attaches a fresh
|
|
560
|
+
* `DefaultRenderingPipeline` with tuned settings for sharper anti-aliasing and subtle grain.
|
|
561
|
+
* @private
|
|
562
|
+
* @returns {boolean} True when the pipeline is supported and active, otherwise false.
|
|
563
|
+
* @see {@link https://doc.babylonjs.com/features/featuresDeepDive/postProcesses/defaultRenderingPipeline|Using the Default Rendering Pipeline | Babylon.js Documentation}
|
|
564
|
+
*/
|
|
565
|
+
#initializeVisualImprovements() {
|
|
566
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
567
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
568
|
+
return false;
|
|
504
569
|
}
|
|
505
570
|
|
|
506
571
|
if (!this.#settings.antiAliasingEnabled) {
|
|
507
572
|
return false;
|
|
508
573
|
}
|
|
574
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
575
|
+
|
|
576
|
+
if (supportedPipelines === undefined) {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const pipelineName = "PrefViewerDefaultRenderingPipeline";
|
|
509
581
|
|
|
510
|
-
|
|
582
|
+
this.#renderPipelines.default = new DefaultRenderingPipeline(pipelineName, true, this.#scene, [this.#scene.activeCamera], true);
|
|
511
583
|
|
|
512
|
-
if (!
|
|
584
|
+
if (!this.#renderPipelines.default){
|
|
513
585
|
return false;
|
|
514
586
|
}
|
|
515
587
|
|
|
516
|
-
if (
|
|
588
|
+
if (this.#renderPipelines.default.isSupported) {
|
|
517
589
|
// MSAA - Multisample Anti-Aliasing
|
|
518
590
|
const caps = this.#scene.getEngine()?.getCaps?.() || {};
|
|
519
591
|
const maxSamples = typeof caps.maxMSAASamples === "number" ? caps.maxMSAASamples : 4;
|
|
520
|
-
|
|
521
|
-
|
|
592
|
+
this.#renderPipelines.default.samples = Math.max(1, Math.min(8, maxSamples));
|
|
522
593
|
// FXAA - Fast Approximate Anti-Aliasing
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
if (
|
|
527
|
-
|
|
594
|
+
this.#renderPipelines.default.fxaaEnabled = true;
|
|
595
|
+
this.#renderPipelines.default.fxaa.samples = 8;
|
|
596
|
+
this.#renderPipelines.default.fxaa.adaptScaleToCurrentViewport = true;
|
|
597
|
+
if (this.#renderPipelines.default.fxaa.edgeThreshold !== undefined) {
|
|
598
|
+
this.#renderPipelines.default.fxaa.edgeThreshold = 0.125;
|
|
528
599
|
}
|
|
529
|
-
if (
|
|
530
|
-
|
|
600
|
+
if (this.#renderPipelines.default.fxaa.edgeThresholdMin !== undefined) {
|
|
601
|
+
this.#renderPipelines.default.fxaa.edgeThresholdMin = 0.0625;
|
|
531
602
|
}
|
|
532
|
-
if (
|
|
533
|
-
|
|
603
|
+
if (this.#renderPipelines.default.fxaa.subPixelQuality !== undefined) {
|
|
604
|
+
this.#renderPipelines.default.fxaa.subPixelQuality = 0.75;
|
|
534
605
|
}
|
|
535
606
|
|
|
536
607
|
// Grain
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
608
|
+
this.#renderPipelines.default.grainEnabled = true;
|
|
609
|
+
this.#renderPipelines.default.grain.adaptScaleToCurrentViewport = true;
|
|
610
|
+
this.#renderPipelines.default.grain.animated = false;
|
|
611
|
+
this.#renderPipelines.default.grain.intensity = 3;
|
|
541
612
|
|
|
542
613
|
// Configure post-processes to calculate only once instead of every frame for better performance
|
|
543
|
-
if (
|
|
544
|
-
|
|
614
|
+
if (this.#renderPipelines.default.fxaa?._postProcess) {
|
|
615
|
+
this.#renderPipelines.default.fxaa._postProcess.autoClear = false;
|
|
545
616
|
}
|
|
546
|
-
if (
|
|
547
|
-
|
|
617
|
+
if (this.#renderPipelines.default.grain?._postProcess) {
|
|
618
|
+
this.#renderPipelines.default.grain._postProcess.autoClear = false;
|
|
548
619
|
}
|
|
549
620
|
|
|
550
|
-
|
|
621
|
+
pipelineManager.update();
|
|
551
622
|
return true;
|
|
552
623
|
} else {
|
|
553
|
-
|
|
554
|
-
|
|
624
|
+
this.#renderPipelines.default.dispose();
|
|
625
|
+
pipelineManager.update();
|
|
555
626
|
return false;
|
|
556
627
|
}
|
|
557
628
|
}
|
|
@@ -571,6 +642,43 @@ export default class BabylonJSController {
|
|
|
571
642
|
return true;
|
|
572
643
|
}
|
|
573
644
|
|
|
645
|
+
/**
|
|
646
|
+
* Removes the IBL shadow render pipeline from the active camera when present.
|
|
647
|
+
* Ensures voxelized shadow data is disposed so reloading environments installs a clean pipeline.
|
|
648
|
+
* @private
|
|
649
|
+
* @returns {boolean} Returns true when the pipeline was removed, false otherwise.
|
|
650
|
+
*/
|
|
651
|
+
#disableIBLShadows() {
|
|
652
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
653
|
+
|
|
654
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
659
|
+
|
|
660
|
+
if (supportedPipelines === undefined) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (!this.#renderPipelines.iblShadows) {
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const pipelineName = this.#renderPipelines.iblShadows.name;
|
|
669
|
+
const defaultPipeline = supportedPipelines ? supportedPipelines.find((pipeline) => pipeline.name === pipelineName) : false;
|
|
670
|
+
|
|
671
|
+
if (defaultPipeline) {
|
|
672
|
+
pipelineManager.detachCamerasFromRenderPipeline(pipelineName, [this.#scene.activeCamera]);
|
|
673
|
+
defaultPipeline.dispose();
|
|
674
|
+
pipelineManager.removePipeline(pipelineName);
|
|
675
|
+
pipelineManager.update();
|
|
676
|
+
this.#renderPipelines.iblShadows = null;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
return true;
|
|
680
|
+
}
|
|
681
|
+
|
|
574
682
|
/**
|
|
575
683
|
* Initializes the Image-Based Lighting (IBL) shadows for the Babylon.js scene.
|
|
576
684
|
* Creates an IBL shadow render pipeline and adds all relevant meshes and materials for shadow casting and receiving.
|
|
@@ -580,27 +688,22 @@ export default class BabylonJSController {
|
|
|
580
688
|
* @returns {void|false} Returns false if no environment texture is set; otherwise void.
|
|
581
689
|
*/
|
|
582
690
|
#initializeIBLShadows() {
|
|
583
|
-
|
|
691
|
+
const pipelineManager = this.#scene?.postProcessRenderPipelineManager;
|
|
692
|
+
|
|
693
|
+
if (!this.#scene || !pipelineManager || this.#scene?.activeCamera === null) {
|
|
584
694
|
return false;
|
|
585
695
|
}
|
|
586
696
|
|
|
587
|
-
// if (!this.#scene.environmentTexture || !this.#scene.environmentTexture.isReady()) {
|
|
588
697
|
if (!this.#scene.environmentTexture) {
|
|
589
698
|
return false;
|
|
590
699
|
}
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
700
|
+
const supportedPipelines = pipelineManager.supportedPipelines;
|
|
701
|
+
|
|
594
702
|
if (!supportedPipelines) {
|
|
595
703
|
return false;
|
|
596
704
|
}
|
|
597
|
-
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
if (oldIblShadowsRenderPipeline) {
|
|
601
|
-
oldIblShadowsRenderPipeline.dispose();
|
|
602
|
-
this.#scene.postProcessRenderPipelineManager.update();
|
|
603
|
-
}
|
|
705
|
+
|
|
706
|
+
const pipelineName = "PrefViewerIblShadowsRenderPipeline";
|
|
604
707
|
|
|
605
708
|
const pipelineOptions = {
|
|
606
709
|
resolutionExp: 1, // Higher resolution for better shadow quality (recomended 8)
|
|
@@ -611,13 +714,13 @@ export default class BabylonJSController {
|
|
|
611
714
|
shadowOpacity: 0.85,
|
|
612
715
|
};
|
|
613
716
|
|
|
614
|
-
|
|
717
|
+
this.#renderPipelines.iblShadows = new IblShadowsRenderPipeline(pipelineName, this.#scene, pipelineOptions, [this.#scene.activeCamera]);
|
|
615
718
|
|
|
616
|
-
if (!
|
|
719
|
+
if (!this.#renderPipelines.iblShadows) {
|
|
617
720
|
return false;
|
|
618
721
|
}
|
|
619
722
|
|
|
620
|
-
if (
|
|
723
|
+
if (this.#renderPipelines.iblShadows.isSupported) {
|
|
621
724
|
// Disable all debug passes for performance
|
|
622
725
|
const pipelineProps = {
|
|
623
726
|
allowDebugPasses: false,
|
|
@@ -631,11 +734,11 @@ export default class BabylonJSController {
|
|
|
631
734
|
accumulationPassDebugEnabled: false,
|
|
632
735
|
};
|
|
633
736
|
|
|
634
|
-
Object.assign(
|
|
737
|
+
Object.assign(this.#renderPipelines.iblShadows, pipelineProps);
|
|
635
738
|
|
|
636
|
-
if (
|
|
637
|
-
|
|
638
|
-
|
|
739
|
+
if (this.#renderPipelines.iblShadows._ssaoPostProcess) {
|
|
740
|
+
this.#renderPipelines.iblShadows._ssaoPostProcess.autoClear = false;
|
|
741
|
+
this.#renderPipelines.iblShadows._ssaoPostProcess.samples = 1;
|
|
639
742
|
}
|
|
640
743
|
|
|
641
744
|
this.#scene.meshes.forEach((mesh) => {
|
|
@@ -649,8 +752,8 @@ export default class BabylonJSController {
|
|
|
649
752
|
const meshGenerateShadows = typeof extrasCastShadows === "boolean" ? extrasCastShadows : isHDRIMesh ? false : true;
|
|
650
753
|
|
|
651
754
|
if (meshGenerateShadows) {
|
|
652
|
-
|
|
653
|
-
|
|
755
|
+
this.#renderPipelines.iblShadows.addShadowCastingMesh(mesh);
|
|
756
|
+
this.#renderPipelines.iblShadows.updateSceneBounds();
|
|
654
757
|
}
|
|
655
758
|
});
|
|
656
759
|
|
|
@@ -658,15 +761,15 @@ export default class BabylonJSController {
|
|
|
658
761
|
if (material instanceof PBRMaterial) {
|
|
659
762
|
material.enableSpecularAntiAliasing = false;
|
|
660
763
|
}
|
|
661
|
-
|
|
764
|
+
this.#renderPipelines.iblShadows.addShadowReceivingMaterial(material);
|
|
662
765
|
});
|
|
663
766
|
|
|
664
|
-
|
|
665
|
-
|
|
767
|
+
this.#renderPipelines.iblShadows.updateVoxelization();
|
|
768
|
+
pipelineManager.update();
|
|
666
769
|
return true;
|
|
667
770
|
} else {
|
|
668
|
-
|
|
669
|
-
|
|
771
|
+
this.#renderPipelines.iblShadows.dispose();
|
|
772
|
+
pipelineManager.update();
|
|
670
773
|
return false;
|
|
671
774
|
}
|
|
672
775
|
}
|
|
@@ -700,7 +803,6 @@ export default class BabylonJSController {
|
|
|
700
803
|
* @returns {void}
|
|
701
804
|
*/
|
|
702
805
|
#initializeDefaultLightShadows() {
|
|
703
|
-
this.#shadowGen = [];
|
|
704
806
|
if (!this.#dirLight) {
|
|
705
807
|
return;
|
|
706
808
|
}
|
|
@@ -766,6 +868,20 @@ export default class BabylonJSController {
|
|
|
766
868
|
});
|
|
767
869
|
}
|
|
768
870
|
|
|
871
|
+
/**
|
|
872
|
+
* Disposes every active shadow generator plus the IBL shadow pipeline to avoid stale casters across reloads.
|
|
873
|
+
* Clears the cached `#shadowGen` array so subsequent loads can rebuild fresh generators.
|
|
874
|
+
* @private
|
|
875
|
+
* @returns {void}
|
|
876
|
+
*/
|
|
877
|
+
#disableShadows() {
|
|
878
|
+
this.#shadowGen.forEach((shadowGenerator) => {
|
|
879
|
+
shadowGenerator.dispose();
|
|
880
|
+
});
|
|
881
|
+
this.#shadowGen = [];
|
|
882
|
+
this.#disableIBLShadows();
|
|
883
|
+
}
|
|
884
|
+
|
|
769
885
|
/**
|
|
770
886
|
* Initializes shadows for the Babylon.js scene.
|
|
771
887
|
* @private
|
|
@@ -913,7 +1029,6 @@ export default class BabylonJSController {
|
|
|
913
1029
|
this.#engine.dispose();
|
|
914
1030
|
this.#engine = this.#scene = this.#camera = null;
|
|
915
1031
|
this.#hemiLight = this.#dirLight = this.#cameraLight = null;
|
|
916
|
-
this.#shadowGen = [];
|
|
917
1032
|
}
|
|
918
1033
|
|
|
919
1034
|
/**
|
|
@@ -1281,6 +1396,7 @@ export default class BabylonJSController {
|
|
|
1281
1396
|
*/
|
|
1282
1397
|
#stopRender() {
|
|
1283
1398
|
this.#engine.stopRenderLoop(this.#handlers.renderLoop);
|
|
1399
|
+
this.#unloadCameraDependentEffects();
|
|
1284
1400
|
}
|
|
1285
1401
|
/**
|
|
1286
1402
|
* Starts the Babylon.js render loop for the current scene.
|
|
@@ -1289,6 +1405,7 @@ export default class BabylonJSController {
|
|
|
1289
1405
|
* @returns {Promise<void>}
|
|
1290
1406
|
*/
|
|
1291
1407
|
async #startRender() {
|
|
1408
|
+
this.#loadCameraDependentEffects();
|
|
1292
1409
|
await this.#scene.whenReadyAsync();
|
|
1293
1410
|
this.#engine.runRenderLoop(this.#handlers.renderLoop);
|
|
1294
1411
|
}
|
|
@@ -1359,7 +1476,6 @@ export default class BabylonJSController {
|
|
|
1359
1476
|
*/
|
|
1360
1477
|
async #loadContainers() {
|
|
1361
1478
|
this.#stopRender();
|
|
1362
|
-
this.#scene.postProcessRenderPipelineManager?.dispose();
|
|
1363
1479
|
|
|
1364
1480
|
let oldModelMetadata = { ...(this.#containers.model?.state?.metadata ?? {}) };
|
|
1365
1481
|
let newModelMetadata = {};
|
|
@@ -1385,6 +1501,13 @@ export default class BabylonJSController {
|
|
|
1385
1501
|
assetContainer.lights = [];
|
|
1386
1502
|
newModelMetadata = { ...(container.state.update.metadata ?? {}) };
|
|
1387
1503
|
}
|
|
1504
|
+
if (container.state.name === "model" || container.state.name === "environment") {
|
|
1505
|
+
assetContainer.cameras.forEach((camera) => {
|
|
1506
|
+
// To avoid conflicts when reloading the model we rename the id because Babylon.js caches the camera's SSAO effect by id.
|
|
1507
|
+
const sufix = "_" + Date.now();
|
|
1508
|
+
camera.id = `${camera.id || camera.name || "camera"}${sufix}`;
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1388
1511
|
this.#replaceContainer(container, assetContainer);
|
|
1389
1512
|
container.state.setSuccess(true);
|
|
1390
1513
|
} else {
|
|
@@ -1410,7 +1533,6 @@ export default class BabylonJSController {
|
|
|
1410
1533
|
.finally(async () => {
|
|
1411
1534
|
this.#checkModelMetadata(oldModelMetadata, newModelMetadata);
|
|
1412
1535
|
this.#setMaxSimultaneousLights();
|
|
1413
|
-
this.#loadCameraDepentEffects();
|
|
1414
1536
|
this.#babylonJSAnimationController = new BabylonJSAnimationController(this.#containers.model.assetContainer);
|
|
1415
1537
|
this.#startRender();
|
|
1416
1538
|
});
|
|
@@ -1423,12 +1545,24 @@ export default class BabylonJSController {
|
|
|
1423
1545
|
* @private
|
|
1424
1546
|
* @returns {void}
|
|
1425
1547
|
*/
|
|
1426
|
-
#
|
|
1548
|
+
#loadCameraDependentEffects() {
|
|
1427
1549
|
this.#initializeVisualImprovements();
|
|
1428
1550
|
this.#initializeAmbientOcclussion();
|
|
1429
1551
|
this.#initializeShadows();
|
|
1430
1552
|
}
|
|
1431
1553
|
|
|
1554
|
+
/**
|
|
1555
|
+
* Shuts down every post-process tied to the active camera before stopping the render loop.
|
|
1556
|
+
* Ensures AA, SSAO, and shadow resources detach cleanly so reloads rebuild from scratch.
|
|
1557
|
+
* @private
|
|
1558
|
+
* @returns {void}
|
|
1559
|
+
*/
|
|
1560
|
+
#unloadCameraDependentEffects() {
|
|
1561
|
+
this.#disableVisualImprovements();
|
|
1562
|
+
this.#disableAmbientOcclusion();
|
|
1563
|
+
this.#disableShadows();
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1432
1566
|
/**
|
|
1433
1567
|
* Checks and applies model metadata changes after asset loading.
|
|
1434
1568
|
* @private
|
|
@@ -1690,6 +1824,7 @@ export default class BabylonJSController {
|
|
|
1690
1824
|
this.#disableInteraction();
|
|
1691
1825
|
this.#disposeAnimationController();
|
|
1692
1826
|
this.#disposeXRExperience();
|
|
1827
|
+
this.#unloadCameraDependentEffects();
|
|
1693
1828
|
this.#disposeEngine();
|
|
1694
1829
|
}
|
|
1695
1830
|
|
|
@@ -1844,7 +1979,6 @@ export default class BabylonJSController {
|
|
|
1844
1979
|
setCameraOptions() {
|
|
1845
1980
|
this.#stopRender();
|
|
1846
1981
|
const cameraOptionsSetted = this.#setOptions_Camera();
|
|
1847
|
-
this.#loadCameraDepentEffects();
|
|
1848
1982
|
this.#startRender();
|
|
1849
1983
|
return cameraOptionsSetted;
|
|
1850
1984
|
}
|
|
@@ -1871,7 +2005,6 @@ export default class BabylonJSController {
|
|
|
1871
2005
|
setIBLOptions() {
|
|
1872
2006
|
this.#stopRender();
|
|
1873
2007
|
const IBLOptionsSetted = this.#setOptions_IBL();
|
|
1874
|
-
this.#loadCameraDepentEffects();
|
|
1875
2008
|
this.#startRender();
|
|
1876
2009
|
return IBLOptionsSetted;
|
|
1877
2010
|
}
|