@hology/core 0.0.186 → 0.0.187

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 (31) hide show
  1. package/dist/effects/vfx/vfx-materializer.d.ts +1 -1
  2. package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
  3. package/dist/gameplay/services/render.d.ts +1 -1
  4. package/dist/rendering/fog/fog-volume-actor.d.ts +4 -0
  5. package/dist/rendering/fog/fog-volume-actor.js +1 -1
  6. package/dist/rendering/fog/fog-volume-object.d.ts +13 -0
  7. package/dist/rendering/fog/volumetric-fog-pass.js +1 -1
  8. package/dist/rendering/outline-effect.js +1 -1
  9. package/dist/rendering.d.ts +8 -0
  10. package/dist/rendering.js +1 -1
  11. package/dist/scene/asset-resource-loader.js +1 -1
  12. package/dist/scene/materializer.d.ts +11 -2
  13. package/dist/scene/materializer.js +1 -1
  14. package/dist/scene/model.d.ts +1 -1
  15. package/dist/scene/storage/storage.js +1 -1
  16. package/dist/shader/builtin/lambert-shader.d.ts +1 -3
  17. package/dist/shader/builtin/lambert-shader.js +1 -1
  18. package/dist/shader/builtin/standard-shader.d.ts +1 -0
  19. package/dist/shader/builtin/standard-shader.js +1 -1
  20. package/dist/shader/builtin/toon-shader.d.ts +1 -0
  21. package/dist/shader/builtin/toon-shader.js +1 -1
  22. package/dist/shader/builtin/unlit-shader.d.ts +1 -4
  23. package/dist/shader/builtin/unlit-shader.js +1 -1
  24. package/dist/shader/sprite-shader.d.ts +8 -0
  25. package/dist/shader/sprite-shader.js +1 -1
  26. package/dist/shader-nodes/pom.d.ts +15 -1
  27. package/dist/shader-nodes/pom.js +1 -1
  28. package/dist/utils/three/transform-controls.d.ts +2 -2
  29. package/dist/utils/three/traverse.d.ts +1 -1
  30. package/package.json +2 -2
  31. package/tsconfig.tsbuildinfo +1 -1
@@ -14,7 +14,7 @@ export type VfxAssetProvider = {
14
14
  getMaterial(assetId: string): Promise<THREE.Material>;
15
15
  };
16
16
  export declare function materializeVfx(asset: VfxAsset, target: Object3D, assetProvider: VfxAssetProvider, view: ViewController, physics: PhysicsSystem, shaderProvider: ShaderProvider, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader): Promise<{
17
- container: THREE.Object3D<THREE.Object3DEventMap>;
17
+ container: THREE.Object3D<THREE.Object3DEventMap, Event>;
18
18
  system: System;
19
19
  dispose: () => void;
20
20
  }>;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{ActorComponent as i,Component as s}from"../component.js";import{Vector3 as o,MathUtils as n,PerspectiveCamera as h,Object3D as r}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as c,RestrictedRotationInput as d}from"../../input/index.js";import{PhysicsSystem as l}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as m}from"../../services/world.js";import{inject as f}from"../../inject.js";import{ease as u}from"@hology/nebula";const v=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let w=class extends i{constructor(){super(),this.viewController=f(a),this.physicsSystem=f(l),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=v?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.camera=new h(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new d(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new o,this.lookAtOffset=new o(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=f(m),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{null!=document.pointerLockElement||null!=document.mozPointerLockElement||this.showCursor()},this.prevLookAt=new o}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.autoActivate&&this.activate()}activate(){this.activated=!0,this.viewController.setCamera(this.camera);const t=this.element;null!=document.body.requestPointerLock&&(t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.disposed.subscribe(()=>{t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1)}))}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&(this.canvas.requestPointerLock(),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);const e=n.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*this.zoomInput.value,this.minDistance)),i=Math.cos(this.rotationInput.rotation.x)*e,s=this.fixedBehind?0:this.rotationInput.rotation.y;this.offset.x=Math.sin(-s)*i,this.offset.y=Math.sin(this.rotationInput.rotation.x)*e+2,this.offset.z=Math.cos(-s)*-i,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition()}checkForCollision(t){const e=this.getLookAtPosition(),i=this.camera.getWorldPosition(x),s=L.subVectors(i,e),o=s.length();if(o<.001)return;s.divideScalar(o);const h=this.physicsSystem.sphereCast(e,this.collisionSphereRadius,s,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(h.hasHit){const t=Math.max(this.minDistance,h.distance-.05);t<this.restrictedDistance&&(this.restrictedDistance=t)}else this.restrictedDistance=n.lerp(this.restrictedDistance,this.distance,n.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=k;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(){this.fixedBehind?(y.position.set(this.offset.x,this.offset.y,this.offset.z),y.rotation.set(0,0,0),y.scale.set(1,1,1),y.applyMatrix4(this.actor.object.matrix)):y.position.copy(this.actor.position).add(this.offset);const t=u.easeInOutCubic(1-this.blendDurationLeft);this.blendDurationLeft>0?this.camera.position.lerp(y.position,t):this.camera.position.copy(y.position);const e=this.getLookAtPosition();this.blendDurationLeft>0?(this.prevLookAt.lerp(e,t),this.camera.lookAt(this.prevLookAt)):(this.camera.lookAt(e),this.prevLookAt.copy(e))}};t([p(),e("design:type",Number)],w.prototype,"near",void 0),t([p(),e("design:type",Number)],w.prototype,"far",void 0),t([p(),e("design:type",Number)],w.prototype,"viewAngle",void 0),t([p(),e("design:type",Boolean)],w.prototype,"collision",void 0),t([p(),e("design:type",Number)],w.prototype,"collisionSphereRadius",void 0),w=t([s(),e("design:paramtypes",[])],w);export{w as ThirdPersonCameraComponent};const y=new r,k=new o,L=(new o,new o),x=(new o,new o);export class ThirdPartyCameraComponent extends w{}/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import{ActorComponent as i,Component as s}from"../component.js";import{Vector3 as o,MathUtils as n,PerspectiveCamera as h,Object3D as r}from"three";import{ViewController as a}from"../../services/render.js";import{DecimalInput as c,RestrictedRotationInput as d}from"../../input/index.js";import{PhysicsSystem as l}from"../../services/physics/physics-system.js";import{Parameter as p}from"../../../shader/parameter.js";import{World as m}from"../../services/world.js";import{inject as f}from"../../inject.js";import{ease as u}from"@hology/nebula";const v=void 0!==window&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let w=class extends i{constructor(){super(),this.viewController=f(a),this.physicsSystem=f(l),this.aspect=this.viewController.htmlElement.clientWidth/this.viewController.htmlElement.clientHeight,this.near=.5,this.far=500,this.viewAngle=v?30:45,this.collision=!0,this.collisionSphereRadius=.25,this.camera=new h(this.viewAngle,this.aspect,this.near,this.far),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=3,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new d(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new o,this.lookAtOffset=new o(this.offsetX,0,this.offsetZ),this.fixedBehind=!0,this.world=f(m),this.activated=!1,this.isMouseLocked=!1,this.prevFixedBehind=!1,this.blendDurationLeft=0,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||"mouse"!==t.pointerType||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{null!=document.pointerLockElement||null!=document.mozPointerLockElement||this.showCursor()},this.prevLookAt=new o}async onInit(){this.prevFixedBehind=this.fixedBehind,this.world.scene.add(this.camera),this.rotationInput.rotation.copy(this.actor.rotation),this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.autoActivate&&this.activate()}activate(){this.activated=!0,this.viewController.setCamera(this.camera);const t=this.element;null!=document.body.requestPointerLock&&(t.addEventListener("pointerdown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.disposed.subscribe(()=>{t.removeEventListener("pointerdown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1)}))}onLateUpdate(t){this.activated&&this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&this.canvas.requestPointerLock&&(this.canvas.requestPointerLock(),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.fixedBehind!==this.prevFixedBehind?(this.blendDurationLeft=1,this.prevFixedBehind=this.fixedBehind):this.blendDurationLeft>0&&(this.blendDurationLeft-=t),this.collision&&this.checkForCollision(t);const e=n.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*this.zoomInput.value,this.minDistance)),i=Math.cos(this.rotationInput.rotation.x)*e,s=this.fixedBehind?0:this.rotationInput.rotation.y;this.offset.x=Math.sin(-s)*i,this.offset.y=Math.sin(this.rotationInput.rotation.x)*e+2,this.offset.z=Math.cos(-s)*-i,this.fixedBehind&&this.offset.add(this.lookAtOffset),this.updateCameraPosition()}checkForCollision(t){const e=this.getLookAtPosition(),i=this.camera.getWorldPosition(x),s=L.subVectors(i,e),o=s.length();if(o<.001)return;s.divideScalar(o);const h=this.physicsSystem.sphereCast(e,this.collisionSphereRadius,s,this.distance,void 0,{excludeActor:this.actor,excludeTriggers:!0,collisionFilter:-2});if(h.hasHit){const t=Math.max(this.minDistance,h.distance-.05);t<this.restrictedDistance&&(this.restrictedDistance=t)}else this.restrictedDistance=n.lerp(this.restrictedDistance,this.distance,n.clamp(this.bounceBackSpeed*t,0,1))}getLookAtPosition(){const t=k;return t.set(0,0,0),t.y=this.height,this.fixedBehind&&t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(){this.fixedBehind?(y.position.set(this.offset.x,this.offset.y,this.offset.z),y.rotation.set(0,0,0),y.scale.set(1,1,1),y.applyMatrix4(this.actor.object.matrix)):y.position.copy(this.actor.position).add(this.offset);const t=u.easeInOutCubic(1-this.blendDurationLeft);this.blendDurationLeft>0?this.camera.position.lerp(y.position,t):this.camera.position.copy(y.position);const e=this.getLookAtPosition();this.blendDurationLeft>0?(this.prevLookAt.lerp(e,t),this.camera.lookAt(this.prevLookAt)):(this.camera.lookAt(e),this.prevLookAt.copy(e))}};t([p(),e("design:type",Number)],w.prototype,"near",void 0),t([p(),e("design:type",Number)],w.prototype,"far",void 0),t([p(),e("design:type",Number)],w.prototype,"viewAngle",void 0),t([p(),e("design:type",Boolean)],w.prototype,"collision",void 0),t([p(),e("design:type",Number)],w.prototype,"collisionSphereRadius",void 0),w=t([s(),e("design:paramtypes",[])],w);export{w as ThirdPersonCameraComponent};const y=new r,k=new o,L=(new o,new o),x=(new o,new o);export class ThirdPartyCameraComponent extends w{}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -30,7 +30,7 @@ export declare class ViewController {
30
30
  getMuted(): boolean;
31
31
  private outlined;
32
32
  setOutlined(objects: THREE.Object3D[]): void;
33
- getOutlined(): THREE.Object3D<THREE.Object3DEventMap>[];
33
+ getOutlined(): THREE.Object3D<THREE.Object3DEventMap, Event>[];
34
34
  addOutlined(object: THREE.Object3D): void;
35
35
  removeOutlined(object: THREE.Object3D): void;
36
36
  setOutlineColor(color: THREE.Color): void;
@@ -1,5 +1,6 @@
1
1
  import { Color } from "three";
2
2
  import { BaseActor } from "../../gameplay";
3
+ import { ScatteringMode } from "./fog-volume-object";
3
4
  export declare class FogVolume extends BaseActor {
4
5
  baseDensity: number;
5
6
  heightFalloff: number;
@@ -7,6 +8,9 @@ export declare class FogVolume extends BaseActor {
7
8
  startDistance: number;
8
9
  scatteringDistribution: number;
9
10
  albedo: Color;
11
+ emissive: Color;
12
+ ambientIntensity: number;
13
+ scatteringMode: ScatteringMode;
10
14
  private sprite;
11
15
  onInit(): Promise<void> | void;
12
16
  }
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Color as i}from"three";import{Actor as o,attach as s,BaseActor as r,Parameter as n}from"../../gameplay";import{FogVolumeObject as a}from"./fog-volume-object";import{EditorSpriteComponent as p}from"../../gameplay/actors/builtin/components/editor-sprite-component";let h=class extends r{constructor(){super(...arguments),this.baseDensity=.5,this.heightFalloff=1,this.heightOffset=0,this.startDistance=3,this.scatteringDistribution=0,this.albedo=new i(1,1,.6),this.sprite=s(p,{file:"assets/cloud-icon.webp"})}onInit(){this.object.add(new a(this))}};e([n({range:[0,5],stepSize:.01,help:"The density (or thickness) of fog."}),t("design:type",Number)],h.prototype,"baseDensity",void 0),e([n(),t("design:type",Number)],h.prototype,"heightFalloff",void 0),e([n(),t("design:type",Number)],h.prototype,"heightOffset",void 0),e([n(),t("design:type",Number)],h.prototype,"startDistance",void 0),e([n({range:[-1,1],help:"\n Controls the direction in which light scatters inside the fog.\n\n - Positive values (> 0): More light is scattered forward, making beams and shafts more visible when looking toward the directional light source. (for dramatic god rays).\n - Zero: Even scattering in all directions—fog appears uniform.\n - Negative values (< 0): Fog is brighter when looking away from the directional light source.\n "}),t("design:type",Number)],h.prototype,"scatteringDistribution",void 0),e([n(),t("design:type",i)],h.prototype,"albedo",void 0),h=e([o()],h);export{h as FogVolume};/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import{Color as i}from"three";import{Actor as o,attach as s,BaseActor as r,Parameter as n}from"../../gameplay";import{FogVolumeObject as a}from"./fog-volume-object";import{EditorSpriteComponent as l}from"../../gameplay/actors/builtin/components/editor-sprite-component";let h=class extends r{constructor(){super(...arguments),this.baseDensity=.5,this.heightFalloff=1,this.heightOffset=0,this.startDistance=3,this.scatteringDistribution=0,this.albedo=new i(1,1,.6),this.emissive=new i(0,0,0),this.ambientIntensity=1,this.scatteringMode="volumetric",this.sprite=s(l,{file:"assets/cloud-icon.webp"})}onInit(){this.object.add(new a(this))}};t([n({range:[0,5],stepSize:.01,help:"The density (or thickness) of fog."}),e("design:type",Number)],h.prototype,"baseDensity",void 0),t([n(),e("design:type",Number)],h.prototype,"heightFalloff",void 0),t([n(),e("design:type",Number)],h.prototype,"heightOffset",void 0),t([n(),e("design:type",Number)],h.prototype,"startDistance",void 0),t([n({range:[-1,1],help:"\n Controls the direction in which light scatters inside the fog.\n\n - Positive values (> 0): More light is scattered forward, making beams and shafts more visible when looking toward the directional light source. (for dramatic god rays).\n - Zero: Even scattering in all directions—fog appears uniform.\n - Negative values (< 0): Fog is brighter when looking away from the directional light source.\n "}),e("design:type",Number)],h.prototype,"scatteringDistribution",void 0),t([n(),e("design:type",i)],h.prototype,"albedo",void 0),t([n({help:"Self-illumination color - makes fog visible even without light sources. Useful for stylized fog that should always be visible."}),e("design:type",i)],h.prototype,"emissive",void 0),t([n({range:[0,2],stepSize:.1,help:"Multiplier for ambient light contribution. Higher values make fog more visible in shadows. Set to 0 for god rays that only appear in direct light."}),e("design:type",Number)],h.prototype,"ambientIntensity",void 0),t([n({options:[{name:"Volumetric",value:"volumetric"},{name:"Light shaft",value:"lightShaft"}],help:"\n Controls how fog interacts with lighting:\n \n - volumetric: Standard fog. Occludes background, can appear dark in shadows. Good for realistic fog.\n - lightShaft: God rays/light scattering. Only visible where light hits (shadow map). Good for dramatic light shafts.\n "}),e("design:type",String)],h.prototype,"scatteringMode",void 0),h=t([o()],h);export{h as FogVolume};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,11 @@
1
1
  import { Color, Object3D } from 'three';
2
+ /**
3
+ * Controls how fog affects the scene:
4
+ * - "volumetric": Standard fog. Fog always has opacity based on density, can appear dark in shadows.
5
+ * - "lightShaft": God rays/light scattering. Fog only visible where directional light hits (using shadow map).
6
+ * Invisible in shadows. No ambient/emissive contribution.
7
+ */
8
+ export type ScatteringMode = "volumetric" | "lightShaft";
2
9
  export type FogVolumeSettings = {
3
10
  object: Object3D;
4
11
  baseDensity: number;
@@ -7,5 +14,11 @@ export type FogVolumeSettings = {
7
14
  startDistance: number;
8
15
  scatteringDistribution: number;
9
16
  albedo: Color;
17
+ /** Self-illumination color - makes fog visible even without light sources */
18
+ emissive: Color;
19
+ /** Multiplier for how much ambient light affects the fog (default: 1.0) */
20
+ ambientIntensity: number;
21
+ /** Scattering mode: "volumetric" for standard fog, "lightShaft" for god rays */
22
+ scatteringMode: ScatteringMode;
10
23
  };
11
24
  //# sourceMappingURL=fog-volume-object.d.ts.map
@@ -1,4 +1,4 @@
1
- import*as t from"three";import{Matrix4 as e,PerspectiveCamera as n,PointLight as i,Vector3 as o,WebGLRenderTarget as a}from"three";import{FullScreenQuad as r,Pass as s}from"three/examples/jsm/Addons.js";import{ambientLightName as l}from"../../scene/sky.js";import{FogVolumeObject as c}from"./fog-volume-object";const h=new o;export class VolumetricFogPass extends s{constructor(n){super(),this.resolution=n,this.fsQuad=new r(null),this.downSampleRatio=4,this._oldClearColor=new t.Color,this.oldClearAlpha=1,this.volumesCache=new WeakMap,this._viewProjection=new e,this._invViewProjection=new e;const i={minFilter:t.LinearFilter,magFilter:t.LinearFilter,format:t.RGBAFormat,depthBuffer:!1,stencilBuffer:!1,type:t.HalfFloatType},s=Math.round(this.resolution.x/this.downSampleRatio),l=Math.round(this.resolution.y/this.downSampleRatio);this.renderTargetFog=new a(s,l,i),this.renderTargetFog.texture.generateMipmaps=!1,this.renderTargetBlur=new a(s,l,i),this.renderTargetBlur.texture.generateMipmaps=!1,this.material=new t.ShaderMaterial({defines:{PERSPECTIVE_CAMERA:1,NUM_FOG_VOLUMES:0,MAX_POINT_LIGHTS:8,MAX_SPOT_LIGHTS:2,VOLUMETRIC:1},uniforms:{tDepth:{value:null},tDiffuse:{value:null},cameraPos:{value:new o},cameraMatrix:{value:new e},invProjection:{value:new e},fogVolumes:{value:[]},stepCount:{value:30},cameraNear:{value:null},cameraFar:{value:null},pointLights:{value:new Array(8).fill(null).map(()=>({color:new o(0,0,0),distance:0,position:new o}))},activePointLightCount:{value:0},spotLights:{value:new Array(2).fill(null).map(()=>({position:new o,direction:new o,color:new o,distance:0,decay:0,coneCos:0,penumbraCos:0}))},activeSpotLightCount:{value:0},directionalLight:{value:{direction:new o(0,-1,1).normalize(),color:new o(1,1,1)}},ambientLight:{value:new o(1,1,1).multiplyScalar(1.35)},directionalShadowMatrix:{value:new e},directionalShadowMap:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);\n }\n ",fragmentShader:"\n #define MAX_STEP_COUNT 64\n\n struct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n };\n\n #if MAX_POINT_LIGHTS > 0\n struct PointLight {\n\t\t\tvec3 position;\n vec3 color;\n float distance;\n\t\t};\n #endif\n\n #if MAX_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n };\n uniform SpotLight spotLights[ MAX_SPOT_LIGHTS ];\n uniform int activeSpotLightCount;\n float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n return smoothstep( coneCosine, penumbraCosine, angleCosine );\n }\n #ifndef saturate\n #define saturate( a ) clamp( a, 0.0, 1.0 )\n #endif\n float pow2( const in float x ) { return x*x; }\n vec3 pow2( const in vec3 x ) { return x*x; }\n float pow4( const in float x ) { float x2 = x*x; return x2*x2; }\n float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n // based upon Frostbite 3 Moving to Physically-based Rendering\n // page 32, equation 26: E[window1]\n // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n if ( cutoffDistance > 0.0 ) {\n distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n }\n return distanceFalloff;\n }\n void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n vec3 lVector = spotLight.position - geometryPosition;\n light.direction = normalize( lVector );\n float angleCos = dot( light.direction, spotLight.direction );\n float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n if ( spotAttenuation > 0.0 ) {\n float lightDistance = length( lVector );\n light.color = spotLight.color * spotAttenuation;\n light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n } else {\n light.color = vec3( 0.0 );\n light.visible = false;\n }\n }\n vec3 calcSpotLight(vec3 p, vec3 rayDir, float g, SpotLight spotLight) {\n IncidentLight directLight;\n getSpotLightInfo(spotLight, p, directLight);\n return directLight.color * 3.14;\n }\n #endif\n\n struct DirectionalLight {\n vec3 color; // pre multiplied with intensity\n vec3 direction; // should point *from the light*, normalized\n };\n\n struct FogVolume {\n vec3 sphereCenter;\n float sphereRadius;\n float baseDensity;\n float heightFalloff;\n float heightOffset;\n float scatteringDistribution;\n float startDistance;\n vec3 albedo;\n };\n\n varying vec2 vUv;\n uniform sampler2D tDiffuse;\n uniform vec3 cameraPos;\n\n uniform float stepCount;\n uniform float nearMinDistance;\n\n uniform mat4 cameraMatrix;\n uniform mat4 invProjection;\n uniform sampler2D tDepth;\n\t\tuniform float cameraNear;\n\t\tuniform float cameraFar;\n \n uniform DirectionalLight directionalLight;\n\n uniform mat4 directionalShadowMatrix;\n uniform sampler2D directionalShadowMap;\n\n uniform vec3 ambientLight;\n\n #if NUM_FOG_VOLUMES > 0\n uniform FogVolume fogVolumes[ NUM_FOG_VOLUMES ];\n #endif\n #if MAX_POINT_LIGHTS > 0\n uniform PointLight pointLights[ MAX_POINT_LIGHTS ];\n uniform int activePointLightCount;\n #endif\n\n #include <packing>\n\n // Ray-sphere intersection\n bool intersectSphere(vec3 rayOrigin, vec3 rayDir, vec3 sphereCenter, float sphereRadius, out float t0, out float t1) {\n // Vector from ray origin to sphere center\n vec3 L = rayOrigin - sphereCenter;\n float a = dot(rayDir, rayDir); // should be 1 if rayDir is normalized\n float b = 2.0 * dot(rayDir, L);\n float c = dot(L, L) - sphereRadius * sphereRadius;\n \n float discriminant = b * b - 4.0 * a * c;\n if (discriminant < 0.0) {\n return false; // no intersection\n }\n \n float sqrtD = sqrt(discriminant);\n t0 = (-b - sqrtD) / (2.0 * a);\n t1 = (-b + sqrtD) / (2.0 * a);\n \n // Make sure t0 <= t1\n if (t0 > t1) {\n float tmp = t0;\n t0 = t1;\n t1 = tmp;\n }\n return true;\n }\n\n float getLinearDepth( const in vec2 uv ) {\n\n float fragCoordZ = texture2D( tDepth, uv ).x;\n return perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );\n\n\t\t}\n\n float linearizeDepth(float depth) {\n float z = depth * 2.0 - 1.0; // back to NDC (-1..1)\n return (2.0 * cameraNear * cameraFar) / (cameraFar + cameraNear - z * (cameraFar - cameraNear));\n }\n\n\n\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n\n vec3 calcDirectionalLight(vec3 p, vec3 rayDir, float g, DirectionalLight dirLight) {\n vec3 toLight = dirLight.direction; // direction from sample point to light\n float cosTheta = dot(toLight, -rayDir); // angle between view ray and light\n cosTheta = clamp(cosTheta, -1.0, 1.0); // keep it safe\n\n // phase function (Henyey-Greenstein or isotropic)\n float denom = 1.0 + g*g - 2.0*g*cosTheta;\n float phase = (1.0 - g*g) / (4.0 * 3.14159265 * pow(denom, 1.5));\n phase *= 3.0 * 3.14159265; // scale to total energy\n\n vec4 shadowCoord = directionalShadowMatrix * vec4(p, 1.0);\n shadowCoord.xyz /= shadowCoord.w; // perspective divide\n\n float bias = 0.0; \n float inShadow = texture2DCompare(directionalShadowMap, shadowCoord.xy, shadowCoord.z - bias);\n\n return dirLight.color * phase * inShadow;\n }\n\n vec3 calcPointLight(vec3 p, vec3 rayDir, float g, PointLight pointLight) {\n vec3 lightPos = pointLight.position;\n vec3 lightColor = pointLight.color;\n float lightRadius = pointLight.distance;\n\n vec3 L = normalize(lightPos - p);\n float lightDist = length(lightPos - p);\n \n float attenuation = clamp(1.0 - lightDist / lightRadius, 0.0, 1.0);\n attenuation *= attenuation; // smoother falloff\n attenuation /= (1.0 + lightDist*lightDist); // inverse-square style\n\n attenuation *= 4.0 * 3.14159; // Manually scaled to match point light intensity\n // float attenuation = 1.0 / (4.0 * 3.14159 * lightDist * lightDist);\n\n\n float cosTheta = dot(L, -rayDir); // angle between light and view ray\n float phase = (1.0 - g*g) / pow(1.0 + g*g - 2.0*g*cosTheta, 1.5);\n phase *= 0.25 / 3.14159; // normalize\n\n // Intensity is part of color\n vec3 light = lightColor * attenuation * phase;\n return light;\n }\n\n float random01(vec2 p) {\n return fract(sin(dot(p, vec2(41.0, 289.0))) * 45758.5453);\n }\n\n float hash(vec3 p) { return fract(sin(dot(p, vec3(12.9898,78.233,37.719))) * 43758.5453); }\n\n // Compute perceived brightness of a color (luminosity, Rec. 709)\n float luminosity(vec3 color) {\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n }\n \n void main() {\n // reconstruct ray in world space\n vec2 ndc = vUv * 2.0 - 1.0;\n vec4 nearPoint = invProjection * vec4(ndc, -1.0, 1.0);\n nearPoint /= nearPoint.w;\n vec4 farPoint = invProjection * vec4(ndc, 1.0, 1.0);\n farPoint /= farPoint.w;\n\n vec3 rayOrigin = cameraPos;\n vec3 rayDir = normalize(farPoint.xyz - cameraPos);\n\n float sceneDepth = -getLinearDepth(vUv); // in view space\n\n // vec4 scenePosView = invProjection * vec4(ndc, sceneDepth * 2.0 - 1.0, 1.0);\n // scenePosView /= scenePosView.w;\n\n // distance from camera to surface\n // float sceneDist = length(scenePosView.xyz - cameraPosition);\n\n float transmittance = 1.0;\n vec3 inscatter = vec3(0.0);\n float random = random01(vUv);\n\n\n #if NUM_FOG_VOLUMES > 0\n for (int v = 0; v < NUM_FOG_VOLUMES; v++) {\n FogVolume volume = fogVolumes[v];\n vec3 sphereCenter = volume.sphereCenter;\n float sphereRadius = volume.sphereRadius;\n float heightFalloff = volume.heightFalloff;\n float heightOffset = volume.heightOffset;\n float baseDensity = volume.baseDensity;\n float startDistance = volume.startDistance;\n float g = volume.scatteringDistribution;\n\n float t0, t1;\n if (!intersectSphere(rayOrigin, rayDir, sphereCenter, sphereRadius, t0, t1) || t1 <= 0.0) {\n continue;\n }\n // if camera inside sphere\n t0 = max(t0, 0.0);\n\n // An alternative method to get stepSize but is less dynamic\n // float stepSize = (t1 - t0) / float(MAX_STEP_COUNT);\n\n float maxStepSize = 0.3; // adjust for visual quality\n float distance = t1 - t0;\n int stepCount = int(ceil(distance / maxStepSize));\n stepCount = min(stepCount, MAX_STEP_COUNT); // optional clamp for performance\n float stepSize = distance / float(stepCount);\n \n // Add a slight random offset to reduce banding \n float jitterAmount = 1.0;\n float rayStartOffset = random * stepSize * jitterAmount;\n t0 += rayStartOffset;\n\n for (int i = 0; i < stepCount; i++) {\n\n float t = t0 + float(i) * stepSize;\n vec3 p = rayOrigin + rayDir * t;\n\n float geomDelta = sceneDepth - t; // how far fog sample is from hitting geometry\n float fade = clamp(geomDelta, 0.0, 1.0); \n // float fade = clamp((sceneDepth - t) / 0.1, 0.0, 1.0);\n\n float closeFade = smoothstep(0.0, 0.3, (t - startDistance) / t);\n float edgeFade = clamp(sphereRadius - length(p - sphereCenter), 0.0, 1.0);\n\n // density with exponential height falloff\n float h = p.y - (sphereCenter.y + heightOffset);\n float heightFactor = clamp(exp(-h * heightFalloff), 0.0, 1.0);\n float density = baseDensity * heightFactor * fade * closeFade * edgeFade;\n\n vec3 light = vec3(0.0); // simple white light\n #if VOLUMETRIC == 1\n\n #if MAX_POINT_LIGHTS > 0\n for (int pi = 0; pi < activePointLightCount; pi++) {\n light += calcPointLight(p, rayDir, g, pointLights[pi]);\n } \n #endif\n\n #if MAX_SPOT_LIGHTS > 0\n for (int pi = 0; pi < activeSpotLightCount; pi++) {\n light += calcSpotLight(p, rayDir, g, spotLights[pi]);\n } \n #endif\n\n light += calcDirectionalLight(p, rayDir, g, directionalLight);\n\n // Ambient \n light += ambientLight / 12.0;\n\n // Use luminosity to reduce transparency when dark to avoid dark fog\n transmittance *= exp(-density * stepSize * luminosity(light));\n #else\n light = vec3(1.0);\n transmittance *= exp(-density * stepSize);\n #endif\n\n light *= volume.albedo;\n inscatter += transmittance * light * density * stepSize;\n }\n }\n #endif\n\n float alpha = 1.0 - transmittance;\n // inscatter += ambientLight * alpha;\n\n vec3 color = inscatter;\n\n gl_FragColor = vec4(color, alpha);\n }\n "}),this.material.onBeforeCompile=t=>{},this.materialBlur=new t.ShaderMaterial({uniforms:{tInput:{value:null},tDepth:{value:null},texelSize:{value:new t.Vector2(1,1).divideScalar(1e3)},direction:{value:new t.Vector2(1,0)},depthSigma:{value:2},blurSigma:{value:2}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n ",fragmentShader:"\n uniform sampler2D tInput;\n uniform sampler2D tDepth;\n uniform vec2 texelSize;\n uniform vec2 direction;\n uniform float depthSigma;\n uniform float blurSigma;\n varying vec2 vUv;\n\n #include <packing>\n\n void main() {\n // float centerDepth = texture2D(tDepth, vUv).r;\n\n float centerDepth = unpackRGBAToDepth( texture2D( tDepth, vUv ) );\n vec4 center = texture2D(tInput, vUv);\n vec4 centerColor = center;\n\n vec4 sum = vec4(0.0);\n float wsum = 0.0;\n\n // int radius = int(ceil(2.0 * blurSigma));\n\n for (int i = -5; i <= 5; i++) {\n // if (i > radius || i < -radius) continue;\n\n vec2 offset = direction * float(i) * texelSize; // this should be based on resolution\n vec2 uv = vUv + offset;\n\n vec4 sampleColor = texture2D(tInput, uv);\n float sampleDepth = unpackRGBAToDepth( texture2D( tDepth, uv ) );\n\n float spatialWeight = exp(-0.5 * (float(i) * float(i)) / (blurSigma * blurSigma));\n float depthDiff = abs(sampleDepth - centerDepth) * 100.0;\n float depthWeight = exp(-0.5 * (depthDiff * depthDiff) / (depthSigma * depthSigma));\n\n float w = spatialWeight * depthWeight;\n\n sum += sampleColor * w;\n wsum += w;\n }\n\n gl_FragColor = sum / wsum;\n }\n ",transparent:!0}),this.materialComposite=new t.ShaderMaterial({uniforms:{tDiffuse:{value:null},tFog:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n ",fragmentShader:"\n uniform sampler2D tDiffuse;\n uniform sampler2D tFog;\n varying vec2 vUv;\n void main() {\n vec4 sceneColor = texture2D(tDiffuse, vUv);\n vec4 fogColor = texture2D(tFog, vUv);\n // Composite: fogColor.a is the fog alpha, blend over scene\n // vec3 color = mix(sceneColor.rgb, fogColor.rgb, fogColor.a);\n // Not sure why multipling alpha like this helps but it is necessary to avoid a dark\n // borders around the fog\n gl_FragColor = vec4(fogColor.rgb + (1.0 - fogColor.a * fogColor.a) * sceneColor.rgb, 1.0);\n }\n ",transparent:!0})}render(t,e,n){t.getClearColor(this._oldClearColor),this.oldClearAlpha=t.getClearAlpha();const i=t.autoClear;t.autoClear=!1,t.setClearColor(16777215,0),this.fsQuad.material=this.material,t.setRenderTarget(this.renderTargetFog),t.clear(),this.fsQuad.render(t),this.materialBlur.uniforms.tInput.value=this.renderTargetFog.texture,this.materialBlur.uniforms.direction.value=u,this.fsQuad.material=this.materialBlur,t.setRenderTarget(this.renderTargetBlur),t.clear(),this.fsQuad.render(t),this.materialBlur.uniforms.tInput.value=this.renderTargetBlur.texture,this.materialBlur.uniforms.direction.value=f,t.setRenderTarget(this.renderTargetFog),t.clear(),this.fsQuad.render(t),this.materialComposite.uniforms.tDiffuse.value=n.texture,this.materialComposite.uniforms.tFog.value=this.renderTargetFog.texture,this.fsQuad.material=this.materialComposite,this.renderToScreen?(t.setRenderTarget(null),this.fsQuad.render(t)):(t.setRenderTarget(e),this.clear&&t.clear(),this.fsQuad.render(t)),t.setClearColor(this._oldClearColor,this.oldClearAlpha),t.autoClear=i}setSize(t,e){let n=Math.round(t/this.downSampleRatio),i=Math.round(e/this.downSampleRatio);this.renderTargetFog.setSize(n,i),this.renderTargetBlur.setSize(n,i),this.materialBlur.uniforms.texelSize.value.set(1/n,1/i)}set volumetric(t){this.material.defines.VOLUMETRIC=t?1:0}get volumetric(){return!!this.material.defines.VOLUMETRIC}getVolumeUniforms(t){let e=this.volumesCache.get(t);return null==e&&(e={albedo:new o,baseDensity:t.baseDensity,heightFalloff:t.heightFalloff,heightOffset:t.heightOffset,startDistance:t.startDistance??3,scatteringDistribution:t.scatteringDistribution,sphereRadius:1,sphereCenter:new o},this.volumesCache.set(t,e)),t.object.getWorldPosition(e.sphereCenter),t.object.getWorldScale(h),e.sphereRadius=5*h.x,e.albedo.set(t.albedo.r,t.albedo.g,t.albedo.b),e.baseDensity=t.baseDensity,e.heightFalloff=t.heightFalloff,e.heightOffset=t.heightOffset,e.scatteringDistribution=t.scatteringDistribution,e.startDistance=t.startDistance,e}getPointLightUniforms(t){const e={position:new o,color:new o,distance:0};return t.getWorldPosition(e.position),e.color.set(t.color.r,t.color.g,t.color.b).multiplyScalar(t.intensity*(t.userData?.volumetricIntensity??1)),e.distance=void 0!==t.distance&&t.distance>0?t.distance:1,e}getSpotLightUniforms(t){const e={position:new o,direction:new o,color:new o,distance:0,coneCos:0,penumbraCos:0,decay:1};return t.getWorldPosition(e.position),e.direction.setFromMatrixPosition(t.matrixWorld),h.setFromMatrixPosition(t.target.matrixWorld),e.direction.sub(h),e.color.set(t.color.r,t.color.g,t.color.b).multiplyScalar(t.intensity*(t.userData?.volumetricIntensity??1)),e.distance=void 0!==t.distance&&t.distance>0?t.distance:0,e.coneCos=Math.cos(t.angle),e.penumbraCos=Math.cos(t.angle*(1-t.penumbra)),e.decay=void 0!==t.decay?t.decay:1,e}updateArrayUniforms(e){const n=this.material.uniforms.fogVolumes.value;let o=0;const a=this.material.uniforms.pointLights.value;let r=0;const s=this.material.uniforms.spotLights.value;let l=0;e.traverseVisible(e=>{if(e instanceof c){const t=e.volume,i=this.getVolumeUniforms(t);n[o]=i,o++}else if(e instanceof i){if(r<a.length){if(0===e.userData.volumetricIntensity)return;const t=this.getPointLightUniforms(e);a[r].position.copy(t.position),a[r].color.copy(t.color),a[r].distance=t.distance,r++}}else if(e instanceof t.SpotLight&&l<s.length){if(0===e.userData.volumetricIntensity)return;const t=this.getSpotLightUniforms(e);s[l].position.copy(t.position),s[l].direction.copy(t.direction),s[l].color.copy(t.color),s[l].distance=t.distance,s[l].coneCos=t.coneCos,s[l].penumbraCos=t.penumbraCos,s[l].decay=t.decay,l++}}),this.material.uniforms.activePointLightCount.value=r,this.material.uniforms.activeSpotLightCount.value=l,this.material.defines.NUM_FOG_VOLUMES!==o&&(this.material.needsUpdate=!0,this.material.uniformsNeedUpdate=!0),this.material.defines.NUM_FOG_VOLUMES=o}get uniforms(){return this.material.uniforms}update(t,e,i,a){if(this.updateArrayUniforms(a),this.enabled=0!=this.material.defines.NUM_FOG_VOLUMES,!this.enabled)return;null==this.uniforms.cameraPosition&&(this.uniforms.cameraPos={value:new o}),this.uniforms.cameraPos.value.copy(t.position),this._viewProjection.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.uniforms.invProjection.value.copy(this._invViewProjection.copy(this._viewProjection).invert()),this.uniforms.tDepth.value=e.depthTexture,this.materialBlur.uniforms.tDepth.value=e.depthTexture,t instanceof n&&(this.uniforms.cameraNear.value=t.near,this.uniforms.cameraFar.value=t.far),this.uniforms.directionalLight.value.direction=i.lightDirection,this.uniforms.directionalLight.value.color.set(1,1,1).multiplyScalar(i.lightIntensity);const r=i.lights[0];r&&r.shadow&&r.castShadow&&r.visible&&(this.uniforms.directionalShadowMap.value=r.shadow.map?.texture,this.uniforms.directionalShadowMatrix.value=r.shadow.matrix),r&&!r.visible?this.uniforms.directionalLight.value.color.set(0,0,0):this.uniforms.directionalLight.value.color.set(r.color.r,r.color.g,r.color.b).multiplyScalar(r.intensity*(r.userData?.volumetricIntensity??1));const s=a.children.find(t=>t.name===l);null!=s&&s.visible?this.uniforms.ambientLight.value.set(s.color.r,s.color.g,s.color.b).multiplyScalar(s.intensity*(s.userData?.volumetricIntensity??1)):this.uniforms.ambientLight.value.set(0,0,0)}}const u=new t.Vector2(1,0),f=new t.Vector2(0,1);/*
1
+ import*as t from"three";import{Matrix4 as e,PerspectiveCamera as n,PointLight as i,Vector3 as o,WebGLRenderTarget as a}from"three";import{FullScreenQuad as r,Pass as s}from"three/examples/jsm/Addons.js";import{ambientLightName as l}from"../../scene/sky.js";import{FogVolumeObject as c}from"./fog-volume-object";const h=new o;export class VolumetricFogPass extends s{constructor(n){super(),this.resolution=n,this.fsQuad=new r(null),this.downSampleRatio=4,this._oldClearColor=new t.Color,this.oldClearAlpha=1,this.volumesCache=new WeakMap,this._viewProjection=new e,this._invViewProjection=new e;const i={minFilter:t.LinearFilter,magFilter:t.LinearFilter,format:t.RGBAFormat,depthBuffer:!1,stencilBuffer:!1,type:t.HalfFloatType},s=Math.round(this.resolution.x/this.downSampleRatio),l=Math.round(this.resolution.y/this.downSampleRatio);this.renderTargetFog=new a(s,l,i),this.renderTargetFog.texture.generateMipmaps=!1,this.renderTargetBlur=new a(s,l,i),this.renderTargetBlur.texture.generateMipmaps=!1,this.material=new t.ShaderMaterial({defines:{PERSPECTIVE_CAMERA:1,NUM_FOG_VOLUMES:0,MAX_POINT_LIGHTS:8,MAX_SPOT_LIGHTS:2,VOLUMETRIC:1,SHADOW_FAR:100},uniforms:{tDepth:{value:null},tDiffuse:{value:null},cameraPos:{value:new o},cameraMatrix:{value:new e},invProjection:{value:new e},fogVolumes:{value:[]},stepCount:{value:30},cameraNear:{value:null},cameraFar:{value:null},pointLights:{value:new Array(8).fill(null).map(()=>({color:new o(0,0,0),distance:0,position:new o}))},activePointLightCount:{value:0},spotLights:{value:new Array(2).fill(null).map(()=>({position:new o,direction:new o,color:new o,distance:0,decay:0,coneCos:0,penumbraCos:0}))},activeSpotLightCount:{value:0},directionalLight:{value:{direction:new o(0,-1,1).normalize(),color:new o(1,1,1)}},ambientLight:{value:new o(1,1,1).multiplyScalar(1.35)},directionalShadowMatrix:{value:new e},directionalShadowMap:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);\n }\n ",fragmentShader:"\n #define MAX_STEP_COUNT 64\n\n struct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n };\n\n #if MAX_POINT_LIGHTS > 0\n struct PointLight {\n\t\t\tvec3 position;\n vec3 color;\n float distance;\n\t\t};\n #endif\n\n #if MAX_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n };\n uniform SpotLight spotLights[ MAX_SPOT_LIGHTS ];\n uniform int activeSpotLightCount;\n float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n return smoothstep( coneCosine, penumbraCosine, angleCosine );\n }\n #ifndef saturate\n #define saturate( a ) clamp( a, 0.0, 1.0 )\n #endif\n float pow2( const in float x ) { return x*x; }\n vec3 pow2( const in vec3 x ) { return x*x; }\n float pow4( const in float x ) { float x2 = x*x; return x2*x2; }\n float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n // based upon Frostbite 3 Moving to Physically-based Rendering\n // page 32, equation 26: E[window1]\n // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n if ( cutoffDistance > 0.0 ) {\n distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n }\n return distanceFalloff;\n }\n void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n vec3 lVector = spotLight.position - geometryPosition;\n light.direction = normalize( lVector );\n float angleCos = dot( light.direction, spotLight.direction );\n float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n if ( spotAttenuation > 0.0 ) {\n float lightDistance = length( lVector );\n light.color = spotLight.color * spotAttenuation;\n light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n } else {\n light.color = vec3( 0.0 );\n light.visible = false;\n }\n }\n vec3 calcSpotLight(vec3 p, vec3 rayDir, float g, SpotLight spotLight) {\n IncidentLight directLight;\n getSpotLightInfo(spotLight, p, directLight);\n return directLight.color * 3.14;\n }\n #endif\n\n struct DirectionalLight {\n vec3 color; // pre multiplied with intensity\n vec3 direction; // should point *from the light*, normalized\n };\n\n struct FogVolume {\n vec3 sphereCenter;\n float sphereRadius;\n float baseDensity;\n float heightFalloff;\n float heightOffset;\n float scatteringDistribution;\n float startDistance;\n vec3 albedo;\n vec3 emissive; // Self-illumination color\n float ambientIntensity; // Multiplier for ambient light contribution\n float scatteringMode; // 0 = volumetric (occludes), 1 = lightShaft (god rays)\n };\n\n varying vec2 vUv;\n uniform sampler2D tDiffuse;\n uniform vec3 cameraPos;\n\n uniform float stepCount;\n uniform float nearMinDistance;\n\n uniform mat4 cameraMatrix;\n uniform mat4 invProjection;\n uniform sampler2D tDepth;\n\t\tuniform float cameraNear;\n\t\tuniform float cameraFar;\n \n uniform DirectionalLight directionalLight;\n\n uniform mat4 directionalShadowMatrix;\n uniform sampler2D directionalShadowMap;\n\n uniform vec3 ambientLight;\n\n #if NUM_FOG_VOLUMES > 0\n uniform FogVolume fogVolumes[ NUM_FOG_VOLUMES ];\n #endif\n #if MAX_POINT_LIGHTS > 0\n uniform PointLight pointLights[ MAX_POINT_LIGHTS ];\n uniform int activePointLightCount;\n #endif\n\n #include <packing>\n\n // Ray-sphere intersection\n bool intersectSphere(vec3 rayOrigin, vec3 rayDir, vec3 sphereCenter, float sphereRadius, out float t0, out float t1) {\n // Vector from ray origin to sphere center\n vec3 L = rayOrigin - sphereCenter;\n float a = dot(rayDir, rayDir); // should be 1 if rayDir is normalized\n float b = 2.0 * dot(rayDir, L);\n float c = dot(L, L) - sphereRadius * sphereRadius;\n \n float discriminant = b * b - 4.0 * a * c;\n if (discriminant < 0.0) {\n return false; // no intersection\n }\n \n float sqrtD = sqrt(discriminant);\n t0 = (-b - sqrtD) / (2.0 * a);\n t1 = (-b + sqrtD) / (2.0 * a);\n \n // Make sure t0 <= t1\n if (t0 > t1) {\n float tmp = t0;\n t0 = t1;\n t1 = tmp;\n }\n return true;\n }\n\n float getLinearDepth( const in vec2 uv ) {\n\n float fragCoordZ = texture2D( tDepth, uv ).x;\n return perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );\n\n\t\t}\n\n float linearizeDepth(float depth) {\n float z = depth * 2.0 - 1.0; // back to NDC (-1..1)\n return (2.0 * cameraNear * cameraFar) / (cameraFar + cameraNear - z * (cameraFar - cameraNear));\n }\n\n\n\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n\n vec3 calcDirectionalLight(vec3 p, vec3 rayDir, float g, DirectionalLight dirLight, out float outInShadow) {\n vec3 toLight = dirLight.direction; // direction from sample point to light\n float cosTheta = dot(toLight, -rayDir); // angle between view ray and light\n cosTheta = clamp(cosTheta, -1.0, 1.0); // keep it safe\n\n // phase function (Henyey-Greenstein or isotropic)\n float denom = 1.0 + g*g - 2.0*g*cosTheta;\n float phase = (1.0 - g*g) / (4.0 * 3.14159265 * pow(denom, 1.5));\n phase *= 3.0 * 3.14159265; // scale to total energy\n\n vec4 shadowCoord = directionalShadowMatrix * vec4(p, 1.0);\n shadowCoord.xyz /= shadowCoord.w; // perspective divide\n\n float bias = 0.0; \n outInShadow = texture2DCompare(directionalShadowMap, shadowCoord.xy, shadowCoord.z - bias);\n\n return dirLight.color * phase * outInShadow;\n }\n\n vec3 calcPointLight(vec3 p, vec3 rayDir, float g, PointLight pointLight) {\n vec3 lightPos = pointLight.position;\n vec3 lightColor = pointLight.color;\n float lightRadius = pointLight.distance;\n\n vec3 L = normalize(lightPos - p);\n float lightDist = length(lightPos - p);\n \n float attenuation = clamp(1.0 - lightDist / lightRadius, 0.0, 1.0);\n attenuation *= attenuation; // smoother falloff\n attenuation /= (1.0 + lightDist*lightDist); // inverse-square style\n\n attenuation *= 4.0 * 3.14159; // Manually scaled to match point light intensity\n // float attenuation = 1.0 / (4.0 * 3.14159 * lightDist * lightDist);\n\n\n float cosTheta = dot(L, -rayDir); // angle between light and view ray\n float phase = (1.0 - g*g) / pow(1.0 + g*g - 2.0*g*cosTheta, 1.5);\n phase *= 0.25 / 3.14159; // normalize\n\n // Intensity is part of color\n vec3 light = lightColor * attenuation * phase;\n return light;\n }\n\n float random01(vec2 p) {\n return fract(sin(dot(p, vec2(41.0, 289.0))) * 45758.5453);\n }\n\n float hash(vec3 p) { return fract(sin(dot(p, vec3(12.9898,78.233,37.719))) * 43758.5453); }\n\n // Compute perceived brightness of a color (luminosity, Rec. 709)\n float luminosity(vec3 color) {\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n }\n \n void main() {\n // reconstruct ray in world space\n vec2 ndc = vUv * 2.0 - 1.0;\n vec4 nearPoint = invProjection * vec4(ndc, -1.0, 1.0);\n nearPoint /= nearPoint.w;\n vec4 farPoint = invProjection * vec4(ndc, 1.0, 1.0);\n farPoint /= farPoint.w;\n\n vec3 rayOrigin = cameraPos;\n vec3 rayDir = normalize(farPoint.xyz - cameraPos);\n\n float sceneDepth = -getLinearDepth(vUv); // in view space\n\n // vec4 scenePosView = invProjection * vec4(ndc, sceneDepth * 2.0 - 1.0, 1.0);\n // scenePosView /= scenePosView.w;\n\n // distance from camera to surface\n // float sceneDist = length(scenePosView.xyz - cameraPosition);\n\n float transmittance = 1.0;\n vec3 inscatter = vec3(0.0);\n float random = random01(vUv);\n\n\n #if NUM_FOG_VOLUMES > 0\n for (int v = 0; v < NUM_FOG_VOLUMES; v++) {\n FogVolume volume = fogVolumes[v];\n vec3 sphereCenter = volume.sphereCenter;\n float sphereRadius = volume.sphereRadius;\n float heightFalloff = volume.heightFalloff;\n float heightOffset = volume.heightOffset;\n float baseDensity = volume.baseDensity;\n float startDistance = volume.startDistance;\n float g = volume.scatteringDistribution;\n bool isLightShaft = volume.scatteringMode > 0.5;\n\n float t0, t1;\n if (!intersectSphere(rayOrigin, rayDir, sphereCenter, sphereRadius, t0, t1) || t1 <= 0.0) {\n continue;\n }\n // if camera inside sphere\n t0 = max(t0, 0.0);\n\n // An alternative method to get stepSize but is less dynamic\n // float stepSize = (t1 - t0) / float(MAX_STEP_COUNT);\n\n float maxStepSize = 0.3; // adjust for visual quality\n float distance = t1 - t0;\n int stepCount = int(ceil(distance / maxStepSize));\n stepCount = min(stepCount, MAX_STEP_COUNT); // optional clamp for performance\n float stepSize = distance / float(stepCount);\n \n // Add a slight random offset to reduce banding \n float jitterAmount = 1.0;\n float rayStartOffset = random * stepSize * jitterAmount;\n t0 += rayStartOffset;\n\n for (int i = 0; i < stepCount; i++) {\n\n float t = t0 + float(i) * stepSize;\n vec3 p = rayOrigin + rayDir * t;\n\n float geomDelta = sceneDepth - t; // how far fog sample is from hitting geometry\n float fade = clamp(geomDelta, 0.0, 1.0); \n // float fade = clamp((sceneDepth - t) / 0.1, 0.0, 1.0);\n\n float closeFade = smoothstep(0.0, 0.3, (t - startDistance) / t);\n float edgeFade = clamp(sphereRadius - length(p - sphereCenter), 0.0, 1.0);\n\n // density with exponential height falloff\n float h = p.y - (sphereCenter.y + heightOffset);\n float heightFactor = clamp(exp(-h * heightFalloff), 0.0, 1.0);\n float density = baseDensity * heightFactor * fade * closeFade * edgeFade;\n\n vec3 light = vec3(0.0);\n float inDirectLight = 1.0; // 1.0 = in light, 0.0 = in shadow\n \n #if VOLUMETRIC == 1\n // Skip if we're too far away for directional light shadows\n // Or the entire volume will show instead of just the shafts\n if (isLightShaft && t > float(SHADOW_FAR)) {\n continue;\n }\n // Get directional light first - this also gives us the shadow value for god rays\n light += calcDirectionalLight(p, rayDir, g, directionalLight, inDirectLight);\n \n // For god rays mode, skip everything else if we're in shadow\n // For atmospheric mode, always include all lights\n if (!isLightShaft || inDirectLight > 0.5) {\n #if MAX_POINT_LIGHTS > 0\n for (int pi = 0; pi < activePointLightCount; pi++) {\n light += calcPointLight(p, rayDir, g, pointLights[pi]);\n } \n #endif\n\n #if MAX_SPOT_LIGHTS > 0\n for (int pi = 0; pi < activeSpotLightCount; pi++) {\n light += calcSpotLight(p, rayDir, g, spotLights[pi]);\n } \n #endif\n\n // Ambient and emissive only for atmospheric mode, not god rays\n if (!isLightShaft) {\n light += ambientLight * volume.ambientIntensity;\n light += volume.emissive;\n }\n }\n\n #else\n light = vec3(1.0);\n #endif\n\n light *= volume.albedo;\n \n // In god rays mode, only accumulate when in direct light\n // In atmospheric mode, always accumulate\n if (!isLightShaft || inDirectLight > 0.5) {\n transmittance *= exp(-density * stepSize);\n inscatter += transmittance * light * density * stepSize;\n }\n }\n }\n #endif\n\n float alpha = 1.0 - transmittance;\n\n gl_FragColor = vec4(inscatter, alpha);\n }\n "}),this.material.onBeforeCompile=t=>{},this.materialBlur=new t.ShaderMaterial({uniforms:{tInput:{value:null},tDepth:{value:null},texelSize:{value:new t.Vector2(1,1).divideScalar(1e3)},direction:{value:new t.Vector2(1,0)},depthSigma:{value:2},blurSigma:{value:2}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n ",fragmentShader:"\n uniform sampler2D tInput;\n uniform sampler2D tDepth;\n uniform vec2 texelSize;\n uniform vec2 direction;\n uniform float depthSigma;\n uniform float blurSigma;\n varying vec2 vUv;\n\n #include <packing>\n\n void main() {\n // float centerDepth = texture2D(tDepth, vUv).r;\n\n float centerDepth = unpackRGBAToDepth( texture2D( tDepth, vUv ) );\n vec4 center = texture2D(tInput, vUv);\n vec4 centerColor = center;\n\n vec4 sum = vec4(0.0);\n float wsum = 0.0;\n\n // int radius = int(ceil(2.0 * blurSigma));\n\n for (int i = -5; i <= 5; i++) {\n // if (i > radius || i < -radius) continue;\n\n vec2 offset = direction * float(i) * texelSize; // this should be based on resolution\n vec2 uv = vUv + offset;\n\n vec4 sampleColor = texture2D(tInput, uv);\n float sampleDepth = unpackRGBAToDepth( texture2D( tDepth, uv ) );\n\n float spatialWeight = exp(-0.5 * (float(i) * float(i)) / (blurSigma * blurSigma));\n float depthDiff = abs(sampleDepth - centerDepth) * 100.0;\n float depthWeight = exp(-0.5 * (depthDiff * depthDiff) / (depthSigma * depthSigma));\n\n float w = spatialWeight * depthWeight;\n\n sum += sampleColor * w;\n wsum += w;\n }\n\n gl_FragColor = sum / wsum;\n }\n ",transparent:!0}),this.materialComposite=new t.ShaderMaterial({uniforms:{tDiffuse:{value:null},tFog:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n ",fragmentShader:"\n uniform sampler2D tDiffuse;\n uniform sampler2D tFog;\n varying vec2 vUv;\n void main() {\n vec4 sceneColor = texture2D(tDiffuse, vUv);\n vec4 fogColor = texture2D(tFog, vUv);\n // Composite: fogColor.a is the fog alpha, blend over scene\n // vec3 color = mix(sceneColor.rgb, fogColor.rgb, fogColor.a);\n // Not sure why multipling alpha like this helps but it is necessary to avoid a dark\n // borders around the fog\n gl_FragColor = vec4(fogColor.rgb + (1.0 - fogColor.a * fogColor.a) * sceneColor.rgb, 1.0);\n }\n ",transparent:!0})}render(t,e,n){t.getClearColor(this._oldClearColor),this.oldClearAlpha=t.getClearAlpha();const i=t.autoClear;t.autoClear=!1,t.setClearColor(16777215,0),this.fsQuad.material=this.material,t.setRenderTarget(this.renderTargetFog),t.clear(),this.fsQuad.render(t),this.materialBlur.uniforms.tInput.value=this.renderTargetFog.texture,this.materialBlur.uniforms.direction.value=u,this.fsQuad.material=this.materialBlur,t.setRenderTarget(this.renderTargetBlur),t.clear(),this.fsQuad.render(t),this.materialBlur.uniforms.tInput.value=this.renderTargetBlur.texture,this.materialBlur.uniforms.direction.value=f,t.setRenderTarget(this.renderTargetFog),t.clear(),this.fsQuad.render(t),this.materialComposite.uniforms.tDiffuse.value=n.texture,this.materialComposite.uniforms.tFog.value=this.renderTargetFog.texture,this.fsQuad.material=this.materialComposite,this.renderToScreen?(t.setRenderTarget(null),this.fsQuad.render(t)):(t.setRenderTarget(e),this.clear&&t.clear(),this.fsQuad.render(t)),t.setClearColor(this._oldClearColor,this.oldClearAlpha),t.autoClear=i}setSize(t,e){let n=Math.round(t/this.downSampleRatio),i=Math.round(e/this.downSampleRatio);this.renderTargetFog.setSize(n,i),this.renderTargetBlur.setSize(n,i),this.materialBlur.uniforms.texelSize.value.set(1/n,1/i)}set volumetric(t){this.material.defines.VOLUMETRIC=t?1:0}get volumetric(){return!!this.material.defines.VOLUMETRIC}getVolumeUniforms(t){let e=this.volumesCache.get(t);return null==e&&(e={albedo:new o,baseDensity:t.baseDensity,heightFalloff:t.heightFalloff,heightOffset:t.heightOffset,startDistance:t.startDistance??3,scatteringDistribution:t.scatteringDistribution,sphereRadius:1,sphereCenter:new o,emissive:new o,ambientIntensity:t.ambientIntensity??1,scatteringMode:"lightShaft"===t.scatteringMode?1:0},this.volumesCache.set(t,e)),t.object.getWorldPosition(e.sphereCenter),t.object.getWorldScale(h),e.sphereRadius=5*h.x,e.albedo.set(t.albedo.r,t.albedo.g,t.albedo.b),e.baseDensity=t.baseDensity,e.heightFalloff=t.heightFalloff,e.heightOffset=t.heightOffset,e.scatteringDistribution=t.scatteringDistribution,e.startDistance=t.startDistance,e.emissive.set(t.emissive.r,t.emissive.g,t.emissive.b),e.ambientIntensity=t.ambientIntensity??1,e.scatteringMode="lightShaft"===t.scatteringMode?1:0,e}getPointLightUniforms(t){const e={position:new o,color:new o,distance:0};return t.getWorldPosition(e.position),e.color.set(t.color.r,t.color.g,t.color.b).multiplyScalar(t.intensity*(t.userData?.volumetricIntensity??1)),e.distance=void 0!==t.distance&&t.distance>0?t.distance:1,e}getSpotLightUniforms(t){const e={position:new o,direction:new o,color:new o,distance:0,coneCos:0,penumbraCos:0,decay:1};return t.getWorldPosition(e.position),e.direction.setFromMatrixPosition(t.matrixWorld),h.setFromMatrixPosition(t.target.matrixWorld),e.direction.sub(h),e.color.set(t.color.r,t.color.g,t.color.b).multiplyScalar(t.intensity*(t.userData?.volumetricIntensity??1)),e.distance=void 0!==t.distance&&t.distance>0?t.distance:0,e.coneCos=Math.cos(t.angle),e.penumbraCos=Math.cos(t.angle*(1-t.penumbra)),e.decay=void 0!==t.decay?t.decay:1,e}updateArrayUniforms(e){const n=this.material.uniforms.fogVolumes.value;let o=0;const a=this.material.uniforms.pointLights.value;let r=0;const s=this.material.uniforms.spotLights.value;let l=0;e.traverseVisible(e=>{if(e instanceof c){const t=e.volume,i=this.getVolumeUniforms(t);n[o]=i,o++}else if(e instanceof i){if(r<a.length){if(0===e.userData.volumetricIntensity)return;const t=this.getPointLightUniforms(e);a[r].position.copy(t.position),a[r].color.copy(t.color),a[r].distance=t.distance,r++}}else if(e instanceof t.SpotLight&&l<s.length){if(0===e.userData.volumetricIntensity)return;const t=this.getSpotLightUniforms(e);s[l].position.copy(t.position),s[l].direction.copy(t.direction),s[l].color.copy(t.color),s[l].distance=t.distance,s[l].coneCos=t.coneCos,s[l].penumbraCos=t.penumbraCos,s[l].decay=t.decay,l++}}),this.material.uniforms.activePointLightCount.value=r,this.material.uniforms.activeSpotLightCount.value=l,this.material.defines.NUM_FOG_VOLUMES!==o&&(this.material.needsUpdate=!0,this.material.uniformsNeedUpdate=!0),this.material.defines.NUM_FOG_VOLUMES=o}get uniforms(){return this.material.uniforms}update(t,e,i,a){if(this.updateArrayUniforms(a),this.enabled=0!=this.material.defines.NUM_FOG_VOLUMES,!this.enabled)return;null==this.uniforms.cameraPosition&&(this.uniforms.cameraPos={value:new o}),this.uniforms.cameraPos.value.copy(t.position),this._viewProjection.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.uniforms.invProjection.value.copy(this._invViewProjection.copy(this._viewProjection).invert()),this.uniforms.tDepth.value=e.depthTexture,this.materialBlur.uniforms.tDepth.value=e.depthTexture,t instanceof n&&(this.uniforms.cameraNear.value=t.near,this.uniforms.cameraFar.value=t.far),this.uniforms.directionalLight.value.direction=i.lightDirection,this.uniforms.directionalLight.value.color.set(1,1,1).multiplyScalar(i.lightIntensity);const r=i.lights[i.lights.length-1];r&&r.shadow&&r.castShadow&&r.visible&&(this.uniforms.directionalShadowMap.value=r.shadow.map?.texture,this.uniforms.directionalShadowMatrix.value=r.shadow.matrix),r&&!r.visible?this.uniforms.directionalLight.value.color.set(0,0,0):this.uniforms.directionalLight.value.color.set(r.color.r,r.color.g,r.color.b).multiplyScalar(r.intensity*(r.userData?.volumetricIntensity??1));const s=a.children.find(t=>t.name===l);null!=s&&s.visible?this.uniforms.ambientLight.value.set(s.color.r,s.color.g,s.color.b).multiplyScalar(s.intensity*(s.userData?.volumetricIntensity??1)):this.uniforms.ambientLight.value.set(0,0,0)}}const u=new t.Vector2(1,0),f=new t.Vector2(0,1);/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{BackSide as e,Color as t,ShaderMaterial as i,UniformsLib as n,UniformsUtils as a,Object3D as l,Mesh as r,InstancedMesh as o,BatchedMesh as s,Vector3 as c}from"three";import{glslFunction as p,NodeShaderMaterial as u,Vec4Node as d,uniforms as m,transformed as v,neg as f,uniformFloat as h,uniformVec3 as _,vec3 as g,rgba as x,vec4 as k,negVec3 as A,ifDefApply as w,BooleanExpression as y,select as b,attributes as D}from"three-shader-graph";export class OutlineEffect{constructor(i,n={}){this.applied=new WeakSet,this.enabled=!0;const a=void 0!==n.defaultThickness?n.defaultThickness:.003,l=((new t).fromArray(void 0!==n.defaultColor?n.defaultColor:[0,0,0]),void 0!==n.defaultAlpha?n.defaultAlpha:1),r=void 0!==n.defaultKeepAlive&&n.defaultKeepAlive,o={},s={};["#include <common>","#include <uv_pars_vertex>","#include <displacementmap_pars_vertex>","#include <fog_pars_vertex>","#include <morphtarget_pars_vertex>","#include <skinning_pars_vertex>","#include <logdepthbuf_pars_vertex>","#include <clipping_planes_pars_vertex>","uniform float outlineThickness;","vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {","\tfloat thickness = outlineThickness;","\tconst float ratio = 1.0;","\tvec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );"," float viewDistance = length((modelViewMatrix * vec4(skinned.xyz, 1.0)).xyz);"," float scale = pow(viewDistance, 0.5); // sqrt, or any exponent","\tvec4 norm = normalize( pos - pos2 );","\treturn pos + norm * thickness * scale * ratio;","}","void main() {","\t#include <uv_vertex>","\t#include <beginnormal_vertex>","\t#include <morphnormal_vertex>","\t#include <skinbase_vertex>","\t#include <skinnormal_vertex>","\t#include <begin_vertex>","\t#include <morphtarget_vertex>","\t#include <skinning_vertex>","\t#include <displacementmap_vertex>","\t#include <project_vertex>","\tvec3 outlineNormal = - objectNormal;","\tgl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );","\t#include <logdepthbuf_vertex>","\t#include <clipping_planes_vertex>","\t#include <fog_vertex>","}"].join("\n"),["#include <common>","#include <fog_pars_fragment>","#include <logdepthbuf_pars_fragment>","#include <clipping_planes_pars_fragment>","uniform vec3 outlineColor;","uniform float outlineAlpha;","void main() {","\t#include <clipping_planes_fragment>","\t#include <logdepthbuf_fragment>","\tgl_FragColor = vec4( outlineColor, outlineAlpha );","\t#include <tonemapping_fragment>","\t#include <colorspace_fragment>","\t#include <fog_fragment>","\t#include <premultiplied_alpha_fragment>","}"].join("\n");function f(t){Array.isArray(t)&&(t=t[0]);const i=m.projectionMatrix.multiply(m.modelViewMatrix).multiplyVec(v.position);let n=v.normal;n=w("DOUBLE_SIDED",n,e=>b(new y("gl_FrontFacing"),e,e.multiplyScalar(-1)));const r=h("outlineThickness",a),o=_("outlineColor",new c(0,0,0)),s=h("outlineAlpha",l),f=p(d,{pos:i,normal:n,skinned:v.position,outlineThickness:r},"\n\t\t\t\tfloat thickness = outlineThickness;\n\t\t\t\tvec4 viewPos = modelViewMatrix * vec4(skinned.xyz, 1.0);\n\t\t\t\tfloat viewDistance = length(viewPos.xyz);\n\t\t\t\t// Clamp to safe domain\n\t\t\t\tviewDistance = max(viewDistance, 0.0001);\n\t\t\t\tfloat scale = sqrt(viewDistance) * 0.5;\n\t\t\t\tvec3 displaced = viewPos.xyz + normal * thickness * scale;\n\t\t\t\treturn projectionMatrix * vec4(displaced, 1.0);\n\t\t\t"),g=x(o,s),A=[g,k(0),k(0)],D="number"==typeof t.userData.mrtOutputs&&t.userData.mrtOutputs>1,M=new u({position:f,outputs:D?A:void 0,color:D?void 0:g});return M.side=e,M.depthTest=!0,M.depthWrite=!0,M.transparent=!0,M}this.createMaterial=f,this.getOutlineMaterial=function(e){const t=function(e){let t=o[e.uuid];return void 0===t&&(t={material:f(e),used:!0,keepAlive:r,count:0},o[e.uuid]=t),t.used=!0,t.material}(e);return s[t.uuid]=e,function(e,t){Array.isArray(t)&&(t=t[0]);if("invisible"===e.name)return;const i=t.userData.outlineParameters;e.fog=t.fog,e.toneMapped=t.toneMapped,e.premultipliedAlpha=t.premultipliedAlpha,e.displacementMap=t.displacementMap,void 0!==i?(!1===t.visible?e.visible=!1:e.visible=void 0===i.visible||i.visible,e.transparent=void 0!==i.alpha&&i.alpha<1||t.transparent,void 0!==i.keepAlive&&(o[t.uuid].keepAlive=i.keepAlive)):(e.transparent=t.transparent,e.visible=t.visible);!0!==t.wireframe&&!1!==t.depthTest||(e.visible=!1);t.clippingPlanes&&(e.clipping=!0,e.clippingPlanes=t.clippingPlanes,e.clipIntersection=t.clipIntersection,e.clipShadows=t.clipShadows);e.version=t.version}(t,e),t},this.updateUniforms=function(e,t){const i=t.userData.outlineParameters;e.uniforms.outlineAlpha.value=t.opacity,void 0!==i&&(void 0!==i.thickness&&(e.uniforms.outlineThickness.value=i.thickness),void 0!==i.color&&e.uniforms.outlineColor.value.fromArray(i.color),void 0!==i.alpha&&(e.uniforms.outlineAlpha.value=i.alpha)),t.displacementMap&&(e.uniforms.displacementMap.value=t.displacementMap,e.uniforms.displacementScale.value=t.displacementScale,e.uniforms.displacementBias.value=t.displacementBias)}}apply(e){if(!(e instanceof r)||e instanceof s||e instanceof o)return;if(this.applied.has(e))return;this.applied.add(e);const t=e.onAfterRender;e.onAfterRender=(i,n,a,l,r,o)=>{t(i,n,a,l,r);let s=!1;if(Array.isArray(r)?s=r.some(e=>e&&e.userData&&e.userData.outlineParameters):r&&r.userData&&r.userData.outlineParameters&&(s=!0),!s)return;const c=e.material,p=this.getOutlineMaterial(c);e.material=p,this.updateUniforms(p,r),i.renderBufferDirect(a,n,l,p,e,o),e.material=c}}}/*
1
+ import{BackSide as e,Color as t,ShaderMaterial as i,UniformsLib as n,UniformsUtils as a,Object3D as r,Mesh as l,InstancedMesh as o,BatchedMesh as s,Vector3 as u}from"three";import{glslFunction as c,NodeShaderMaterial as p,Vec4Node as d,uniforms as m,transformed as v,neg as f,uniformFloat as h,uniformVec3 as _,vec3 as g,rgba as x,vec4 as k,negVec3 as A,ifDefApply as y,BooleanExpression as w,select as D,attributes as b}from"three-shader-graph";export class OutlineEffect{constructor(i,n={}){this.applied=new WeakSet,this.enabled=!0;const a=void 0!==n.defaultThickness?n.defaultThickness:.003,r=((new t).fromArray(void 0!==n.defaultColor?n.defaultColor:[0,0,0]),void 0!==n.defaultAlpha?n.defaultAlpha:1),l=void 0!==n.defaultKeepAlive&&n.defaultKeepAlive,o={},s={};["#include <common>","#include <uv_pars_vertex>","#include <displacementmap_pars_vertex>","#include <fog_pars_vertex>","#include <morphtarget_pars_vertex>","#include <skinning_pars_vertex>","#include <logdepthbuf_pars_vertex>","#include <clipping_planes_pars_vertex>","uniform float outlineThickness;","vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {","\tfloat thickness = outlineThickness;","\tconst float ratio = 1.0;","\tvec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );"," float viewDistance = length((modelViewMatrix * vec4(skinned.xyz, 1.0)).xyz);"," float scale = pow(viewDistance, 0.5); // sqrt, or any exponent","\tvec4 norm = normalize( pos - pos2 );","\treturn pos + norm * thickness * scale * ratio;","}","void main() {","\t#include <uv_vertex>","\t#include <beginnormal_vertex>","\t#include <morphnormal_vertex>","\t#include <skinbase_vertex>","\t#include <skinnormal_vertex>","\t#include <begin_vertex>","\t#include <morphtarget_vertex>","\t#include <skinning_vertex>","\t#include <displacementmap_vertex>","\t#include <project_vertex>","\tvec3 outlineNormal = - objectNormal;","\tgl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );","\t#include <logdepthbuf_vertex>","\t#include <clipping_planes_vertex>","\t#include <fog_vertex>","}"].join("\n"),["#include <common>","#include <fog_pars_fragment>","#include <logdepthbuf_pars_fragment>","#include <clipping_planes_pars_fragment>","uniform vec3 outlineColor;","uniform float outlineAlpha;","void main() {","\t#include <clipping_planes_fragment>","\t#include <logdepthbuf_fragment>","\tgl_FragColor = vec4( outlineColor, outlineAlpha );","\t#include <tonemapping_fragment>","\t#include <colorspace_fragment>","\t#include <fog_fragment>","\t#include <premultiplied_alpha_fragment>","}"].join("\n");function f(t){Array.isArray(t)&&(t=t[0]);const i=m.projectionMatrix.multiply(m.modelViewMatrix).multiplyVec(v.position);let n=v.normal;n=y("DOUBLE_SIDED",n,e=>D(new w("gl_FrontFacing"),e,e.multiplyScalar(-1)));const l=h("outlineThickness",a),o=_("outlineColor",new u(0,0,0)),s=h("outlineAlpha",r),f=c(d,{pos:i,normal:n,skinned:v.position,outlineThickness:l},"\n\t\t\t\tfloat thickness = outlineThickness;\n\t\t\t\tvec4 viewPos = modelViewMatrix * vec4(skinned.xyz, 1.0);\n\t\t\t\tfloat viewDistance = length(viewPos.xyz);\n\t\t\t\t// Clamp to safe domain\n\t\t\t\tviewDistance = max(viewDistance, 0.0001);\n\t\t\t\tfloat scale = sqrt(viewDistance) * 0.5;\n\t\t\t\tvec3 displaced = viewPos.xyz + normal * thickness * scale;\n\t\t\t\treturn projectionMatrix * vec4(displaced, 1.0);\n\t\t\t"),g=x(o,s),A=[g,k(0),k(0)],b="number"==typeof t.userData.mrtOutputs&&t.userData.mrtOutputs>1,M=new p({position:f,outputs:b?A:void 0,color:b?void 0:g});return M.side=e,M.depthTest=!0,M.depthWrite=!0,M.transparent=!0,M}this.createMaterial=f,this.getOutlineMaterial=function(e){const t=function(e){let t=o[e.uuid];return void 0===t&&(t={material:f(e),used:!0,keepAlive:l,count:0},o[e.uuid]=t),t.used=!0,t.material}(e);return s[t.uuid]=e,function(e,t){Array.isArray(t)&&(t=t[0]);if("invisible"===e.name)return;const i=t.userData.outlineParameters;e.fog=t.fog,e.toneMapped=t.toneMapped,e.premultipliedAlpha=t.premultipliedAlpha,e.displacementMap=t.displacementMap,void 0!==i?(!1===t.visible?e.visible=!1:e.visible=void 0===i.visible||i.visible,e.transparent=void 0!==i.alpha&&i.alpha<1||t.transparent,void 0!==i.keepAlive&&(o[t.uuid].keepAlive=i.keepAlive)):(e.transparent=t.transparent,e.visible=t.visible);!0!==t.wireframe&&!1!==t.depthTest||(e.visible=!1);t.clippingPlanes&&(e.clipping=!0,e.clippingPlanes=t.clippingPlanes,e.clipIntersection=t.clipIntersection,e.clipShadows=t.clipShadows);e.version=t.version}(t,e),t},this.updateUniforms=function(e,t){const i=t.userData.outlineParameters;e.uniforms.outlineAlpha.value=t.opacity,void 0!==i&&(void 0!==i.thickness&&(e.uniforms.outlineThickness.value=i.thickness),void 0!==i.color&&e.uniforms.outlineColor.value.fromArray(i.color),void 0!==i.alpha&&(e.uniforms.outlineAlpha.value=i.alpha)),t.displacementMap&&(e.uniforms.displacementMap.value=t.displacementMap,e.uniforms.displacementScale.value=t.displacementScale,e.uniforms.displacementBias.value=t.displacementBias)}}apply(e){if(!(e instanceof l)||e instanceof s||e instanceof o)return;if(this.applied.has(e))return;if(!function(e){if(Array.isArray(e.material))return e.material.some(e=>e&&e.userData&&e.userData.outlineParameters);if(e.material&&e.material.userData&&e.material.userData.outlineParameters)return!0;return!1}(e))return;this.applied.add(e);const t=e.onAfterRender;e.onAfterRender=(i,n,a,r,l,o)=>{t(i,n,a,r,l);let s=!1;if(Array.isArray(l)?s=l.some(e=>e&&e.userData&&e.userData.outlineParameters):l&&l.userData&&l.userData.outlineParameters&&(s=!0),!s)return;const u=e.material,c=this.getOutlineMaterial(u);e.material=c,this.updateUniforms(c,l),i.renderBufferDirect(a,n,r,c,e,o),e.material=u}}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -111,11 +111,19 @@ export declare class RenderingView {
111
111
  private setupCsm;
112
112
  private gbufferMaterialCache;
113
113
  private tbufferMaterialCache;
114
+ /**
115
+ * If the material such as a standard material has updated properties, then we need to update
116
+ * the corresponding g buffer material
117
+ * @param source
118
+ * @param target
119
+ */
120
+ private updateMaterialProperties;
114
121
  /**
115
122
  * Updates uniform values from source material to target material.
116
123
  * Optimized for hot path execution in rendering loop.
117
124
  */
118
125
  private updateUniformValues;
126
+ private updateMaterialCommonProperties;
119
127
  /**
120
128
  * After rendering the opaque scene, we will also calculate lights which updates uniforms.
121
129
  * These need to be present on the gbuffer materials so we need to copy them afterward.
package/dist/rendering.js CHANGED
@@ -1,4 +1,4 @@
1
- var e;import{__decorate as t,__metadata as s}from"tslib";import*as i from"three";import{Color as r,Material as a,Matrix4 as n,Mesh as o,PerspectiveCamera as l,ShaderChunk as h,ShaderMaterial as d,WebGLRenderTarget as u,Texture as c,Euler as p,MeshStandardMaterial as m}from"three";import{CopyShader as f,EffectComposer as g,FXAAShader as M,GammaCorrectionShader as v,LUTPass as T,RenderPass as y,ShaderPass as x,VRButton as b}from"three-stdlib";import{CSMShader as w,CSMUtil as P}from"./csm.js";import{bool as S,colorToNormal as R,float as C,NodeShaderMaterial as A,standardMaterial as U,uniformFloat as F,uniformVec3 as B,toonMaterial as O,lambertMaterial as D,normalize as I,rgb as E,rgba as L,textureSampler2d as _,transformed as j,varying as G,varyingAttributes as W,varyingTransformed as V,vec4 as q,BooleanExpression as k,select as N,ifDefApply as z,uniformSampler2d as H,RgbaNode as $,mix as X,vec3 as Y,Vec3ExpressionNode as Q}from"three-shader-graph";import{Reflector as K}from"three-stdlib";import{BokehPass as J,OutputPass as Z}from"three/examples/jsm/Addons.js";import{CSM as ee}from"three/examples/jsm/csm/CSM.js";import te from"three/examples/jsm/libs/stats.module.js";import{GTAOPass as se}from"three/examples/jsm/postprocessing/GTAOPass.js";import{Service as ie}from"typedi";import{depthUniformName as re,farUniformName as ae,nearUniformName as ne,resolutionUniformName as oe,sceneNormalUniformName as le,screenUV as he,supportsDepthTextureExtension as de}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as ue}from"./shader-nodes/time.js";import{aoMapUniformName as ce,sceneMapUniformName as pe}from"./shader-nodes/scene-sample.js";import{DepthPass as me}from"./utils/three/depth-pass.js";import{GPUStatsPanel as fe}from"./utils/three/gpu-stats-panel.js";import{OutlinePass as ge}from"./utils/three/outline-pass.js";import{findFirstVisibleObject as Me,traverseVisibleStop as ve}from"./utils/three/traverse.js";import{clamp as Te}from"./utils/math.js";import{ColorPass as ye}from"./rendering/color-pass.js";import{SSRPass as xe}from"./rendering/ssr/SSRPass.js";import{SSRShader as be}from"./rendering/ssr/SSRShader.js";import{VolumetricFogPass as we}from"./rendering/fog/volumetric-fog-pass.js";import{OutlineEffect as Pe}from"./rendering/outline-effect.js";import{UnrealBloomPass as Se}from"./rendering/bloom/UnrealBloomPass.js";import{highPrecisionEyeDepth as Re}from"./shader-nodes/depth.js";import{packDepthToRGBA as Ce}from"three-shader-graph";import{FogVolumeObject as Ae}from"./rendering/fog/fog-volume-object";import{ParallaxStandardMaterial as Ue}from"./shader/builtin/standard-shader.js";import{parallaxOcclusionMapping as Fe}from"./shader-nodes/pom.js";import{FullScreenQuad as Be}from"three-stdlib";import{edgeDepthEffect as Oe}from"./shader-nodes/effects";import{decalDiscard as De}from"./shader-nodes/decal.js";import{Pass as Ie}from"three/examples/jsm/Addons.js";P.patchSetupMaterial();const Ee=document.createElement("div");Ee.style.position="absolute",Ee.style.left="50%",Ee.style.top="50%",Ee.style.color="black",Ee.style.zIndex="999";(new i.Layers).set(9);const Le=new i.MeshBasicMaterial({color:"black"}),_e=new i.MeshDepthMaterial;var je;_e.depthPacking=i.RGBADepthPacking,_e.blending=i.NoBlending,_e.side=i.DoubleSide,function(e){e[e.opaque=0]="opaque",e[e.transparent=1]="transparent"}(je||(je={}));const Ge=(()=>{const e=new Uint8Array([255,255,255,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),We=(()=>{const e=new Uint8Array([0,0,0,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),Ve=(()=>{const e=new Uint8Array([128,128,255,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),qe=new A({color:C(0),position:q(C(0))});qe.visible=!1;const ke=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let Ne=0,ze=e=class{setPaused(e){this.paused=e}resizeRender(){if(!this.running)return;const e=this.container.clientWidth,t=this.container.clientHeight;this.previousClientWith===e&&this.previousClientHeight===t||0!==e&&0!==t&&(this.previousClientWith=e,this.previousClientHeight=t,this.camera instanceof l&&(this.camera.aspect=e/t,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,window.devicePixelRatio)*this.resolutionScale),this.renderer.setSize(e,t),this.composer.setSize(e,t),this.dofPass.setSize(e*this.renderer.getPixelRatio(),t*this.renderer.getPixelRatio()),this.fxaaPass.setSize(e*this.renderer.getPixelRatio(),t*this.renderer.getPixelRatio()),this.fxaaPass.uniforms.resolution.value.set(1/(e*this.renderer.getPixelRatio()),1/(t*this.renderer.getPixelRatio())),this.createGRenderTarget(),this.phasedRenderPass.gRenderTarget=this.gRenderTarget,this.bloomPass.emissiveTexture=this.gRenderTarget.textures[1],this.ssrPass.setSize(this.gRenderTarget.width,this.gRenderTarget.height),this.ssrPass.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),this.aoPass.setSize(this.gRenderTarget.width,this.gRenderTarget.height),this.aoPass.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),this.sceneColorRenderTarget.dispose(),this.sceneColorRenderTarget=this.createSceneColorRenderTarget(this.renderer,this.container),this.copyPass.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[0],this.copyPass.material.uniformsNeedUpdate=!0)}addPostProcessVolume(e){if(0===this.postProcessVolumes.length)this.postProcessVolumes.push(e);else{let t=!1;for(let s=0;s<this.postProcessVolumes.length;s++)if(e.priority<this.postProcessVolumes[s].priority){this.postProcessVolumes.splice(s,0,e),t=!0;break}t||this.postProcessVolumes.push(e)}}removePostProcessVolume(e){const t=this.postProcessVolumes.indexOf(e);t>-1&&this.postProcessVolumes.splice(t,1)}constructor(t,s={}){this.container=t,this.options=s,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.postProcessVolumes=[],this.postProcessSettings={},this.csmUpdateInvervals=this.options.shadows?.cascadeUpdateIntervals,this._id=Ne++,this.fquadCopy=new Be(new d(f)),this.fquadCopyOpaque=new Be(new A({outputs:[H("tSceneColor",new c).sample(W.uv),q(H("tDepthTexture",new i.DepthTexture(1,1)).sample(W.uv).r)]})),this.fquadBlendAO=(()=>{const e=q(1),t=new A({outputs:[H("tAO",new c).sample(he),e,e],transparent:!0});t.depthWrite=!1,t.depthTest=!1,t.blending=i.MultiplyBlending;return new Be(t)})(),this.resolutionScale=1,this.maxPixelRatio=ke?1:window.devicePixelRatio,this.onResize=()=>{if(this.resizeRender(),!this.paused)try{this.render()}catch(e){}},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!0,this.onLoopCallbacks=[],this.stats=new te,this._showStats=!0,this.gbufferMaterialCache=new Map,this.tbufferMaterialCache=new Map,this.gBufferCachedMaterials=new Map,this.gBufferCachedVisibility=[],this._initiatedMaterialTextures=new Set,this._initiatedTextures=new Set,this.compileInProgress=!1,this.pmremGeneratorResults=new WeakMap,this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,this.prevClearColor=new r,this.hadBloom=!1,this.bloomStoredMaterials={},this.bloomHidden=[],this._customDepthMaterialCache=new WeakMap,null!=s.maxPixelRatio&&(this.maxPixelRatio=s.maxPixelRatio),this.resolutionScale=s.resolutionScale??1,window.renderer=this.renderer=new i.WebGLRenderer({antialias:!1,powerPreference:"high-performance"});new i.MeshStandardMaterial({color:"#ccc"});this.scene=new i.Scene,this.scene.matrixWorldAutoUpdate=!0,this.scene.updateMatrixWorld=function(e){const t=this.children;for(let s=0,i=t.length;s<i;s++){t[s].updateMatrixWorld(e)}}.bind(this.scene),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,window.devicePixelRatio)*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(b.createButton(this.renderer));const a=new Pe(this.renderer,{defaultThickness:.005,defaultColor:[0,0,0],defaultAlpha:1,defaultKeepAlive:!0});this.outlineEffect=a,this.createGRenderTarget(),this.composer=new g(this.renderer),this.composer.setSize(t.clientWidth,t.clientHeight);var n=(t.clientWidth||1)/(t.clientHeight||1);const o=new i.PerspectiveCamera(45,n,.5,800);o.layers.enable(19),this.setCamera(o),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=i.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=s.shadows?.autoUpdate??!1,this.renderer.outputColorSpace=i.SRGBColorSpace,this.renderer.toneMapping=i.NoToneMapping,this.renderer.toneMappingExposure=1,this.renderer.gammaFactor=1.4,P.renderingView=this,this.isDepthTextureExtensionSupported=de(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.aoMaskDepthRenderTarget=e.createAOMaskDepthRenderTarget(this.renderer,this.container),this.sceneColorRenderTarget=this.createSceneColorRenderTarget(this.renderer,this.container);const l=new i.Vector2(t.clientWidth,t.clientHeight),h=(new y(this.scene,this.camera),new x(f,"prevtexture"));h.enabled=!0,h.needsSwap=!0,h.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[0],this.copyPass=h;const u=new Se(l,1.5,.4,.85);u.threshold=1,u.strength=.9,u.radius=.5,this.bloomPass=u;const p=new se(this.scene,this.camera,this.gRenderTarget.width,this.gRenderTarget.height,{});p.normalRenderTarget?.dispose(),p.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),p.output=se.OUTPUT.Off,p.enabled=!1,this.aoPass=p,this.fquadBlendAO.material.uniforms.tAO.value=p.pdRenderTarget.texture,be.fragmentShader=be.fragmentShader.replace("if(metalness==0.) return;","if(metalness<0.1) return;");const m=new xe({renderer:this.renderer,scene:this.scene,camera:this.camera,width:this.gRenderTarget.width,height:this.gRenderTarget.height,groundReflector:null,selects:[],normalTexture:this.gRenderTarget.textures[2],depthTexture:this.gRenderTarget.depthTexture});m.output=xe.OUTPUT.Default,m.blur=!0,m.fresnel=!1,m.distanceAttenuation=!0,m.maxDistance=50,m.selective=!0,m.bouncing=!1,m.opacity=.4,m.enabled=!1!==this.options?.reflection?.enabled,this.ssrPass=m,!1!==this.options.ao?.enabled&&this.composer.addPass(p);const w=new nt((e,t,s,i,r)=>{this.aoPass.enabled&&(this.initResolutionUniform(this.fquadBlendAO.material),this.renderer.setRenderTarget(this.gRenderTarget),this.fquadBlendAO.render(this.renderer),this.renderer.setRenderTarget(null))});this.composer.addPass(w);const S=new nt((e,t,s,i,r)=>{this.renderer.setRenderTarget(this.gRenderTarget),this.renderScene(je.transparent),this.renderer.setRenderTarget(null)});this.composer.addPass(S),this.composer.addPass(h),this.composer.addPass(m),this.phasedRenderPass=new at(this.scene,this.camera,this.gRenderTarget),this.composer.addPass(this.phasedRenderPass),this.composer.addPass(u),u.emissiveTexture=this.gRenderTarget.textures[1],this.renderer.info.autoReset=!1,this.volumetricFogPass=new we(l),this.composer.addPass(this.volumetricFogPass),this.volumetricFogPass.enabled=!0,this.dofPass=new J(this.scene,this.camera,{focus:1,aperture:.025,maxblur:.01}),this.dofPass.enabled=!1,this.composer.addPass(this.dofPass);const R=new ye;this.composer.addPass(R),this.colorPass=R,R.vignetteEnabled=!1,this.outlinePass=new ge(new i.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.outlinePass.enabled=!1,this.composer.addPass(this.outlinePass);const C=new x(M);C.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(C),this.fxaaPass=C,this.fxaaPass.enabled=!1,!0===s.enableOutlines&&this.setEnableOutlines(!0),new x(v).clear=!1,this.fixStatsStyle(),this.lutPass=new T({}),this.lutPass.enabled=!1,this.composer.addPass(this.lutPass);const U=new x(f,"prevtexture");U.enabled=!0,U.needsSwap=!1,U.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[1],U.renderToScreen=!0;const F=new Z;this.composer.addPass(F)}fixStatsStyle(){const e=this.stats.dom;e.style.position="absolute";const t=e.getElementsByTagName("canvas");for(let e=0;e<t.length;e++)t.item(e).style.display="inline-block"}setEnableOutlines(e){this.outlinePass.enabled=e,this.fxaaPass.enabled=e}setCamera(e){if(this.camera=e,this.composer.passes.forEach(t=>{t instanceof y?t.camera=e:t instanceof ge?t.renderCamera=e:(t instanceof me||t instanceof se)&&(t.camera=e)}),this.ssrPass&&(this.ssrPass.camera=e),this.aoPass&&(this.aoPass.camera=e),this.phasedRenderPass&&(this.phasedRenderPass.camera=e),null==this.csm){if(this.csm=new ee({maxFar:100,lightFar:250,lightMargin:20,cascades:ke?2:4,shadowMapSize:2048*(ke?.5:1),lightDirection:new i.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5*Math.PI,camera:this.camera,parent:this.scene,mode:"practical"}),null!=this.csmUpdateInvervals){this.csmCascadeLastUpdate=new Array(this.csm.lights.length).fill(0);for(const e of this.csm.lights)e.shadow.autoUpdate=!1}this.csm&&Array.isArray(this.csm.lights),this.csm.fade=!0,h.lights_fragment_begin=w.lights_fragment_begin}else this.csm.camera=this.camera,this.camera;this.csm.updateFrustums()}setSelectedObjects(e){if(null==this.outlinePass)return;const t=new Map;for(const s of e)t.set(s.uuid,s);for(const s of e)s.traverse(e=>{e.uuid!==s.uuid&&t.has(e.uuid)&&t.delete(e.uuid)});this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(e,t,s){const r=Math.max(1,Math.floor(t.clientWidth*s)),a=Math.max(1,Math.floor(t.clientHeight*s)),n=new i.WebGLRenderTarget(r,a);return n.texture.minFilter=i.NearestFilter,n.texture.magFilter=i.NearestFilter,n.texture.generateMipmaps=!1,n.stencilBuffer=!1,n.depthTexture=new i.DepthTexture(r,a),n.depthTexture.type=i.UnsignedShortType,n.depthTexture.minFilter=i.NearestFilter,n.depthTexture.magFilter=i.NearestFilter,n}static createAOMaskDepthRenderTarget(e,t){const s=Math.max(1,t.clientWidth*e.getPixelRatio()),r=Math.max(1,t.clientHeight*e.getPixelRatio()),a=new i.DepthTexture(s,r);a.type=i.UnsignedInt248Type,a.minFilter=i.NearestFilter,a.magFilter=i.NearestFilter;const n=new i.WebGLRenderTarget(s,r,{type:i.HalfFloatType,depthTexture:a});return n.texture.minFilter=i.NearestFilter,n.texture.magFilter=i.NearestFilter,n.texture.generateMipmaps=!1,n.stencilBuffer=!1,n}createSceneColorRenderTarget(e,t){const s=this.gRenderTarget.width,r=this.gRenderTarget.height,a=new i.WebGLRenderTarget(s,r,{count:2,type:i.FloatType,format:i.RGBAFormat,colorSpace:i.SRGBColorSpace,depthBuffer:!1,stencilBuffer:!1});return a.texture.minFilter=i.LinearFilter,a.texture.magFilter=i.LinearFilter,a.texture.generateMipmaps=!1,a.textures[1].minFilter=i.NearestFilter,a.textures[1].magFilter=i.NearestFilter,a}createGRenderTarget(){const e=this.container;null!=this.gRenderTarget&&this.gRenderTarget.dispose();const t=Math.max(1,e.clientWidth*this.renderer.getPixelRatio()),s=Math.max(1,e.clientHeight*this.renderer.getPixelRatio()),r=new i.DepthTexture(t,s);r.type=i.UnsignedIntType,r.minFilter=i.NearestFilter,r.magFilter=i.NearestFilter,this.gRenderTarget=new u(t,s,{count:3,minFilter:i.NearestFilter,magFilter:i.NearestFilter,type:i.HalfFloatType,format:i.RGBAFormat,depthTexture:r}),this.gRenderTarget.texture.generateMipmaps=!1,this.gRenderTarget.stencilBuffer=!1}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.gRenderTarget.dispose(),this.aoMaskDepthRenderTarget.dispose(),this.sceneColorRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren(),this.volumetricFogPass.dispose(),P.clearSceneCache(this.scene)}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);t>=0&&this.onLoopCallbacks.splice(t,1)}set showStats(e){this._showStats=e,this._showStats&&!this.container.contains(this.stats.dom)?this.container.appendChild(this.stats.dom):!this._showStats&&this.container.contains(this.stats.dom)&&this.container.removeChild(this.stats.dom)}get showStats(){return this._showStats}applyEnvMap(e){if(null!=this.scene.environment&&(e instanceof A&&(null==e.envMap||e.userData.useSceneEnv)&&(e.userData.useSceneEnv=!0,null==e.uniforms.envMap&&(e.uniforms.envMap={value:this.scene.environment},e.uniformsNeedUpdate=!0,e.uniforms.envMapRotation={value:et(this.scene.environmentRotation,this.scene.environment,new i.Matrix3)}),null==e.uniforms.envMapIntensity&&(e.uniforms.envMapIntensity={value:1},e.uniformsNeedUpdate=!0),e.uniforms.envMap.value=this.scene.environment,e.uniforms.envMapIntensity.value=this.scene.environmentIntensity,e.envMap=this.scene.environment),e instanceof A||e instanceof i.MeshStandardMaterial)){const t=this.gbufferMaterialCache.get(e);null==t||this.gbufferMaterialCache.has(t)||this.applyEnvMap(t)}}setupCsm(e){if(e instanceof i.Mesh||e instanceof i.SkinnedMesh)if(e.material instanceof Array)for(const t of e.material)this.csm.setupMaterial(t);else this.csm.setupMaterial(e.material)}updateUniformValues(e,t){const s=e.uniforms,i=t.uniforms;for(const e in s){const t=i[e],r=s[e].value;null!=t&&t.value!==r&&"receiveShadow"!==e&&!1===ot.includes(e)&&(t.value=r)}}updateLightUniformValues(e,t){const s=e.uniforms,i=t.uniforms;for(const e of ot){const t=i[e],r=s[e];null!=r&&null!=t&&(t.value=r.value)}}createGBufferMaterial(e,t){const s=t===je.opaque?this.gbufferMaterialCache:this.tbufferMaterialCache;let r=s.get(e);if(!0===e.userData.isGBufferMaterial)return e;if(null==r){let n=W.uv;if(e instanceof Ue&&null!=e.heightMap){const t=F("heightScale",e.heightScale??1);n=Fe(n,_(e.heightMap),t)}let o=V.normal;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){const t=e.normalMap??Ve,s=F("useNormalMap",null!=e.normalMap?1:0),i=F("normalScale",e.normalScale?.x??1),r=R(_(t).sample(n),i);o=X(V.normal,r,s)}else e instanceof A&&null!=e.outputNormal&&(o=e.outputNormal);!0!==e.userData.disableAO&&(o=z("DOUBLE_SIDED",o,e=>N(new k("gl_FrontFacing"),e,e.multiplyScalar(-1))));let l=e.userData?.reflective?C(0):C(1);if(e instanceof i.MeshStandardMaterial){const t=F("roughness",e.roughness??1),s=e.roughnessMap??Ge,i=F("useRoughnessMap",null!=e.roughnessMap?1:0),r=_(s).sample(n).g.multiply(t);l=X(t,r,i)}else e instanceof A&&null!=e.outputRoughness&&(l=e.outputRoughness);let h=null;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial||e instanceof i.MeshBasicMaterial){const t=e.lightMap??We,s=F("useLightMap",null!=e.lightMap?1:0),i=F("lightMapIntensity",e.lightMapIntensity??1),r=_(t).sample(n).rgb.multiplyScalar(i);h=X(E(0),r,s)}let u=C(0);if(e instanceof i.MeshStandardMaterial){const t=F("metalness",e.metalness??0),s=e.metalnessMap??We,i=F("useMetalnessMap",null!=e.metalnessMap?1:0),r=_(s).sample(n).b.multiply(t);u=X(t,r,i)}else e instanceof A&&e.outputRoughness;let c=null,p=C(1);if(e instanceof i.MeshStandardMaterial){const t=e.aoMap??Ge,s=F("useAoMap",null!=e.aoMap?1:0);p=F("aoMapIntensity",e.aoMapIntensity??1);const i=_(t).sample(n).r;c=X(C(1),i,s)}else e instanceof A&&e.outputRoughness;const f=F("opacity",e.opacity??1);let g=C(1);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){const t=e.alphaMap??Ge,s=F("useAlphaMap",null!=e.alphaMap?1:0),i=_(t).sample(n).r;g=X(C(1),i,s),g=g.multiply(f)}else e instanceof A&&null!=e.outputOpacity&&(g=e.outputOpacity);let M=L(0,1);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial||e instanceof i.MeshBasicMaterial){let t=B("color",(new i.Vector3).setFromColor(e.color));if(e.vertexColors){const e=G(z("USE_COLOR",Y(1,1,1),e=>new Q("color")));t=t.multiply(e)}const s=e.map??Ge,r=F("useAlbedoMap",null!=e.map?1:0),a=_(s).sample(n),o=a.multiply(L(t,1)),l=L(t,1);M=X(l,o,r);const h=X(C(1),a.w,r);g=g.multiply(h)}const v=!0===e.userData.hasBloom;let T=E(0);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){const t=B("emissive",(new i.Vector3).setFromColor(e.emissive)),s=F("emissiveIntensity",e.emissiveIntensity),r=e.emissiveMap??We,a=F("useEmissiveMap",null!=e.emissiveMap?1:0),o=_(r).sample(n).rgb.multiply(t);T=X(t,o,a),T=T.multiplyScalar(s)}else e instanceof A&&null!=e.outputEmissive&&(T=e.outputEmissive);const y=e instanceof d&&null!=e.uniforms[re],x=e instanceof d&&null!=e.uniforms[pe],b=e instanceof d&&null!=e.uniforms[ce],w=e.transparent&&e.alphaTest<=.01||e.blending===i.AdditiveBlending,P=F("alphaTest",e.alphaTest);let j,H=e.alphaTest>0?g.lt(P):w&&t===je.opaque?g.lt(.8):S(!1);!0===e.userData.isDecal&&(H=H.or(De)),j=w?q(0,0,0,0):(a=o,I(a).multiplyScalar(.5).addScalar(.5)).rgba(e.userData?.reflective?l:1);const $=e instanceof A?e.outputPosition:void 0,K=e instanceof A?e.outputTransform:void 0;let J,Z=L("black",1);if(e instanceof A&&null!=e.outputColor)Z=e.outputColor;else if(e instanceof i.MeshStandardMaterial)Z=U({color:M,metalness:u,roughness:l,emissive:T.rgb,normal:o,ambientOcclusion:c,ambientOcclusionIntensity:p,bakedLight:h});else if(e instanceof i.MeshLambertMaterial||e instanceof i.MeshPhongMaterial)Z=D({color:M.rgb});else if(e instanceof i.MeshBasicMaterial){let e=M.rgb,t=h??E("white");null!=c&&(t=t.multiplyScalar(c.subtract(1).multiply(p).add(1))),e=e.add(t),Z=e.rgba(g)}else e instanceof i.MeshToonMaterial&&(Z=O({color:M,emissive:T.rgb,normal:o,ambientOcclusion:c,ambientOcclusionIntensity:p,bakedLight:h}));(e instanceof A||e instanceof i.MeshStandardMaterial)&&(J=e.envMap);let ee=!0;(e instanceof m||e instanceof i.MeshBasicMaterial||e instanceof i.ShaderMaterial)&&(ee=e.fog);let te=L(Z.rgb,g);ee&&(te=new FogNode(te));let se=!0;if(t===je.opaque?(se&&(se=!y&&!x&&!b),se&&(se=!w)):t===je.transparent&&se&&(se=w||y||x||b),!se)return r=qe,s.set(e,r),r;r=new A({transform:K,position:null==K?$:void 0,outputs:[te,T.rgba(t===je.opaque?P:v?1:0),j],opacity:g,outputEncoding:!1,fog:ee,transparent:e.transparent,lights:!0,envMap:J,discard:H}),e instanceof i.MeshStandardMaterial&&null!=e.envMap&&null!=r.uniforms.envMapIntensity&&(r.uniforms.envMapIntensity.value=e.envMapIntensity),(e instanceof A||e instanceof i.MeshStandardMaterial)&&this.applyEnvMap(r),e instanceof A&&(Object.assign(r.defines,e.defines),null!=r.uniforms[ce]&&(r.uniforms[ce].value=this.aoPass.pdRenderTarget.texture,r.defines.USE_SSAO_MAP="")),r.userData.mrtOutputs=3,r.forceSinglePass=e.forceSinglePass,r.side=e.side,r.blending=e.blending,w?(r.depthWrite=!e.transparent,r.depthTest=e.depthTest,r.colorWrite=t===je.transparent):(r.depthWrite=e.depthWrite,r.depthTest=e.depthTest),r.visible=e.visible,r.alphaTest=e.alphaTest,r.alphaHash=e.alphaHash,r.vertexColors=e.vertexColors,r.premultipliedAlpha=e.premultipliedAlpha,r.toneMapped=e.toneMapped,r.blendAlpha=e.blendAlpha,r.blendColor=e.blendColor,r.polygonOffset=e.polygonOffset,r.polygonOffsetFactor=e.polygonOffsetFactor,r.polygonOffsetUnits=e.polygonOffsetUnits,r.blending=e.blending,r.userData.isGBufferMaterial=!0,r.visible=se,Object.assign(r.userData,e.userData),r.visible&&(this.csm.setupMaterial(r),e instanceof d&&Object.assign(r.uniforms,e.uniforms)),s.set(e,r)}var a;return r.visible&&e instanceof d&&this.updateUniformValues(e,r),r}updateCsm(){const e=this.csmUpdateInvervals;if(this.renderer.shadowMap.autoUpdate&&null!=this.csmCascadeLastUpdate&&Array.isArray(e)){const t=performance.now();for(let s=0;s<this.csm.lights.length;++s){const i=e[s]??e[e.length-1]??16;if(t-this.csmCascadeLastUpdate[s]>=i&&this.csm.lights[s].shadow){this.csm.lights[s].shadow.needsUpdate=!0,this.csmCascadeLastUpdate[s]=t;break}}}this.csm.update()}loop(e,t=!1){const s=this.stats,r=s.addPanel(new te.Panel("Calls","#83f","#002")),a=s.addPanel(new te.Panel("Triangles","#c32","#002"));let l;navigator.userAgent.includes("Chrome")&&navigator.userAgent.includes("HologyEngine")&&(l=new fe(this.renderer.getContext()),s.addPanel(l)),this.showStats=t;let h=10,d=1e3;const u=()=>{const e=this.renderer.info.render.calls;e>h&&(h=e,setTimeout(()=>h=10,5e3)),r.update(e,h);const t=this.renderer.info.render.triangles;t>d&&(d=t,setTimeout(()=>d=1e3,5e3)),a.update(t,d)};performance.now();i.Ray.prototype.intersectTriangle;this.resizeRender();const c=[],p=[],m=[];let f=0;const g=new n,M=new n;let v=0;let T=this.paused;const y=t=>{const r=this.renderer.getContext();if(this.paused&&this.running&&r.drawingBufferHeight>1)return setTimeout(()=>y(t),500),void(T=!0);this.renderer.clear(),this.applyPostProcessSettings(),this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,s.begin(),this.showStats&&l?.startQuery(),this.ssrPass.gpuPanel=l;let a=(t*=.001)-f;if(f=t,T&&(a=.016,T=!1),g.copy(this.camera.matrixWorld),a>1){let t=a;for(;t>.05;)e(He),t-=He;e(t)}else e(a);this.onLoopCallbacks.forEach(e=>e(a)),this.camera?.updateMatrixWorld(),M.copy(this.camera.matrixWorld),t-v>.08&&!M.equals(g)&&(this.renderer.shadowMap.needsUpdate=!0,v=t),this.updateCsm();let n=!1;c.length=0,p.length=0,m.length=0;const h=Xe;Qe.multiplyMatrices(this.camera.projectionMatrix,this.camera.matrixWorldInverse),h.setFromProjectionMatrix(Qe);let d=!1,x=!1,b=!1;this.scene.traverseVisible(e=>{if(this.setupCsm(e),this.outlineEffect.apply(e),e instanceof Ae&&(d=!0),e instanceof o&&this.initCustomDepthMaterial(e),(e instanceof o||e instanceof i.Sprite)&&(this.initResolutionUniform(e.material),this.initNormalUniform(e.material),this.initShadowUniform(e,e.material),null!=this.scene.environment&&function(e,t){if(Array.isArray(e.material))for(const s of e.material)t(s);else null!=e.material&&t(e.material)}(e,e=>this.applyEnvMap(e)),!0===e.material?.userData?.hasBloom&&(n=!0)),(e instanceof o||e instanceof i.Sprite)&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[re])&&isObjectInFrustum(e,h)?(this.initDepthUniform(e.material),x=!0):e instanceof K&&(e.visible=!1,p.push(e)),(e instanceof o||e instanceof i.Sprite)&&e.material?.uniforms&&null!=e.material?.uniforms[ce]&&isObjectInFrustum(e,h)&&e.material instanceof A&&this.initAoUniform(e.material),(e instanceof o||e instanceof i.Sprite)&&e.material?.uniforms&&null!=e.material?.uniforms[pe]&&isObjectInFrustum(e,h)&&(m.push(e),e.material.uniforms[pe].value=this.sceneColorRenderTarget.texture,b=!0),e instanceof o&&e.material?.uniforms&&null!=e.material?.uniforms[ue])e.material.uniforms[ue].value=t;else if(e instanceof o&&Array.isArray(e.material))for(const s of e.material)s.uniforms&&null!=s.uniforms[ue]&&(s.uniforms[ue].value=t)}),this.bloomPass.enabled=n,this.renderer.setRenderTarget(this.gRenderTarget),this.renderer.clear(),this.renderScene(je.opaque),this.aoPass.output=se.OUTPUT.Off,(x||b)&&(this.fquadCopyOpaque.material.uniforms.tSceneColor.value=this.gRenderTarget.textures[0],this.fquadCopyOpaque.material.uniforms.tDepthTexture.value=this.gRenderTarget.depthTexture,this.initResolutionUniform(this.fquadCopyOpaque.material),this.renderer.setRenderTarget(this.sceneColorRenderTarget),this.renderer.clear(),this.fquadCopyOpaque.render(this.renderer),this.renderer.setRenderTarget(this.gRenderTarget)),m.length,c.forEach(e=>e.visible=!0),p.forEach(e=>e.visible=!0),m.forEach(e=>e.visible=!0),this.aoPass.enabled,this.ssrPass&&(this.ssrPass.elapsedTime=t),this.volumetricFogPass&&d&&this.volumetricFogPass.update(this.camera,this.gRenderTarget,this.csm,this.scene);try{!this.paused&&this.running&&(this.render(a),this.showStats&&l?.endQuery(),this.showStats&&u(),this.renderer.info.reset(),this.renderOverlay())}catch(e){console.warn(e)}s.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout(()=>{requestAnimationFrame(y)},1e3/this.fpsCap):requestAnimationFrame(y))};!0===this.options.enableXR?this.renderer.setAnimationLoop(y):requestAnimationFrame(y)}applyGBufferMaterials(e){const t=this.gBufferCachedMaterials,s=this.gBufferCachedVisibility;t.clear(),s.length=0;ve(this.scene,i=>{if(it(i))return s.push(i),i.visible=!1,!1;if(i instanceof o){t.set(i,i.material);let r=!1;if(Array.isArray(i.material)){i.material=i.material.slice();for(let t=0;t<i.material.length;t++)i.material[t]=this.createGBufferMaterial(i.material[t],e),r||(r=i.material[t].visible),this.initShadowUniform(i,i.material[t])}else i.material=this.createGBufferMaterial(i.material,e),r||(r=i.material.visible),this.initShadowUniform(i,i.material);r?i.visible=!0:null!=i.children&&0!=i.children.length||(s.push(i),i.visible=!1)}})}unapplyGBufferMaterials(){this.gBufferCachedMaterials.forEach((e,t)=>{t.material=e}),this.gBufferCachedVisibility.forEach((e,t)=>{e.visible=!0,e.updateMatrixWorld(!0)})}initTextures(e=this.scene){e.traverse(e=>{if(e instanceof o)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++)this._initMaterialTextures(e.material[t]);else this._initMaterialTextures(e.material)})}_initMaterialTextures(e){if(!this._initiatedMaterialTextures.has(e))if(this._initiatedMaterialTextures.add(e),e instanceof d){for(const[t,s]of Object.entries(e.uniforms))if(s.value instanceof c){if(this._initiatedTextures.has(s.value))continue;this.renderer.initTexture(s.value),this._initiatedTextures.add(s.value)}}else for(const[t,s]of Object.entries(e))if(s instanceof c){if(this._initiatedTextures.has(s))continue;this.renderer.initTexture(s),this._initiatedTextures.add(s)}}async compileAsync(e=this.scene){if(this.compileInProgress)return;this.renderer.setRenderTarget(this.gRenderTarget),this.compileInProgress=!0,this.applyGBufferMaterials(je.opaque),await this.renderer.compileAsync(e,this.camera),this.unapplyGBufferMaterials(),this.applyGBufferMaterials(je.transparent),await this.renderer.compileAsync(e,this.camera),this.unapplyGBufferMaterials(),e===this.scene&&(this.renderer.setRenderTarget(this.gRenderTarget),this.renderer.compileAsync(this.fquadBlendAO.mesh,this.fquadBlendAO.camera),this.renderer.setRenderTarget(this.sceneColorRenderTarget),this.renderer.compileAsync(this.fquadCopyOpaque.mesh,this.fquadCopyOpaque.camera));const t=this.csm.lights[0]?.shadow.camera;null!=t&&(this.applyDepthMaterial(),await this.renderer.compileAsync(e,t),this.unapplyDepthMaterial()),this.compileInProgress=!1,this.renderer.setRenderTarget(null)}applyDepthMaterial(){const e=this.gBufferCachedMaterials;e.clear(),this.scene.traverse(t=>{(t.isMesh||t.isPoints||t.isLine||t.isSprite)&&(this.initCustomDepthMaterial(t),e.set(t,t.material),t.castShadow?null!=t.customDepthMaterial?t.material=t.customDepthMaterial:t.material=ht:t.material=null)})}unapplyDepthMaterial(){this.gBufferCachedMaterials.forEach((e,t)=>{t.material=e})}renderScene(e){if(!this.running||this.paused)return;if(this.compileInProgress)return void console.error("Compile in progress, skipping render");this.applyGBufferMaterials(e);const t=this.scene.matrixWorldAutoUpdate,s=this.scene.matrixAutoUpdate,i=this.renderer.shadowMap.autoUpdate;e!==je.opaque&&(this.renderer.shadowMap.autoUpdate=!1,this.scene.matrixWorldAutoUpdate=!1,this.scene.matrixAutoUpdate=!1);try{this.renderer.render(this.scene,this.camera)}catch(e){console.warn("Render failed",e)}e===je.opaque&&this.gBufferCachedMaterials.forEach((e,t)=>{!Array.isArray(e)&&!Array.isArray(t.material)&&e instanceof d&&this.updateLightUniformValues(t.material,e)}),this.unapplyGBufferMaterials(),this.renderer.shadowMap.autoUpdate=i,this.scene.matrixWorldAutoUpdate=t,this.scene.matrixAutoUpdate=s}getEnvTexture(e){null==this.pmremGenerator&&(this.pmremGenerator=new i.PMREMGenerator(this.renderer),this.pmremGenerator.compileEquirectangularShader());let t=this.pmremGeneratorResults.get(e);return null==t&&(t=this.pmremGenerator.fromEquirectangular(e).texture,this.pmremGeneratorResults.set(e,t)),t.colorSpace=i.SRGBColorSpace,t}applyPostProcessSettings(){if(0==this.postProcessVolumes.length)return this.lutPass.enabled=!1,void(this.colorPass.enabled=!1);var e;(e=this.postProcessSettings).tonemapMapping=void 0,e.tonemapExposure=1,e.envIntensity=1,e.envTexture=void 0,e.vignetteIntensity=0,e.colorTint=new i.Color("white"),e.colorTintIntensity=0,e.depthFocus=void 0,e.depthAperture=void 0,e.depthMaxBlur=void 0,e.temperature=6500,e.temperatureTint=0,e.lut=void 0,e.lutIntensity=0;const t=this.postProcessSettings;let s,r=!1,a=!1,n=!1,o=!1;if(null==this.camera)return;const h=this.camera.getWorldPosition(Ke);let d=[];for(const e of this.postProcessVolumes){if(!$e(e.object))continue;let l=e.blendWeight??1;const u=e.distanceToPoint(h);u>e.blendRadius||(e.blendRadius>0&&(l*=Te(1-u/e.blendRadius,0,1)),l>1&&(l=1),l>0&&(d.push(e),void 0!==e.settings.tonemapMapping&&(t.tonemapMapping=e.settings.tonemapMapping),void 0!==e.settings.tonemapExposure&&(t.tonemapExposure=i.MathUtils.lerp(t.tonemapExposure,e.settings.tonemapExposure,l)),void 0!==e.settings.envTexture&&(t.envTexture=e.settings.envTexture),void 0!==e.settings.envIntensity&&(t.envIntensity=i.MathUtils.lerp(t.envIntensity,e.settings.envIntensity,l)),void 0!==e.settings.vignetteIntensity&&(t.vignetteIntensity=i.MathUtils.lerp(t.vignetteIntensity,e.settings.vignetteIntensity,l),a=!0),void 0!==e.settings.colorTint&&void 0!==e.settings.colorTintIntensity&&e.settings.colorTintIntensity>0&&(t.colorTint=t.colorTint.lerp(e.settings.colorTint,l),o=!0),void 0!==e.settings.colorTintIntensity&&(t.colorTintIntensity=i.MathUtils.lerp(t.colorTintIntensity,e.settings.colorTintIntensity,l)),void 0!==e.settings.depthFocus&&(r=!0,t.depthFocus=void 0!==t.depthFocus?i.MathUtils.lerp(t.depthFocus,e.settings.depthFocus,l):e.settings.depthFocus),void 0!==e.settings.depthAperture&&(r=!0,t.depthAperture=void 0!==t.depthAperture?i.MathUtils.lerp(t.depthAperture,e.settings.depthAperture,l):e.settings.depthAperture),void 0!==e.settings.depthMaxBlur&&(r=!0,t.depthMaxBlur=void 0!==t.depthMaxBlur?i.MathUtils.lerp(t.depthMaxBlur,e.settings.depthMaxBlur,l):e.settings.depthMaxBlur),void 0!==e.settings.temperature&&(t.temperature=i.MathUtils.lerp(t.temperature,e.settings.temperature,l)),void 0!==e.settings.temperatureTint&&(t.temperatureTint=i.MathUtils.lerp(t.temperatureTint,e.settings.temperatureTint,l)),void 0!==e.settings.lut&&(s=e.settings.lut,n=!0),void 0!==e.settings.lutIntensity&&(t.lutIntensity=i.MathUtils.lerp(t.lutIntensity,e.settings.lutIntensity,l),n=!0)))}this.renderer.toneMapping=t.tonemapMapping??i.NoToneMapping,this.renderer.toneMappingExposure=t.tonemapExposure,null!=t.envTexture&&(this.scene.environment=this.getEnvTexture(t.envTexture)),this.scene.environmentIntensity=t.envIntensity,this.colorPass.vignetteIntensity=t.vignetteIntensity,this.colorPass.vignetteEnabled=a,this.colorPass.colorTint=t.colorTint,this.colorPass.colorTintIntensity=t.colorTintIntensity,this.colorPass.enabled=a||o,r&&this.camera instanceof l?(this.dofPass.enabled=!0,void 0!==t.depthFocus&&(this.dofPass.uniforms.focus.value=t.depthFocus),void 0!==t.depthAperture&&(this.dofPass.uniforms.aperture.value=t.depthAperture),void 0!==t.depthMaxBlur&&(this.dofPass.uniforms.maxblur.value=t.depthMaxBlur)):this.dofPass.enabled=!1,this.colorPass.temperature=t.temperature,this.colorPass.temperatureTint=t.temperatureTint,this.lutPass.enabled=n,n&&(null!=s&&(s.flipY=!0,s.generateMipmaps=!1),this.lutPass.lut=s,this.lutPass.intensity=t.lutIntensity)}renderOverlay(){if(!this.running)return;if(0===this.overlayCameras.size)return;const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.previousClientWith/2,s=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let i=0;i<e.length;i++)this.renderer.clearDepth(),this.renderer.setViewport(t-s/2+this.insetWidth*i+this.insetMargin*i,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[i])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(e){if(!this.running)return;if(0===this.composer.renderTarget1.width||0===this.composer.renderTarget1.height)return;if(0===this.composer.renderTarget2.width||0===this.composer.renderTarget2.height)return;let t=!1;if(this.ssrPass.enabled&&!1!==this.options?.reflection?.enabled){const e=this.ssrPass.selects??[];e.length=0,this.scene.traverseVisible(t=>{t instanceof o&&!0===t.material.userData?.reflective&&isObjectInFrustum(t,Xe)&&e.push(t)}),this.ssrPass.selects=e,0==e.length&&(this.ssrPass.enabled=!1),t=!0}this.options.bloom,this.composer.render(e),this.scene.matrixWorldAutoUpdate=!0,this.scene.matrixAutoUpdate=!0,t&&(this.ssrPass.enabled=!0)}hasBloom(){return null!=Me(this.scene,e=>e instanceof o&&!0===e.material?.userData?.hasBloom)}darkenNonBloomed(e){if((e instanceof o||e instanceof i.Sprite||e instanceof i.Line)&&e.visible&&(null==e.material.userData||!0!==e.material.userData.hasBloom)){if(e.material?.id===Le.id)return;this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=Le:(e.visible=!1,this.bloomHidden.push(e))}else"TransformControlsPlane"!==e.type&&"TransformControlsGizmo"!==e.type||(e.visible=!1,this.bloomHidden.push(e))}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof d&&(e.uniforms[re].value=this.sceneColorRenderTarget.textures[1],this.camera instanceof l&&(null!=e.uniforms[ne]&&(e.uniforms[ne].value=this.camera.near),null!=e.uniforms[ae]&&(e.uniforms[ae].value=this.camera.far)))}initNormalUniform(e){e instanceof d&&null!=e.uniforms[le]&&(e.uniforms[le].value=this.gRenderTarget.textures[2])}initShadowUniform(e,t){var s;t instanceof A&&(t.uniforms.receiveShadow?(s=t.uniforms.receiveShadow).value||(s.value=e.receiveShadow):t.uniforms.receiveShadow={value:e.receiveShadow})}initResolutionUniform(e){e instanceof d&&null!=e.uniforms[oe]&&e.uniforms[oe].value.set(this.gRenderTarget.width,this.gRenderTarget.height)}initAoUniform(e){if(this.aoPass.enabled){e.uniforms[ce].value=this.aoPass.pdRenderTarget.texture,null==e.defines.USE_SSAO_MAP&&(e.defines.USE_SSAO_MAP="",e.needsUpdate=!0),e.defines.USE_SSAO_MAP="";const t=this.tbufferMaterialCache.get(e);null!=t&&this.initAoUniform(t)}else if(null!=e.defines.USE_SSAO_MAP){delete e.defines.USE_SSAO_MAP,e.needsUpdate=!0;const t=this.tbufferMaterialCache.get(e);null!=t&&this.initAoUniform(t)}}initCustomDepthMaterial(e){if(null!=e.customDepthMaterial||!e.castShadow)return;const t=e.material;if(t instanceof A&&!t.transparent&&t.depthWrite){let s=this._customDepthMaterialCache.get(t);if(null==s){const e=Ce(Re);let i;null!=t.alphaTest&&t.alphaTest>0&&null!=t.outputOpacity&&(i=t.outputOpacity.lt(t.alphaTest)),s=new A({color:e,discard:i}),this._customDepthMaterialCache.set(t,s)}e.customDepthMaterial=s}}};ze=e=t([ie(),s("design:paramtypes",[HTMLElement,Object])],ze);export{ze as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const He=.05;function $e(e){let t=e;for(;t;){if(!1===t.visible)return!1;t=t.parent}return!0}se.prototype.overrideVisibility=function(){const e=this.scene,t=this._visibilityCache;e.traverse(function(e){if(t.set(e,e.visible),(e.isPoints||e.isLine||e.isTransformControls||e.isSprite)&&(e.visible=!1),null!=e.material){let t=!1,s=!1;if(Array.isArray(e.material)){for(const s of e.material)if(null!=s.alphaTest&&s.alphaTest>0){t=!0;break}}else null!=e.material.alphaTest&&e.material.alphaTest>0?t=!0:!0===e.material.userData.isDecal&&(s=!0);s&&(e.visible=!1)}})};const Xe=new i.Frustum,Ye=new i.Box3,Qe=new i.Matrix4;export function isObjectInFrustum(e,t){const s=Ye.setFromObject(e);return t.intersectsBox(s)}const Ke=new i.Vector3;const Je=new n,Ze=new p;function et(e,t,s=new i.Matrix3){return Ze.copy(e),Ze.x*=-1,Ze.y*=-1,Ze.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(Ze.y*=-1,Ze.z*=-1),s.setFromMatrix4(Je.makeRotationFromEuler(Ze))}const tt=new A({outputs:[q(0,0,0,0),q(0,0,0,0),L(E("white"),Oe(4))],transparent:!0}),st=new i.MeshBasicMaterial({color:"blue",transparent:!0,opacity:.5});tt.depthWrite=!1;new o(new i.BoxGeometry(4,4,4),st);function it(e){return e instanceof i.Sprite||e.isPoints||e.isLine||e.isLineSegments2||e.isTransformControls||e.isTransformControlsGizmo||e instanceof o&&rt(e,e.material)}function rt(e,t){return null==t||(Array.isArray(t)?t.some(t=>rt(e,t)):t instanceof i.RawShaderMaterial||t instanceof i.ShaderMaterial&&!(t instanceof A))}class at extends Ie{constructor(e,t,s){super(),this.scene=e,this.camera=t,this.gRenderTarget=s,this.cachedVisibility=[],this.needsSwap=!1}render(e,t,s,i,r){const a=e.autoClear;e.autoClear=!1;const n=this.scene.matrixWorldAutoUpdate,l=this.scene.matrixAutoUpdate,h=e.shadowMap.autoUpdate;this.scene.matrixAutoUpdate=!1,e.shadowMap.autoUpdate=!1;const d=s.depthTexture;s.depthTexture=this.gRenderTarget.depthTexture,e.setRenderTarget(s),this.cachedVisibility.length=0;let u=0;this.scene.traverseVisible(e=>{const t=it(e);e instanceof o&&!t?(this.cachedVisibility.push(e),e.visible=!1):t&&u++}),u>0&&e.render(this.scene,this.camera),this.cachedVisibility.forEach((e,t)=>{e.visible=!0}),e.setRenderTarget(null),e.autoClear=a,s.depthTexture=d,this.scene.matrixWorldAutoUpdate=n,this.scene.matrixAutoUpdate=l,e.shadowMap.autoUpdate=h}}class nt extends Ie{constructor(e){super(),this.fn=e}render(e,t,s,i,r){this.fn(e,t,s,i,r)}}const ot=["ambientLightColor","cameraNear","directionalLightShadows","directionalLights","directionalShadowMap","directionalShadowMatrix","fogColor","fogDensity","fogFar","fogNear","hemisphereLights","lightProbe","ltc_1","ltc_2","pointLightShadows","pointLights","pointShadowMap","pointShadowMatrix","rectAreaLights","shadowFar","spotLightMap","spotLightMatrix","spotLightShadows","spotLights","spotShadowMap"],lt=B("fogColor");export class FogNode extends ${constructor(e,t=lt){super(),this.source=e,this.fogColor=t}compile(e){const t=e.variable(),s=e.get(this.source.rgb),i=e.get(this.source.a),r=e.get(this.fogColor),a=e.get(F("fogFar")),n=e.get(F("fogNear")),o=e.get(F("fogDensity")),l=e.get(G(j.mvPosition.z));return{pars:"\n ",chunk:`\n #ifdef FOG_EXP2\n float fogFactor_${t} = 1.0 - exp( - ${o} * ${o} * ${l} * ${l} );\n #else\n float fogFactor_${t} = smoothstep( ${n}, ${a}, ${l} );\n #endif\n vec4 color_vec4_${t} = vec4(mix(${s}, ${r}, fogFactor_${t}), ${i});\n `,out:`color_vec4_${t}`}}}const ht=new i.MeshDepthMaterial({depthPacking:i.RGBADepthPacking});/*
1
+ var e;import{__decorate as t,__metadata as s}from"tslib";import*as i from"three";import{Color as a,Material as r,Matrix4 as n,Mesh as o,PerspectiveCamera as l,ShaderChunk as h,ShaderMaterial as u,WebGLRenderTarget as d,Texture as c,Euler as p,MeshStandardMaterial as m}from"three";import{CopyShader as f,EffectComposer as g,FXAAShader as M,GammaCorrectionShader as v,LUTPass as T,RenderPass as y,ShaderPass as b,VRButton as x}from"three-stdlib";import{CSMShader as w,CSMUtil as P}from"./csm.js";import{bool as S,colorToNormal as R,float as C,NodeShaderMaterial as A,standardMaterial as U,uniformFloat as F,uniformVec3 as B,toonMaterial as O,lambertMaterial as I,normalize as D,rgb as E,rgba as L,transformed as W,varying as j,varyingAttributes as _,varyingTransformed as G,vec4 as V,BooleanExpression as q,select as k,ifDefApply as N,uniformSampler2d as z,RgbaNode as H,mix as $,attributes as X}from"three-shader-graph";import{Reflector as Y}from"three-stdlib";import{BokehPass as Q,OutputPass as K}from"three/examples/jsm/Addons.js";import{CSM as J}from"three/examples/jsm/csm/CSM.js";import{RectAreaLightUniformsLib as Z}from"three/examples/jsm/lights/RectAreaLightUniformsLib.js";import ee from"three/examples/jsm/libs/stats.module.js";import{GTAOPass as te}from"three/examples/jsm/postprocessing/GTAOPass.js";import{Service as se}from"typedi";import{depthUniformName as ie,farUniformName as ae,nearUniformName as re,resolutionUniformName as ne,sceneNormalUniformName as oe,screenUV as le,supportsDepthTextureExtension as he}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as ue}from"./shader-nodes/time.js";import{aoMapUniformName as de,sceneMapUniformName as ce}from"./shader-nodes/scene-sample.js";import{DepthPass as pe}from"./utils/three/depth-pass.js";import{GPUStatsPanel as me}from"./utils/three/gpu-stats-panel.js";import{OutlinePass as fe}from"./utils/three/outline-pass.js";import{findFirstVisibleObject as ge,traverseVisibleStop as Me}from"./utils/three/traverse.js";import{clamp as ve}from"./utils/math.js";import{ColorPass as Te}from"./rendering/color-pass.js";import{SSRPass as ye}from"./rendering/ssr/SSRPass.js";import{SSRShader as be}from"./rendering/ssr/SSRShader.js";import{VolumetricFogPass as xe}from"./rendering/fog/volumetric-fog-pass.js";import{OutlineEffect as we}from"./rendering/outline-effect.js";import{UnrealBloomPass as Pe}from"./rendering/bloom/UnrealBloomPass.js";import{highPrecisionEyeDepth as Se}from"./shader-nodes/depth.js";import{packDepthToRGBA as Re}from"three-shader-graph";import{FogVolumeObject as Ce}from"./rendering/fog/fog-volume-object";import{ParallaxStandardMaterial as Ae}from"./shader/builtin/standard-shader.js";import{parallaxOcclusionMapping as Ue}from"./shader-nodes/pom.js";import{FullScreenQuad as Fe}from"three-stdlib";import{edgeDepthEffect as Be}from"./shader-nodes/effects";import{decalDiscard as Oe}from"./shader-nodes/decal.js";import{Pass as Ie}from"three/examples/jsm/Addons.js";P.patchSetupMaterial();const De=document.createElement("div");De.style.position="absolute",De.style.left="50%",De.style.top="50%",De.style.color="black",De.style.zIndex="999";(new i.Layers).set(9);const Ee=new i.MeshBasicMaterial({color:"black"}),Le=new i.MeshDepthMaterial;var We;Le.depthPacking=i.RGBADepthPacking,Le.blending=i.NoBlending,Le.side=i.DoubleSide,function(e){e[e.opaque=0]="opaque",e[e.transparent=1]="transparent"}(We||(We={}));const je=(()=>{const e=new Uint8Array([255,255,255,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),_e=(()=>{const e=new Uint8Array([0,0,0,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),Ge=(()=>{const e=new Uint8Array([128,128,255,255]),t=new i.DataTexture(e,1,1,i.RGBAFormat);return t.needsUpdate=!0,t})(),Ve=new A({color:C(0),position:V(C(0))});Ve.visible=!1;const qe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let ke=0,Ne=null;const ze=new Map;function He(){return null==Ne&&(Ne=new IntersectionObserver(e=>{for(const t of e)if(t.isIntersecting){const e=ze.get(t.target);e&&e()}},{threshold:0})),Ne}let $e=e=class{setPaused(e){this.paused=e}resizeRender(){if(!this.running)return;const e=this.container.clientWidth,t=this.container.clientHeight;this.previousClientWith===e&&this.previousClientHeight===t||0!==e&&0!==t&&(this.previousClientWith=e,this.previousClientHeight=t,this.camera instanceof l&&(this.camera.aspect=e/t,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,window.devicePixelRatio)*this.resolutionScale),this.renderer.setSize(e,t),this.composer.setSize(e,t),this.dofPass.setSize(e*this.renderer.getPixelRatio(),t*this.renderer.getPixelRatio()),this.fxaaPass.setSize(e*this.renderer.getPixelRatio(),t*this.renderer.getPixelRatio()),this.fxaaPass.uniforms.resolution.value.set(1/(e*this.renderer.getPixelRatio()),1/(t*this.renderer.getPixelRatio())),this.createGRenderTarget(),this.phasedRenderPass.gRenderTarget=this.gRenderTarget,this.bloomPass.emissiveTexture=this.gRenderTarget.textures[1],this.ssrPass.setSize(this.gRenderTarget.width,this.gRenderTarget.height),this.ssrPass.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),this.aoPass.setSize(this.gRenderTarget.width,this.gRenderTarget.height),this.aoPass.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),this.sceneColorRenderTarget.dispose(),this.sceneColorRenderTarget=this.createSceneColorRenderTarget(this.renderer,this.container),this.copyPass.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[0],this.copyPass.material.uniformsNeedUpdate=!0)}addPostProcessVolume(e){if(0===this.postProcessVolumes.length)this.postProcessVolumes.push(e);else{let t=!1;for(let s=0;s<this.postProcessVolumes.length;s++)if(e.priority<this.postProcessVolumes[s].priority){this.postProcessVolumes.splice(s,0,e),t=!0;break}t||this.postProcessVolumes.push(e)}}removePostProcessVolume(e){const t=this.postProcessVolumes.indexOf(e);t>-1&&this.postProcessVolumes.splice(t,1)}constructor(t,s={}){this.container=t,this.options=s,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.postProcessVolumes=[],this.postProcessSettings={},this.csmUpdateInvervals=this.options.shadows?.cascadeUpdateIntervals,this._id=ke++,this.fquadCopy=new Fe(new u(f)),this.fquadCopyOpaque=new Fe(new A({outputs:[z("tSceneColor",new c).sample(_.uv),V(z("tDepthTexture",new i.DepthTexture(1,1)).sample(_.uv).r)]})),this.fquadBlendAO=(()=>{const e=V(1),t=new A({outputs:[z("tAO",new c).sample(le),e,e],transparent:!0});t.depthWrite=!1,t.depthTest=!1,t.blending=i.MultiplyBlending;return new Fe(t)})(),this.resolutionScale=1,this.maxPixelRatio=qe?1:window.devicePixelRatio,this.onResize=()=>{if(this.resizeRender(),!this.paused)try{this.render()}catch(e){}},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!0,this.onLoopCallbacks=[],this.stats=new ee,this._showStats=!0,this.gbufferMaterialCache=new Map,this.tbufferMaterialCache=new Map,this.gBufferCachedMaterials=new Map,this.gBufferCachedVisibility=[],this._initiatedMaterialTextures=new Set,this._initiatedTextures=new Set,this.compileInProgress=!1,this.pmremGeneratorResults=new WeakMap,this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,this.prevClearColor=new a,this.hadBloom=!1,this.bloomStoredMaterials={},this.bloomHidden=[],this._customDepthMaterialCache=new WeakMap,null!=s.maxPixelRatio&&(this.maxPixelRatio=s.maxPixelRatio),this.resolutionScale=s.resolutionScale??1,Z.init(),window.renderer=this.renderer=window.renderer??new i.WebGLRenderer({antialias:!1,powerPreference:"high-performance"});new i.MeshStandardMaterial({color:"#ccc"});this.scene=new i.Scene,this.scene.matrixWorldAutoUpdate=!0,this.scene.updateMatrixWorld=function(e){const t=this.children;for(let s=0,i=t.length;s<i;s++){t[s].updateMatrixWorld(e)}}.bind(this.scene),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,window.devicePixelRatio)*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(x.createButton(this.renderer));const r=new we(this.renderer,{defaultThickness:.005,defaultColor:[0,0,0],defaultAlpha:1,defaultKeepAlive:!0});this.outlineEffect=r,this.createGRenderTarget(),this.composer=new g(this.renderer),this.composer.setSize(t.clientWidth,t.clientHeight);var n=(t.clientWidth||1)/(t.clientHeight||1);const o=new i.PerspectiveCamera(45,n,.5,800);o.layers.enable(19),this.setCamera(o),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=i.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=s.shadows?.autoUpdate??!1,this.renderer.outputColorSpace=i.SRGBColorSpace,this.renderer.toneMapping=i.NoToneMapping,this.renderer.toneMappingExposure=1,this.renderer.gammaFactor=1.4,P.renderingView=this,this.isDepthTextureExtensionSupported=he(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.aoMaskDepthRenderTarget=e.createAOMaskDepthRenderTarget(this.renderer,this.container),this.sceneColorRenderTarget=this.createSceneColorRenderTarget(this.renderer,this.container);const l=new i.Vector2(t.clientWidth,t.clientHeight),h=(new y(this.scene,this.camera),new b(f,"prevtexture"));h.enabled=!0,h.needsSwap=!0,h.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[0],this.copyPass=h;const d=new Pe(l,1.5,.4,.85);d.threshold=1,d.strength=.9,d.radius=.5,this.bloomPass=d;const p=new te(this.scene,this.camera,this.gRenderTarget.width,this.gRenderTarget.height,{});p.normalRenderTarget?.dispose(),p.setGBuffer(this.gRenderTarget.depthTexture,this.gRenderTarget.textures[2]),p.output=te.OUTPUT.Off,p.enabled=!1,this.aoPass=p,this.fquadBlendAO.material.uniforms.tAO.value=p.pdRenderTarget.texture,be.fragmentShader=be.fragmentShader.replace("if(metalness==0.) return;","if(metalness<0.1) return;");const m=new ye({renderer:this.renderer,scene:this.scene,camera:this.camera,width:this.gRenderTarget.width,height:this.gRenderTarget.height,groundReflector:null,selects:[],normalTexture:this.gRenderTarget.textures[2],depthTexture:this.gRenderTarget.depthTexture});m.output=ye.OUTPUT.Default,m.blur=!0,m.fresnel=!1,m.distanceAttenuation=!0,m.maxDistance=50,m.selective=!0,m.bouncing=!1,m.opacity=.4,m.enabled=!1!==this.options?.reflection?.enabled,this.ssrPass=m,!1!==this.options.ao?.enabled&&this.composer.addPass(p);const w=new lt((e,t,s,i,a)=>{this.aoPass.enabled&&(this.initResolutionUniform(this.fquadBlendAO.material),this.renderer.setRenderTarget(this.gRenderTarget),this.fquadBlendAO.render(this.renderer),this.renderer.setRenderTarget(null))});this.composer.addPass(w);const S=new lt((e,t,s,i,a)=>{this.renderer.setRenderTarget(this.gRenderTarget),this.renderScene(We.transparent),this.renderer.setRenderTarget(null)});this.composer.addPass(S),this.composer.addPass(h),this.composer.addPass(m),this.phasedRenderPass=new ot(this.scene,this.camera,this.gRenderTarget),this.composer.addPass(this.phasedRenderPass),this.composer.addPass(d),d.emissiveTexture=this.gRenderTarget.textures[1],this.renderer.info.autoReset=!1,this.volumetricFogPass=new xe(l),this.composer.addPass(this.volumetricFogPass),this.volumetricFogPass.enabled=!0,this.dofPass=new Q(this.scene,this.camera,{focus:1,aperture:.025,maxblur:.01}),this.dofPass.enabled=!1,this.composer.addPass(this.dofPass);const R=new Te;this.composer.addPass(R),this.colorPass=R,R.vignetteEnabled=!1,this.outlinePass=new fe(new i.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.outlinePass.enabled=!1,this.composer.addPass(this.outlinePass);const C=new b(M);C.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(C),this.fxaaPass=C,this.fxaaPass.enabled=!1,!0===s.enableOutlines&&this.setEnableOutlines(!0),new b(v).clear=!1,this.fixStatsStyle(),this.lutPass=new T({}),this.lutPass.enabled=!1,this.composer.addPass(this.lutPass);const U=new b(f,"prevtexture");U.enabled=!0,U.needsSwap=!1,U.material.uniforms.tDiffuse.value=this.gRenderTarget.textures[1],U.renderToScreen=!0;const F=new K;this.composer.addPass(F)}fixStatsStyle(){const e=this.stats.dom;e.style.position="absolute";const t=e.getElementsByTagName("canvas");for(let e=0;e<t.length;e++)t.item(e).style.display="inline-block"}setEnableOutlines(e){this.outlinePass.enabled=e,this.fxaaPass.enabled=e}setCamera(e){if(this.camera=e,this.composer.passes.forEach(t=>{t instanceof y?t.camera=e:t instanceof fe?t.renderCamera=e:(t instanceof pe||t instanceof te)&&(t.camera=e)}),this.ssrPass&&(this.ssrPass.camera=e),this.aoPass&&(this.aoPass.camera=e),this.phasedRenderPass&&(this.phasedRenderPass.camera=e),null==this.csm){if(this.csm=new J({maxFar:100,lightFar:250,lightMargin:20,cascades:qe?2:4,shadowMapSize:2048*(qe?.5:1),lightDirection:new i.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5*Math.PI,camera:this.camera,parent:this.scene,mode:"practical"}),null!=this.csmUpdateInvervals){this.csmCascadeLastUpdate=new Array(this.csm.lights.length).fill(0);for(const e of this.csm.lights)e.shadow.autoUpdate=!1}this.csm&&Array.isArray(this.csm.lights),this.csm.fade=!0,h.lights_fragment_begin=w.lights_fragment_begin}else this.csm.camera=this.camera,this.camera;this.csm.updateFrustums()}setSelectedObjects(e){if(null==this.outlinePass)return;const t=new Map;for(const s of e)t.set(s.uuid,s);for(const s of e)s.traverse(e=>{e.uuid!==s.uuid&&t.has(e.uuid)&&t.delete(e.uuid)});this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(e,t,s){const a=Math.max(1,Math.floor(t.clientWidth*s)),r=Math.max(1,Math.floor(t.clientHeight*s)),n=new i.WebGLRenderTarget(a,r);return n.texture.minFilter=i.NearestFilter,n.texture.magFilter=i.NearestFilter,n.texture.generateMipmaps=!1,n.stencilBuffer=!1,n.depthTexture=new i.DepthTexture(a,r),n.depthTexture.type=i.UnsignedShortType,n.depthTexture.minFilter=i.NearestFilter,n.depthTexture.magFilter=i.NearestFilter,n}static createAOMaskDepthRenderTarget(e,t){const s=Math.max(1,t.clientWidth*e.getPixelRatio()),a=Math.max(1,t.clientHeight*e.getPixelRatio()),r=new i.DepthTexture(s,a);r.type=i.UnsignedInt248Type,r.minFilter=i.NearestFilter,r.magFilter=i.NearestFilter;const n=new i.WebGLRenderTarget(s,a,{type:i.HalfFloatType,depthTexture:r});return n.texture.minFilter=i.NearestFilter,n.texture.magFilter=i.NearestFilter,n.texture.generateMipmaps=!1,n.stencilBuffer=!1,n}createSceneColorRenderTarget(e,t){const s=this.gRenderTarget.width,a=this.gRenderTarget.height,r=new i.WebGLRenderTarget(s,a,{count:2,type:i.FloatType,format:i.RGBAFormat,colorSpace:i.SRGBColorSpace,depthBuffer:!1,stencilBuffer:!1});return r.texture.minFilter=i.LinearFilter,r.texture.magFilter=i.LinearFilter,r.texture.generateMipmaps=!1,r.textures[1].minFilter=i.NearestFilter,r.textures[1].magFilter=i.NearestFilter,r}createGRenderTarget(){const e=this.container;null!=this.gRenderTarget&&this.gRenderTarget.dispose();const t=Math.max(1,e.clientWidth*this.renderer.getPixelRatio()),s=Math.max(1,e.clientHeight*this.renderer.getPixelRatio()),a=new i.DepthTexture(t,s);a.type=i.UnsignedIntType,a.minFilter=i.NearestFilter,a.magFilter=i.NearestFilter,this.gRenderTarget=new d(t,s,{count:3,minFilter:i.NearestFilter,magFilter:i.NearestFilter,type:i.HalfFloatType,format:i.RGBAFormat,depthTexture:a}),this.gRenderTarget.texture.generateMipmaps=!1,this.gRenderTarget.stencilBuffer=!1}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.gRenderTarget.dispose(),this.aoMaskDepthRenderTarget.dispose(),this.sceneColorRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren();He().unobserve(this.container),ze.delete(this.container),this.volumetricFogPass.dispose(),P.clearSceneCache(this.scene)}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);t>=0&&this.onLoopCallbacks.splice(t,1)}set showStats(e){this._showStats=e,this._showStats&&!this.container.contains(this.stats.dom)?this.container.appendChild(this.stats.dom):!this._showStats&&this.container.contains(this.stats.dom)&&this.container.removeChild(this.stats.dom)}get showStats(){return this._showStats}applyEnvMap(e){if(null!=this.scene.environment&&(e instanceof A&&(null==e.envMap||e.userData.useSceneEnv)&&(e.userData.useSceneEnv=!0,null==e.uniforms.envMap&&(e.uniforms.envMap={value:this.scene.environment},e.uniformsNeedUpdate=!0,e.uniforms.envMapRotation={value:st(this.scene.environmentRotation,this.scene.environment,new i.Matrix3)}),null==e.uniforms.envMapIntensity&&(e.uniforms.envMapIntensity={value:1},e.uniformsNeedUpdate=!0),e.uniforms.envMap.value=this.scene.environment,e.uniforms.envMapIntensity.value=this.scene.environmentIntensity,e.envMap=this.scene.environment),e instanceof A||e instanceof i.MeshStandardMaterial)){const t=this.gbufferMaterialCache.get(e);null==t||this.gbufferMaterialCache.has(t)||this.applyEnvMap(t)}}setupCsm(e){if(e instanceof i.Mesh||e instanceof i.SkinnedMesh)if(e.material instanceof Array)for(const t of e.material)this.csm.setupMaterial(t);else this.csm.setupMaterial(e.material)}updateMaterialProperties(e,t){(e instanceof i.MeshBasicMaterial||e instanceof m||e instanceof i.MeshLambertMaterial||e instanceof i.MeshPhongMaterial)&&(t.uniforms.color.value.setFromColor(e.color),t.uniforms.opacity.value=e.opacity,t.uniforms.map.value=e.map,null!=t.uniforms.alphaMap&&(t.uniforms.alphaMap.value=e.alphaMap),null!=t.uniforms.lightMap&&(t.uniforms.lightMap.value=e.lightMap,t.uniforms.lightMapIntensity.value=e.lightMapIntensity),null!=t.uniforms.aoMap&&(t.uniforms.aoMap.value=e.aoMap,t.uniforms.aoMapIntensity.value=e.aoMapIntensity),null!=t.uniforms.alphaTest&&(t.uniforms.alphaTest.value=e.alphaTest)),(e instanceof m||e instanceof i.MeshLambertMaterial||e instanceof i.MeshPhongMaterial)&&(t.uniforms.normalMap&&(t.uniforms.normalMap.value=e.normalMap,t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.emissiveMap&&(t.uniforms.emissiveMap.value=e.emissiveMap,t.uniforms.emissive.value.setFromColor(e.emissive),t.uniforms.emissiveIntensity.value=e.emissiveIntensity)),e instanceof m&&(t.uniforms.roughnessMap.value=e.roughnessMap,t.uniforms.metalnessMap.value=e.metalnessMap,t.uniforms.roughness.value=e.roughness,t.uniforms.metalness.value=e.metalness),e instanceof Ae&&(t.uniforms.heightMap.value=e.heightMap,t.uniforms.heightScale.value=e.heightScale),this.updateMaterialCommonProperties(e,t)}updateUniformValues(e,t){const s=e.uniforms,i=t.uniforms;for(const e in s){const t=i[e],a=s[e].value;null!=t&&t.value!==a&&"receiveShadow"!==e&&!1===ht.includes(e)&&(t.value=a)}this.updateMaterialCommonProperties(e,t)}updateMaterialCommonProperties(e,t){t.alphaTest=e.alphaTest,t.side=e.side,t.depthWrite=e.depthWrite,t.depthTest=e.depthTest,t.blending=e.blending,t.colorWrite=e.colorWrite,t.premultipliedAlpha=e.premultipliedAlpha}updateLightUniformValues(e,t){const s=e.uniforms,i=t.uniforms;for(const e of ht){const t=i[e],a=s[e];null!=a&&null!=t&&(t.value=a.value)}}createGBufferMaterial(e,t){const s=t===We.opaque?this.gbufferMaterialCache:this.tbufferMaterialCache;let a=s.get(e);if(!0===e.userData.isGBufferMaterial)return e;if(null==a){let n=_.uv;if(e instanceof Ae&&null!=e.heightMap){const t=F("heightScale",e.heightScale??1);n=Ue(n,z("heightMap",e.heightMap),t)}let o=G.normal;if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){const t=e.normalMap??Ge,s=F("useNormalMap",null!=e.normalMap?1:0),i=F("normalScale",e.normalScale?.x??1),a=R(z("normalMap",t).sample(n),i);o=$(G.normal,a,s)}else e instanceof A&&null!=e.outputNormal&&(o=e.outputNormal);!0!==e.userData.disableAO&&(o=N("DOUBLE_SIDED",o,e=>k(new q("gl_FrontFacing"),e,e.multiplyScalar(-1))));let l=e.userData?.reflective?C(0):C(1);if(e instanceof i.MeshStandardMaterial){const t=F("roughness",e.roughness??1),s=e.roughnessMap??je,i=F("useRoughnessMap",null!=e.roughnessMap?1:0),a=z("roughnessMap",s).sample(n).g.multiply(t);l=$(t,a,i)}else e instanceof A&&null!=e.outputRoughness&&(l=e.outputRoughness);let h=null;if((e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial||e instanceof i.MeshBasicMaterial)&&null!=e.lightMap){const t=e.lightMap,s=F("useLightMap",null!=e.lightMap?1:0),i=F("lightMapIntensity",e.lightMapIntensity??1),a=z("lightMap",t).sample(n).rgb.multiplyScalar(i);h=$(E(0),a,s)}let d=C(0);if(e instanceof i.MeshStandardMaterial){const t=F("metalness",e.metalness??0),s=e.metalnessMap??_e,i=F("useMetalnessMap",null!=e.metalnessMap?1:0),a=z("metalnessMap",s).sample(n).b.multiply(t);d=$(t,a,i)}else e instanceof A&&e.outputRoughness;let c=null,p=C(1);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial||e instanceof i.MeshBasicMaterial){const t=e.aoMap??je,s=F("useAoMap",null!=e.aoMap?1:0);p=F("aoMapIntensity",e.aoMapIntensity??1);const i=z("aoMap",t).sample(n).r;c=$(C(1),i,s)}else e instanceof A&&e.outputRoughness;const f=F("opacity",e.opacity??1);let g=C(1);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshBasicMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){if(null!=e.alphaMap){const t=e.alphaMap;g=z("alphaMap",t).sample(n).r}g=g.multiply(f)}else e instanceof A&&null!=e.outputOpacity&&(g=e.outputOpacity);let M=L(0,1);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial||e instanceof i.MeshBasicMaterial){let t=B("color",(new i.Vector3).setFromColor(e.color));const s=e.map??je,a=F("useAlbedoMap",null!=e.map?1:0),r=z("map",s).sample(n),o=r.multiply(L(t,1)),l=L(t,1);M=$(l,o,a),e.vertexColors&&(M=M.multiply(V(j(X.color.rgb),1)));const h=$(C(1),r.w,a);g=g.multiply(h)}const v=!0===e.userData.hasBloom;let T=E(0);if(e instanceof i.MeshStandardMaterial||e instanceof i.MeshLambertMaterial||e instanceof i.MeshToonMaterial||e instanceof i.MeshPhongMaterial){const t=B("emissive",(new i.Vector3).setFromColor(e.emissive)),s=F("emissiveIntensity",e.emissiveIntensity),a=e.emissiveMap??_e,r=F("useEmissiveMap",null!=e.emissiveMap?1:0),o=z("emissiveMap",a).sample(n).rgb.multiply(t);T=$(t,o,r),T=T.multiplyScalar(s)}else e instanceof A&&null!=e.outputEmissive&&(T=e.outputEmissive);const y=e instanceof u&&null!=e.uniforms[ie],b=e instanceof u&&null!=e.uniforms[ce],x=e instanceof u&&null!=e.uniforms[de],w=e.transparent&&e.alphaTest<=.01||e.blending===i.AdditiveBlending,P=F("alphaTest",e.alphaTest);let W,H=e.alphaTest>0?g.lt(P):w&&t===We.opaque?g.lt(.8):S(!1);!0===e.userData.isDecal&&(H=H.or(Oe)),W=w?V(0,0,0,0):(r=o,D(r).multiplyScalar(.5).addScalar(.5)).rgba(e.userData?.reflective?l:1);const Y=e instanceof A?e.outputPosition:void 0,Q=e instanceof A?e.outputTransform:void 0;let K,J=L("black",1);if(e instanceof A&&null!=e.outputColor)J=e.outputColor;else if(e instanceof i.MeshStandardMaterial)J=U({color:M,metalness:d,roughness:l,emissive:T.rgb,normal:o,ambientOcclusion:c,ambientOcclusionIntensity:p,bakedLight:h});else if(e instanceof i.MeshLambertMaterial||e instanceof i.MeshPhongMaterial)J=I({color:M.rgb,ambientOcclusion:c,ambientOcclusionIntensity:p});else if(e instanceof i.MeshBasicMaterial){let e=M.rgb,t=h??E("black");null!=c&&(t=t.multiplyScalar(c.subtract(1).multiply(p).add(1))),e=e.add(t),J=e.rgba(g)}else e instanceof i.MeshToonMaterial&&(J=O({color:M,emissive:T.rgb,normal:o,ambientOcclusion:c,ambientOcclusionIntensity:p,bakedLight:h}));(e instanceof A||e instanceof i.MeshStandardMaterial)&&(K=e.envMap);let Z=!0;(e instanceof m||e instanceof i.MeshBasicMaterial||e instanceof i.ShaderMaterial)&&(Z=e.fog);let ee=L(J.rgb,g);Z&&(ee=new FogNode(ee));let te=!0;if(t===We.opaque?(te&&(te=!y&&!b&&!x),te&&(te=!w)):t===We.transparent&&te&&(te=w||y||b||x),!te)return a=Ve,s.set(e,a),a;a=new A({transform:Q,position:null==Q?Y:void 0,outputs:[ee,T.rgba(t===We.opaque?P:v?1:0),W],opacity:g,outputEncoding:!1,fog:Z,transparent:e.transparent,lights:!0,envMap:K,discard:H}),e instanceof i.MeshStandardMaterial&&null!=e.envMap&&null!=a.uniforms.envMapIntensity&&(a.uniforms.envMapIntensity.value=e.envMapIntensity),(e instanceof A||e instanceof i.MeshStandardMaterial)&&this.applyEnvMap(a),e instanceof A&&(Object.assign(a.defines,e.defines),null!=a.uniforms[de]&&(a.uniforms[de].value=this.aoPass.pdRenderTarget.texture,a.defines.USE_SSAO_MAP="")),a.userData.mrtOutputs=3,a.forceSinglePass=e.forceSinglePass,a.side=e.side,a.blending=e.blending,w?(a.depthWrite=!e.transparent,a.depthTest=e.depthTest,a.colorWrite=t===We.transparent):(a.depthWrite=e.depthWrite,a.depthTest=e.depthTest),a.visible=e.visible,a.alphaTest=e.alphaTest,a.alphaHash=e.alphaHash,a.vertexColors=e.vertexColors,a.premultipliedAlpha=e.premultipliedAlpha,a.toneMapped=e.toneMapped,a.blendAlpha=e.blendAlpha,a.blendColor=e.blendColor,a.polygonOffset=e.polygonOffset,a.polygonOffsetFactor=e.polygonOffsetFactor,a.polygonOffsetUnits=e.polygonOffsetUnits,a.blending=e.blending,a.userData.isGBufferMaterial=!0,a.visible=te,Object.assign(a.userData,e.userData),a.visible&&(this.csm.setupMaterial(a),e instanceof u&&Object.assign(a.uniforms,e.uniforms)),s.set(e,a)}var r;return a.visible&&(e instanceof u?this.updateUniformValues(e,a):this.updateMaterialProperties(e,a)),a}updateCsm(){const e=this.csmUpdateInvervals;if(this.renderer.shadowMap.autoUpdate&&null!=this.csmCascadeLastUpdate&&Array.isArray(e)){const t=performance.now();for(let s=0;s<this.csm.lights.length;++s){const i=e[s]??e[e.length-1]??16;if(t-this.csmCascadeLastUpdate[s]>=i&&this.csm.lights[s].shadow){this.csm.lights[s].shadow.needsUpdate=!0,this.csmCascadeLastUpdate[s]=t;break}}}this.csm.update()}loop(e,t=!1){const s=this.stats,a=s.addPanel(new ee.Panel("Calls","#83f","#002")),r=s.addPanel(new ee.Panel("Triangles","#c32","#002"));let l;navigator.userAgent.includes("Chrome")&&navigator.userAgent.includes("HologyEngine")&&(l=new me(this.renderer.getContext()),s.addPanel(l)),this.showStats=t;let h=10,u=1e3;const d=()=>{const e=this.renderer.info.render.calls;e>h&&(h=e,setTimeout(()=>h=10,5e3)),a.update(e,h);const t=this.renderer.info.render.triangles;t>u&&(u=t,setTimeout(()=>u=1e3,5e3)),r.update(t,u)};performance.now();i.Ray.prototype.intersectTriangle;this.resizeRender();const c=[],p=[],m=[];let f=0;const g=new n,M=new n;let v=0;let T=this.paused,y=!1,b=0;const x=He();ze.set(this.container,()=>{y&&(y=!1,requestAnimationFrame(()=>w(b)))}),x.observe(this.container);const w=t=>{y=!1;const a=this.renderer.getContext();if(this.paused&&this.running&&a.drawingBufferHeight>1)return y=!0,b=t,setTimeout(()=>{y&&w(t)},500),void(T=!0);if(this.renderer.clear(),this.applyPostProcessSettings(),this.renderer.autoClear=!1,this.renderer.clear(),null===this.container.offsetParent)return y=!0,b=t,void setTimeout(()=>{y&&w(t)},500);this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),s.begin(),this.showStats&&l?.startQuery(),this.ssrPass.gpuPanel=l;let r=(t*=.001)-f;if(f=t,T&&(r=.016,T=!1),g.copy(this.camera.matrixWorld),r>1){let t=r;for(;t>.05;)e(Xe),t-=Xe;e(t)}else e(r);this.onLoopCallbacks.forEach(e=>e(r)),this.camera?.updateMatrixWorld(),M.copy(this.camera.matrixWorld),t-v>.08&&!M.equals(g)&&(this.renderer.shadowMap.needsUpdate=!0,v=t),this.updateCsm();let n=!1;c.length=0,p.length=0,m.length=0;const h=Qe;Je.multiplyMatrices(this.camera.projectionMatrix,this.camera.matrixWorldInverse),h.setFromProjectionMatrix(Je);let u=!1,x=!1,P=!1;this.scene.traverseVisible(e=>{if(this.setupCsm(e),this.outlineEffect.apply(e),e instanceof Ce&&(u=!0),e instanceof o&&this.initCustomDepthMaterial(e),(e instanceof o||e instanceof i.Sprite)&&(this.initResolutionUniform(e.material),this.initNormalUniform(e.material),this.initShadowUniform(e,e.material),null!=this.scene.environment&&function(e,t){if(Array.isArray(e.material))for(const s of e.material)t(s);else null!=e.material&&t(e.material)}(e,e=>this.applyEnvMap(e)),!0===e.material?.userData?.hasBloom&&(n=!0)),(e instanceof o||e instanceof i.Sprite)&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[ie])&&isObjectInFrustum(e,h)?(this.initDepthUniform(e.material),x=!0):e instanceof Y&&(e.visible=!1,p.push(e)),(e instanceof o||e instanceof i.Sprite)&&e.material?.uniforms&&null!=e.material?.uniforms[de]&&isObjectInFrustum(e,h)&&e.material instanceof A&&this.initAoUniform(e.material),(e instanceof o||e instanceof i.Sprite)&&e.material?.uniforms&&null!=e.material?.uniforms[ce]&&isObjectInFrustum(e,h)&&(m.push(e),e.material.uniforms[ce].value=this.sceneColorRenderTarget.texture,P=!0),e instanceof o&&e.material?.uniforms&&null!=e.material?.uniforms[ue])e.material.uniforms[ue].value=t;else if(e instanceof o&&Array.isArray(e.material))for(const s of e.material)s.uniforms&&null!=s.uniforms[ue]&&(s.uniforms[ue].value=t)}),this.bloomPass.enabled=n,this.renderer.setRenderTarget(this.gRenderTarget),this.renderer.clear(),this.renderScene(We.opaque),this.aoPass.output=te.OUTPUT.Off,(x||P)&&(this.fquadCopyOpaque.material.uniforms.tSceneColor.value=this.gRenderTarget.textures[0],this.fquadCopyOpaque.material.uniforms.tDepthTexture.value=this.gRenderTarget.depthTexture,this.initResolutionUniform(this.fquadCopyOpaque.material),this.renderer.setRenderTarget(this.sceneColorRenderTarget),this.renderer.clear(),this.fquadCopyOpaque.render(this.renderer),this.renderer.setRenderTarget(this.gRenderTarget)),m.length,c.forEach(e=>e.visible=!0),p.forEach(e=>e.visible=!0),m.forEach(e=>e.visible=!0),this.aoPass.enabled,this.ssrPass&&(this.ssrPass.elapsedTime=t),this.volumetricFogPass&&u&&this.volumetricFogPass.update(this.camera,this.gRenderTarget,this.csm,this.scene);try{!this.paused&&this.running&&(this.render(r),this.showStats&&l?.endQuery(),this.showStats&&d(),this.renderer.info.reset(),this.renderOverlay())}catch(e){console.warn(e)}s.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout(()=>{requestAnimationFrame(w)},1e3/this.fpsCap):requestAnimationFrame(w))};!0===this.options.enableXR?this.renderer.setAnimationLoop(w):requestAnimationFrame(w)}applyGBufferMaterials(e){const t=this.gBufferCachedMaterials,s=this.gBufferCachedVisibility;t.clear(),s.length=0;Me(this.scene,i=>{if(rt(i))return s.push(i),i.visible=!1,!1;if(i instanceof o){t.set(i,i.material);let a=!1;if(Array.isArray(i.material)){i.material=i.material.slice();for(let t=0;t<i.material.length;t++)i.material[t]=this.createGBufferMaterial(i.material[t],e),a||(a=i.material[t].visible),this.initShadowUniform(i,i.material[t])}else i.material=this.createGBufferMaterial(i.material,e),a||(a=i.material.visible),this.initShadowUniform(i,i.material);a?i.visible=!0:null!=i.children&&0!=i.children.length||(s.push(i),i.visible=!1)}})}unapplyGBufferMaterials(){this.gBufferCachedMaterials.forEach((e,t)=>{t.material=e}),this.gBufferCachedVisibility.forEach((e,t)=>{e.visible=!0,e.updateMatrixWorld(!0)})}initTextures(e=this.scene){e.traverse(e=>{if(e instanceof o)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++)this._initMaterialTextures(e.material[t]);else this._initMaterialTextures(e.material)})}_initMaterialTextures(e){if(!this._initiatedMaterialTextures.has(e))if(this._initiatedMaterialTextures.add(e),e instanceof u){for(const[t,s]of Object.entries(e.uniforms))if(s.value instanceof c){if(this._initiatedTextures.has(s.value))continue;this.renderer.initTexture(s.value),this._initiatedTextures.add(s.value)}}else for(const[t,s]of Object.entries(e))if(s instanceof c){if(this._initiatedTextures.has(s))continue;this.renderer.initTexture(s),this._initiatedTextures.add(s)}}async compileAsync(e=this.scene){if(this.compileInProgress)return;this.renderer.setRenderTarget(this.gRenderTarget),this.compileInProgress=!0,this.applyGBufferMaterials(We.opaque),await this.renderer.compileAsync(e,this.camera),this.unapplyGBufferMaterials(),this.applyGBufferMaterials(We.transparent),await this.renderer.compileAsync(e,this.camera),this.unapplyGBufferMaterials(),e===this.scene&&(this.renderer.setRenderTarget(this.gRenderTarget),this.renderer.compileAsync(this.fquadBlendAO.mesh,this.fquadBlendAO.camera),this.renderer.setRenderTarget(this.sceneColorRenderTarget),this.renderer.compileAsync(this.fquadCopyOpaque.mesh,this.fquadCopyOpaque.camera));const t=this.csm.lights[0]?.shadow.camera;null!=t&&(this.applyDepthMaterial(),await this.renderer.compileAsync(e,t),this.unapplyDepthMaterial()),this.compileInProgress=!1,this.renderer.setRenderTarget(null)}applyDepthMaterial(){const e=this.gBufferCachedMaterials;e.clear(),this.scene.traverse(t=>{(t.isMesh||t.isPoints||t.isLine||t.isSprite)&&(this.initCustomDepthMaterial(t),e.set(t,t.material),t.castShadow?null!=t.customDepthMaterial?t.material=t.customDepthMaterial:t.material=dt:t.material=null)})}unapplyDepthMaterial(){this.gBufferCachedMaterials.forEach((e,t)=>{t.material=e})}renderScene(e){if(!this.running||this.paused)return;if(this.compileInProgress)return void console.error("Compile in progress, skipping render");this.applyGBufferMaterials(e);const t=this.scene.matrixWorldAutoUpdate,s=this.scene.matrixAutoUpdate,i=this.renderer.shadowMap.autoUpdate;e!==We.opaque&&(this.renderer.shadowMap.autoUpdate=!1,this.scene.matrixWorldAutoUpdate=!1,this.scene.matrixAutoUpdate=!1);try{this.renderer.render(this.scene,this.camera)}catch(e){console.warn("Render failed",e)}e===We.opaque&&this.gBufferCachedMaterials.forEach((e,t)=>{!Array.isArray(e)&&!Array.isArray(t.material)&&e instanceof u&&this.updateLightUniformValues(t.material,e)}),this.unapplyGBufferMaterials(),this.renderer.shadowMap.autoUpdate=i,this.scene.matrixWorldAutoUpdate=t,this.scene.matrixAutoUpdate=s}getEnvTexture(e){null==this.pmremGenerator&&(this.pmremGenerator=new i.PMREMGenerator(this.renderer),this.pmremGenerator.compileEquirectangularShader());let t=this.pmremGeneratorResults.get(e);return null==t&&(t=this.pmremGenerator.fromEquirectangular(e).texture,this.pmremGeneratorResults.set(e,t)),t.colorSpace=i.SRGBColorSpace,t}applyPostProcessSettings(){if(0==this.postProcessVolumes.length)return this.lutPass.enabled=!1,void(this.colorPass.enabled=!1);var e;(e=this.postProcessSettings).tonemapMapping=void 0,e.tonemapExposure=1,e.envIntensity=1,e.envTexture=void 0,e.vignetteIntensity=0,e.colorTint=new i.Color("white"),e.colorTintIntensity=0,e.depthFocus=void 0,e.depthAperture=void 0,e.depthMaxBlur=void 0,e.temperature=6500,e.temperatureTint=0,e.lut=void 0,e.lutIntensity=0;const t=this.postProcessSettings;let s,a=!1,r=!1,n=!1,o=!1;if(null==this.camera)return;const h=this.camera.getWorldPosition(Ze);let u=[];for(const e of this.postProcessVolumes){if(!Ye(e.object))continue;let l=e.blendWeight??1;const d=e.distanceToPoint(h);d>e.blendRadius||(e.blendRadius>0&&(l*=ve(1-d/e.blendRadius,0,1)),l>1&&(l=1),l>0&&(u.push(e),void 0!==e.settings.tonemapMapping&&(t.tonemapMapping=e.settings.tonemapMapping),void 0!==e.settings.tonemapExposure&&(t.tonemapExposure=i.MathUtils.lerp(t.tonemapExposure,e.settings.tonemapExposure,l)),void 0!==e.settings.envTexture&&(t.envTexture=e.settings.envTexture),void 0!==e.settings.envIntensity&&(t.envIntensity=i.MathUtils.lerp(t.envIntensity,e.settings.envIntensity,l)),void 0!==e.settings.vignetteIntensity&&(t.vignetteIntensity=i.MathUtils.lerp(t.vignetteIntensity,e.settings.vignetteIntensity,l),r=!0),void 0!==e.settings.colorTint&&void 0!==e.settings.colorTintIntensity&&e.settings.colorTintIntensity>0&&(t.colorTint=t.colorTint.lerp(e.settings.colorTint,l),o=!0),void 0!==e.settings.colorTintIntensity&&(t.colorTintIntensity=i.MathUtils.lerp(t.colorTintIntensity,e.settings.colorTintIntensity,l)),void 0!==e.settings.depthFocus&&(a=!0,t.depthFocus=void 0!==t.depthFocus?i.MathUtils.lerp(t.depthFocus,e.settings.depthFocus,l):e.settings.depthFocus),void 0!==e.settings.depthAperture&&(a=!0,t.depthAperture=void 0!==t.depthAperture?i.MathUtils.lerp(t.depthAperture,e.settings.depthAperture,l):e.settings.depthAperture),void 0!==e.settings.depthMaxBlur&&(a=!0,t.depthMaxBlur=void 0!==t.depthMaxBlur?i.MathUtils.lerp(t.depthMaxBlur,e.settings.depthMaxBlur,l):e.settings.depthMaxBlur),void 0!==e.settings.temperature&&(t.temperature=i.MathUtils.lerp(t.temperature,e.settings.temperature,l)),void 0!==e.settings.temperatureTint&&(t.temperatureTint=i.MathUtils.lerp(t.temperatureTint,e.settings.temperatureTint,l)),void 0!==e.settings.lut&&(s=e.settings.lut,n=!0),void 0!==e.settings.lutIntensity&&(t.lutIntensity=i.MathUtils.lerp(t.lutIntensity,e.settings.lutIntensity,l),n=!0)))}this.renderer.toneMapping=t.tonemapMapping??i.NoToneMapping,this.renderer.toneMappingExposure=t.tonemapExposure,null!=t.envTexture&&(this.scene.environment=this.getEnvTexture(t.envTexture)),this.scene.environmentIntensity=t.envIntensity,this.colorPass.vignetteIntensity=t.vignetteIntensity,this.colorPass.vignetteEnabled=r,this.colorPass.colorTint=t.colorTint,this.colorPass.colorTintIntensity=t.colorTintIntensity,this.colorPass.enabled=r||o,a&&this.camera instanceof l?(this.dofPass.enabled=!0,void 0!==t.depthFocus&&(this.dofPass.uniforms.focus.value=t.depthFocus),void 0!==t.depthAperture&&(this.dofPass.uniforms.aperture.value=t.depthAperture),void 0!==t.depthMaxBlur&&(this.dofPass.uniforms.maxblur.value=t.depthMaxBlur)):this.dofPass.enabled=!1,this.colorPass.temperature=t.temperature,this.colorPass.temperatureTint=t.temperatureTint,this.lutPass.enabled=n,n&&(null!=s&&(s.flipY=!0,s.generateMipmaps=!1),this.lutPass.lut=s,this.lutPass.intensity=t.lutIntensity)}renderOverlay(){if(!this.running)return;if(0===this.overlayCameras.size)return;const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.previousClientWith/2,s=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let i=0;i<e.length;i++)this.renderer.clearDepth(),this.renderer.setViewport(t-s/2+this.insetWidth*i+this.insetMargin*i,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[i])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(e){if(!this.running||null===this.container.offsetParent)return;if(this.renderer.domElement.parentElement!==this.container&&(this.container.replaceChildren(this.renderer.domElement),this.resizeRender()),0===this.composer.renderTarget1.width||0===this.composer.renderTarget1.height)return;if(0===this.composer.renderTarget2.width||0===this.composer.renderTarget2.height)return;let t=!1;if(this.ssrPass.enabled&&!1!==this.options?.reflection?.enabled){const e=this.ssrPass.selects??[];e.length=0,this.scene.traverseVisible(t=>{t instanceof o&&!0===t.material.userData?.reflective&&isObjectInFrustum(t,Qe)&&e.push(t)}),this.ssrPass.selects=e,0==e.length&&(this.ssrPass.enabled=!1),t=!0}this.options.bloom,this.composer.render(e),this.scene.matrixWorldAutoUpdate=!0,this.scene.matrixAutoUpdate=!0,t&&(this.ssrPass.enabled=!0)}hasBloom(){return null!=ge(this.scene,e=>e instanceof o&&!0===e.material?.userData?.hasBloom)}darkenNonBloomed(e){if((e instanceof o||e instanceof i.Sprite||e instanceof i.Line)&&e.visible&&(null==e.material.userData||!0!==e.material.userData.hasBloom)){if(e.material?.id===Ee.id)return;this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=Ee:(e.visible=!1,this.bloomHidden.push(e))}else"TransformControlsPlane"!==e.type&&"TransformControlsGizmo"!==e.type||(e.visible=!1,this.bloomHidden.push(e))}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof u&&(e.uniforms[ie].value=this.sceneColorRenderTarget.textures[1],this.camera instanceof l&&(null!=e.uniforms[re]&&(e.uniforms[re].value=this.camera.near),null!=e.uniforms[ae]&&(e.uniforms[ae].value=this.camera.far)))}initNormalUniform(e){e instanceof u&&null!=e.uniforms[oe]&&(e.uniforms[oe].value=this.gRenderTarget.textures[2])}initShadowUniform(e,t){var s;t instanceof A&&(t.uniforms.receiveShadow?(s=t.uniforms.receiveShadow).value||(s.value=e.receiveShadow):t.uniforms.receiveShadow={value:e.receiveShadow})}initResolutionUniform(e){e instanceof u&&null!=e.uniforms[ne]&&e.uniforms[ne].value.set(this.gRenderTarget.width,this.gRenderTarget.height)}initAoUniform(e){if(this.aoPass.enabled){e.uniforms[de].value=this.aoPass.pdRenderTarget.texture,null==e.defines.USE_SSAO_MAP&&(e.defines.USE_SSAO_MAP="",e.needsUpdate=!0),e.defines.USE_SSAO_MAP="";const t=this.tbufferMaterialCache.get(e);null!=t&&this.initAoUniform(t)}else if(null!=e.defines.USE_SSAO_MAP){delete e.defines.USE_SSAO_MAP,e.needsUpdate=!0;const t=this.tbufferMaterialCache.get(e);null!=t&&this.initAoUniform(t)}}initCustomDepthMaterial(e){if(null!=e.customDepthMaterial||!e.castShadow)return;const t=e.material;if(t instanceof A&&!t.transparent&&t.depthWrite){let s=this._customDepthMaterialCache.get(t);if(null==s){const e=Re(Se);let i;null!=t.alphaTest&&t.alphaTest>0&&null!=t.outputOpacity&&(i=t.outputOpacity.lt(t.alphaTest)),s=new A({color:e,discard:i}),this._customDepthMaterialCache.set(t,s)}e.customDepthMaterial=s}}};$e=e=t([se(),s("design:paramtypes",[HTMLElement,Object])],$e);export{$e as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const Xe=.05;function Ye(e){let t=e;for(;t;){if(!1===t.visible)return!1;t=t.parent}return!0}te.prototype.overrideVisibility=function(){const e=this.scene,t=this._visibilityCache;e.traverse(function(e){if(t.set(e,e.visible),(e.isPoints||e.isLine||e.isTransformControls||e.isSprite)&&(e.visible=!1),null!=e.material){let t=!1,s=!1;if(Array.isArray(e.material)){for(const s of e.material)if(null!=s.alphaTest&&s.alphaTest>0){t=!0;break}}else null!=e.material.alphaTest&&e.material.alphaTest>0?t=!0:!0===e.material.userData.isDecal&&(s=!0);s&&(e.visible=!1)}})};const Qe=new i.Frustum,Ke=new i.Box3,Je=new i.Matrix4;export function isObjectInFrustum(e,t){const s=Ke.setFromObject(e);return t.intersectsBox(s)}const Ze=new i.Vector3;const et=new n,tt=new p;function st(e,t,s=new i.Matrix3){return tt.copy(e),tt.x*=-1,tt.y*=-1,tt.z*=-1,t.isCubeTexture&&!1===t.isRenderTargetTexture&&(tt.y*=-1,tt.z*=-1),s.setFromMatrix4(et.makeRotationFromEuler(tt))}const it=new A({outputs:[V(0,0,0,0),V(0,0,0,0),L(E("white"),Be(4))],transparent:!0}),at=new i.MeshBasicMaterial({color:"blue",transparent:!0,opacity:.5});it.depthWrite=!1;new o(new i.BoxGeometry(4,4,4),at);function rt(e){return e instanceof i.Sprite||e.isPoints||e.isLine||e.isLineSegments2||e.isTransformControls||e.isTransformControlsGizmo||e instanceof o&&nt(e,e.material)}function nt(e,t){return null==t||(Array.isArray(t)?t.some(t=>nt(e,t)):t instanceof i.RawShaderMaterial||t instanceof i.ShaderMaterial&&!(t instanceof A))}class ot extends Ie{constructor(e,t,s){super(),this.scene=e,this.camera=t,this.gRenderTarget=s,this.cachedVisibility=[],this.toRender=[],this.needsSwap=!1}render(e,t,s,i,a){const r=e.autoClear;e.autoClear=!1;const n=this.scene.matrixWorldAutoUpdate,l=this.scene.matrixAutoUpdate,h=e.shadowMap.autoUpdate;this.scene.matrixAutoUpdate=!1,e.shadowMap.autoUpdate=!1;const u=s.depthTexture;s.depthTexture=this.gRenderTarget.depthTexture,e.setRenderTarget(s),this.cachedVisibility.length=0;let d=0,c=this.toRender;if(c.length=0,this.scene.traverseVisible(e=>{const t=rt(e);e instanceof o&&!t?(this.cachedVisibility.push(e),e.visible=!1):t&&(d++,c.push(e))}),d>0)for(const t of c)e.render(t,this.camera);this.cachedVisibility.forEach((e,t)=>{e.visible=!0}),e.setRenderTarget(null),e.autoClear=r,s.depthTexture=u,this.scene.matrixWorldAutoUpdate=n,this.scene.matrixAutoUpdate=l,e.shadowMap.autoUpdate=h}}class lt extends Ie{constructor(e){super(),this.fn=e}render(e,t,s,i,a){this.fn(e,t,s,i,a)}}const ht=["ambientLightColor","cameraNear","directionalLightShadows","directionalLights","directionalShadowMap","directionalShadowMatrix","fogColor","fogDensity","fogFar","fogNear","hemisphereLights","lightProbe","ltc_1","ltc_2","pointLightShadows","pointLights","pointShadowMap","pointShadowMatrix","rectAreaLights","shadowFar","spotLightMap","spotLightMatrix","spotLightShadows","spotLights","spotShadowMap"],ut=B("fogColor");export class FogNode extends H{constructor(e,t=ut){super(),this.source=e,this.fogColor=t}compile(e){const t=e.variable(),s=e.get(this.source.rgb),i=e.get(this.source.a),a=e.get(this.fogColor),r=e.get(F("fogFar")),n=e.get(F("fogNear")),o=e.get(F("fogDensity")),l=e.get(j(W.mvPosition.z));return{pars:"\n ",chunk:`\n #ifdef FOG_EXP2\n float fogFactor_${t} = 1.0 - exp( - ${o} * ${o} * ${l} * ${l} );\n #else\n float fogFactor_${t} = smoothstep( ${n}, ${r}, ${l} );\n #endif\n vec4 color_vec4_${t} = vec4(mix(${s}, ${a}, fogFactor_${t}), ${i});\n `,out:`color_vec4_${t}`}}}const dt=new i.MeshDepthMaterial({depthPacking:i.RGBADepthPacking});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as r,Mesh as i,Object3D as a,TextureLoader as n}from"three";import{GLTFLoader as o,MTLLoader as h,OBJLoader as l,DRACOLoader as c,LUTCubeLoader as u}from"three-stdlib";import{FBXLoader as d}from"three-stdlib";import{cloneMesh as m}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as p,firstValueFrom as g}from"rxjs";import{importCollisionShapes as w,isCollisionMesh as y}from"./collision/collision-shape-import.js";import*as x from"three";import{iterateMaterials as M}from"../utils/materials.js";import{BufferGeometryUtils as L,EXRLoader as b,KTX2Loader as A,TGALoader as v,UltraHDRLoader as _}from"three/examples/jsm/Addons.js";import{disposeScene as C}from"../utils/three/cleanup.js";const S=new c;S.setDecoderConfig({type:"js"}),S.setDecoderPath("/assets/draco/");const R=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new r,this.glbLoader=new o(this.loadingManager).setDRACOLoader(S),this.fbxLoader=new d(this.loadingManager),this.objLoader=new l(this.loadingManager),this.textureLoader=new n(this.loadingManager),this.tgaLoader=new v(this.loadingManager),this.exrLoader=new b(this.loadingManager),this.cubeLoader=new u(this.loadingManager),this.hdrLoader=new _(this.loadingManager),this.ktx2Loader=new A(this.loadingManager),this._textureLoader=new x.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new p,this.ready=g(this.makeReady),this._texturePromises=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=getElectronArg("windowId");return null!=t||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=t?`?windowId=${t}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if(this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);t.dispose(),null!=e.texture&&(t.flipY!==e.texture?.flipY?(t.needsUpdate=!0,t.flipY=e.texture?.flipY??!0):t.wrapS!==P(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=P(e.texture?.wrapS)):t.wrapT!==P(e.texture?.wrapT)&&(t.wrapT=P(e.texture?.wrapT),t.needsUpdate=!0))}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=P(e.texture?.wrapS),t.wrapT=P(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}return this.textureCache.get(e.id)}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){"mesh"===e.type&&Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)})}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new s,animations:[]};if(!R.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new s,animations:[]}}const a=this.cache.get(r).scene,n=this.computeCollisionShapes(e,a);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(a);const o=m(a),h=this.cache.get(r).animations;o.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const l=new AssetMeshInstance;l.add(o),l.collisionShapes=n,l.animations=h;const c=e.receiveShadow??!0,u=e.castShadow??!1;return o.traverse(e=>{e.castShadow=u,e.receiveShadow=c}),{scene:l,animations:h}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const s=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,s),s}async getAnimationClip(e){if(null==e||null==e.fileKey||null==!e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,s=e.fileKey+"|"+t;if(this._animationCache.has(s))return this._animationCache.get(s);if(this._animationPromises.has(s))return this._animationPromises.get(s);const r=(async()=>{try{const r=await this.getMesh(e),i=r.animations.find(e=>e.name===t);return null!=i&&this._animationCache.set(s,i),i}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(s),1e3)}})();return this._animationPromises.set(s,r),r}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,w(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(e=>(e.scene.traverse(e=>{e instanceof i&&e.material,y(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(e.scene),e.scene=function(e,t){let s=!1;if(t.traverseVisible(e=>{j.test(e.name)&&(s=!0)}),!s)return t;const r=new x.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(j);if(null!=t){const s=parseInt(t[1]);0===s?r.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return r}(0,e.scene),e))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,r=0,a=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){r++;const t=Object.keys(e.geometry.attributes).length;t!==a&&0!==a&&(s=!1),a=t}else(e instanceof x.SkinnedMesh||e instanceof x.Bone)&&(s=!1)}),r>1&&s){const s=new Map;e.updateWorldMatrix(!0,!0),e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){if(Array.isArray(e.material))return;e.updateWorldMatrix(!0,!0);const t=e.material?.uuid||"default";s.has(t)||s.set(t,{material:e.material,geometries:[],objects:[]});const r=s.get(t);r.geometries.push(e.geometry.clone().applyMatrix4(e.matrixWorld)),r.objects.push(e)}});for(const e of s.values())for(const t of e.objects)t.removeFromParent();for(const t of s.values()){let s;s=1===t.geometries.length?t.geometries[0]:L.mergeGeometries(t.geometries,!0),s.groups.length>1&&L.mergeGroups(s),e.add(new i(s,t.material))}}const n=[];e.traverse(e=>{e instanceof i&&e.geometry instanceof t&&Array.isArray(e.material)&&!y(e)&&n.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:s,materialArray:r,parent:a}of n){t.removeFromParent();for(let t=0;t<r.length;t++){const n=r[t],o=s.groups.filter(e=>e.materialIndex===t);if(0===o.length)continue;const h=this.extractGeometryGroups(s,o);h.groups.length>1&&L.mergeGroups(h);const l=new i(h,n);a?a.add(l):e.add(l)}s.dispose()}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&L.mergeGroups(t)}})}extractGeometryGroups(e,s){const r=e.index;if(!r){const r=new t;let i=0;for(const e of s)i+=e.count;if(0===i)return r;for(const t in e.attributes){const a=e.attributes[t],n=a.itemSize,o=a.array,h=new(0,o.constructor)(i*n);let l=0;for(const e of s){const t=e.start*n,s=e.count*n;for(let e=0;e<s;e++)h[l+e]=o[t+e];l+=s}const c=new x.BufferAttribute(h,n,a.normalized);r.setAttribute(t,c)}return r.groups=[{start:0,count:i,materialIndex:0}],r}const i=[];for(const e of s)for(let t=0;t<e.count;t++){const s=r.getX(e.start+t);i.push(s)}if(0===i.length)return new t;const a=new Map,n=[];let o=0;for(const e of i)a.has(e)||(a.set(e,o),o++),n.push(a.get(e));if(0===n.length||0===a.size)return new t;const h=new t;for(const t in e.attributes){const s=e.attributes[t],r=s.itemSize,i=s.array,n=new(0,i.constructor)(a.size*r);for(const[e,t]of a)for(let s=0;s<r;s++)n[t*r+s]=i[e*r+s];const o=new x.BufferAttribute(n,r,s.normalized);h.setAttribute(t,o)}const l=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)l[e]=n[e];return h.setIndex(new x.BufferAttribute(l,1)),h.groups=[{start:0,count:n.length,materialIndex:0}],h}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new h;t.materialOptions={normalizeRGB:!1};const s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then(e=>(T(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>C(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}function T(e){if(e instanceof i)for(const t of M(e.material))t instanceof x.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(T)}export class AssetMeshInstance extends a{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find(e=>e.startsWith(t));return s?.substring(t.length)}function P(e){switch(e){case"clamp":return x.ClampToEdgeWrapping;case"repeat":return x.RepeatWrapping;case"mirror":return x.MirroredRepeatWrapping}return x.RepeatWrapping}new x.Matrix4;const j=/_LOD(\d+)$/;/*
1
+ import{AudioLoader as e,BufferGeometry as t,Group as s,LoadingManager as r,Mesh as i,Object3D as a,TextureLoader as n}from"three";import{GLTFLoader as o,MTLLoader as l,OBJLoader as h,DRACOLoader as c,LUTCubeLoader as u}from"three-stdlib";import{FBXLoader as d}from"three-stdlib";import{cloneMesh as m}from"../utils/mesh.js";import{pathJoin as f}from"../utils/files.js";import{Subject as p,firstValueFrom as g}from"rxjs";import{importCollisionShapes as w,isCollisionMesh as y}from"./collision/collision-shape-import.js";import*as x from"three";import{iterateMaterials as M}from"../utils/materials.js";import{BufferGeometryUtils as L,EXRLoader as b,KTX2Loader as A,TGALoader as v,UltraHDRLoader as _}from"three/examples/jsm/Addons.js";import{disposeScene as C}from"../utils/three/cleanup.js";const S=new c;S.setDecoderConfig({type:"js"}),S.setDecoderPath("/assets/draco/");const R=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new r,this.glbLoader=new o(this.loadingManager).setDRACOLoader(S),this.fbxLoader=new d(this.loadingManager),this.objLoader=new h(this.loadingManager),this.textureLoader=new n(this.loadingManager),this.tgaLoader=new v(this.loadingManager),this.exrLoader=new b(this.loadingManager),this.cubeLoader=new u(this.loadingManager),this.hdrLoader=new _(this.loadingManager),this.ktx2Loader=new A(this.loadingManager),this._textureLoader=new x.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.initialisedKtx2=!1,this._retrievedMeshes=[],this._retrievedTextures=[],this.makeReady=new p,this.ready=g(this.makeReady),this._texturePromises=new Map,this._animationPromises=new Map,this._animationCache=new Map,this.asyncMeshResults=new Map,this.asyncAudioResults=new Map,this.collisionShapeCache=new Map,this.optimizedMeshes=new Set}initKtx2(e){this.initialisedKtx2=!0;null!=getElectronArg("windowId")||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?this.ktx2Loader.setTranscoderPath("/assets/basis/"):this.ktx2Loader.setTranscoderPath(new URL("../assets/basis/",import.meta.url).href),this.ktx2Loader.detectSupport(e)}setDataDir(e){this.basePath=f(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){const t=function(e){return T.get(e)}(e),s=getElectronArg("windowId");return null!=s||import.meta.url.includes(".vite")||import.meta.url.includes("hology/packages/core")?f(this.basePath,e)+(null!=s?`?windowId=${s}&v=${t}`:""):new URL(f("..",this.basePath,e),import.meta.url).href}async getTexture(e){if(!e||!e.fileKey)return null;if(this._texturePromises.has(e.id))return this._texturePromises.get(e.id);const t=this._getTexture(e).finally(()=>{this._texturePromises.delete(e.id)});return this._texturePromises.set(e.id,t),t}async _getTexture(e){if(null==e||null==e.fileKey)return null;if(await this.ready,this.textureCache.has(e.id)){const t=this.textureCache.get(e.id);t.dispose(),null!=e.texture&&(t.flipY!==e.texture?.flipY?(t.needsUpdate=!0,t.flipY=e.texture?.flipY??!0):t.wrapS!==K(e.texture?.wrapS)?(t.needsUpdate=!0,t.wrapS=K(e.texture?.wrapS)):t.wrapT!==K(e.texture?.wrapT)&&(t.wrapT=K(e.texture?.wrapT),t.needsUpdate=!0))}else try{await this._getTextureLoader(e.fileKey).loadAsync(this.getUri(e.fileKey)).then(t=>(t.texture3D?t=t.texture3D:(t.wrapS=K(e.texture?.wrapS),t.wrapT=K(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0),this.textureCache.set(e.id,t),this._retrievedTextures.push(t),t))}catch(t){return console.warn("Failed to load texture "+e.name,t),null}const t=this.textureCache.get(e.id);return null!=t&&(t.userData.assetId=e.id),t}_getTextureLoader(e){return e?.toLowerCase().endsWith(".tga")?this.tgaLoader:e?.toLowerCase().endsWith(".ktx2")?this.ktx2Loader:e?.toLowerCase().endsWith(".exr")?this.exrLoader:e?.toLowerCase().endsWith(".cube")?this.cubeLoader:this.textureLoader}clearCache(e){"mesh"===e.type?(Array.from(this.cache.keys()).forEach(t=>{t.startsWith(e.fileKey)&&this.cache.delete(t)}),P(e.fileKey)):"texture"===e.type&&(this.textureCache.delete(e.id),P(e.fileKey))}async getMesh(e,t){if(await this.ready,null==e)return console.error("No asset was provided"),{scene:new s,animations:[]};if(!R.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new s,animations:[]};const r=e.fileKey+(!0===t?.mergeGeomtries?"1":"0");if(!this.cache.has(r))try{this.asyncMeshResults.has(r)||this.asyncMeshResults.set(r,this.loadMesh(e).finally(()=>this.asyncMeshResults.delete(r))),this.cache.set(r,await this.asyncMeshResults.get(r))}catch(e){return this.onError(e),{scene:new s,animations:[]}}const a=this.cache.get(r).scene,n=this.computeCollisionShapes(e,a);!0===t?.mergeGeomtries&&this.optimizeDrawGroups(a);const o=m(a),l=this.cache.get(r).animations;o.traverse(e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())});const h=new AssetMeshInstance;h.add(o),h.collisionShapes=n,h.animations=l;const c=e.receiveShadow??!0,u=e.castShadow??!1;return o.traverse(e=>{e.castShadow=u,e.receiveShadow=c}),{scene:h,animations:l}}async getAudio(e){await this.ready;const t=e.fileKey;if(this.asyncAudioResults.has(t))return await this.asyncAudioResults.get(t);const s=this.audioLoader.loadAsync(this.getUri(e.fileKey)).finally(()=>{setTimeout(()=>{this.asyncAudioResults.delete(t)},1e3)});return this.asyncAudioResults.set(t,s),s}async getAnimationClip(e){if(null==e||null==e.fileKey||null==!e.anim?.clip)return console.warn("Asset or animation clip name is not defined",e),null;const t=e.anim.clip,s=e.fileKey+"|"+t;if(this._animationCache.has(s))return this._animationCache.get(s);if(this._animationPromises.has(s))return this._animationPromises.get(s);const r=(async()=>{try{const r=await this.getMesh(e),i=r.animations.find(e=>e.name===t);return null!=i&&this._animationCache.set(s,i),i}catch(e){return this.onError(e),null}finally{setTimeout(()=>this._animationPromises.delete(s),1e3)}})();return this._animationPromises.set(s,r),r}computeCollisionShapes(e,t){const s=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(s)||this.collisionShapeCache.set(s,w(t,e)),this.collisionShapeCache.get(s)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then(e=>(e.scene.traverse(e=>{e instanceof i&&e.material,y(e)?e.visible=!1:e instanceof i&&e.geometry instanceof t&&(e.geometry.hasAttribute("normal")||e.geometry.computeVertexNormals())}),this._retrievedMeshes.push(e.scene),e.scene=function(e,t){let s=!1;if(t.traverseVisible(e=>{k.test(e.name)&&(s=!0)}),!s)return t;const r=new x.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(k);if(null!=t){const s=parseInt(t[1]);0===s?r.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return r}(0,e.scene),e))}optimizeDrawGroups(e){if(this.optimizedMeshes.has(e.uuid))return;this.optimizedMeshes.add(e.uuid);let s=!0,r=0,a=0;if(e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){r++;const t=Object.keys(e.geometry.attributes).length;t!==a&&0!==a&&(s=!1),a=t}else(e instanceof x.SkinnedMesh||e instanceof x.Bone)&&(s=!1)}),r>1&&s){const s=new Map;e.updateWorldMatrix(!0,!0),e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){if(Array.isArray(e.material))return;e.updateWorldMatrix(!0,!0);const t=e.material?.uuid||"default";s.has(t)||s.set(t,{material:e.material,geometries:[],objects:[]});const r=s.get(t);r.geometries.push(e.geometry.clone().applyMatrix4(e.matrixWorld)),r.objects.push(e)}});for(const e of s.values())for(const t of e.objects)t.removeFromParent();for(const t of s.values()){let s;s=1===t.geometries.length?t.geometries[0]:L.mergeGeometries(t.geometries,!0),s.groups.length>1&&L.mergeGroups(s),e.add(new i(s,t.material))}}const n=[];e.traverse(e=>{e instanceof i&&e.geometry instanceof t&&Array.isArray(e.material)&&!y(e)&&n.push({mesh:e,geometry:e.geometry,materialArray:e.material,parent:e.parent})});for(const{mesh:t,geometry:s,materialArray:r,parent:a}of n){t.removeFromParent();for(let t=0;t<r.length;t++){const n=r[t],o=s.groups.filter(e=>e.materialIndex===t);if(0===o.length)continue;const l=this.extractGeometryGroups(s,o);l.groups.length>1&&L.mergeGroups(l);const h=new i(l,n);a?a.add(h):e.add(h)}s.dispose()}e.traverse(e=>{if(e instanceof i&&e.geometry instanceof t&&!y(e)){const t=e.geometry;!Array.isArray(e.material)&&t.groups.length>1&&L.mergeGroups(t)}})}extractGeometryGroups(e,s){const r=e.index;if(!r){const r=new t;let i=0;for(const e of s)i+=e.count;if(0===i)return r;for(const t in e.attributes){const a=e.attributes[t],n=a.itemSize,o=a.array,l=new(0,o.constructor)(i*n);let h=0;for(const e of s){const t=e.start*n,s=e.count*n;for(let e=0;e<s;e++)l[h+e]=o[t+e];h+=s}const c=new x.BufferAttribute(l,n,a.normalized);r.setAttribute(t,c)}return r.groups=[{start:0,count:i,materialIndex:0}],r}const i=[];for(const e of s)for(let t=0;t<e.count;t++){const s=r.getX(e.start+t);i.push(s)}if(0===i.length)return new t;const a=new Map,n=[];let o=0;for(const e of i)a.has(e)||(a.set(e,o),o++),n.push(a.get(e));if(0===n.length||0===a.size)return new t;const l=new t;for(const t in e.attributes){const s=e.attributes[t],r=s.itemSize,i=s.array,n=new(0,i.constructor)(a.size*r);for(const[e,t]of a)for(let s=0;s<r;s++)n[t*r+s]=i[e*r+s];const o=new x.BufferAttribute(n,r,s.normalized);l.setAttribute(t,o)}const h=new((n.length>0?Math.max(...n):0)>65535?Uint32Array:Uint16Array)(n.length);for(let e=0;e<n.length;e++)h[e]=n[e];return l.setIndex(new x.BufferAttribute(h,1)),l.groups=[{start:0,count:n.length,materialIndex:0}],l}async loadByAsset(e){this.fbxLoader;const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then(e=>({scene:e.scene,animations:e.animations}));case"fbx":return this.fbxLoader.loadAsync(t).then(e=>({scene:e,animations:e.animations}));case"obj":if(null!=e.materialLib){const t=new l;t.materialOptions={normalizeRGB:!1};const s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then(e=>(j(e),e)).then(e=>({scene:e,animations:e.animations}))}}disposeAll(){this.cache.clear(),this._retrievedMeshes.forEach(e=>C(e)),this._retrievedTextures.forEach(e=>e.dispose()),this._retrievedMeshes.length=0,this._retrievedTextures.length=0}}const T=new Map;function P(e){T.set(e,T.get(e)??1)}function j(e){if(e instanceof i)for(const t of M(e.material))t instanceof x.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(j)}export class AssetMeshInstance extends a{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find(e=>e.startsWith(t));return s?.substring(t.length)}function K(e){switch(e){case"clamp":return x.ClampToEdgeWrapping;case"repeat":return x.RepeatWrapping;case"mirror":return x.MirroredRepeatWrapping}return x.RepeatWrapping}new x.Matrix4;const k=/_LOD(\d+)$/;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */