@hology/core 0.0.273 → 0.0.274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +19 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
- package/dist/gameplay/actors/builtin/water-spline-volume-actor.d.ts +10 -0
- package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +1 -1
- package/dist/gameplay/actors/builtin/water-volume-actor.d.ts +3 -1
- package/dist/gameplay/actors/builtin/water-volume-actor.js +1 -1
- package/dist/gameplay/actors/camera/first-person-camera-component.js +1 -1
- package/dist/gameplay/actors/camera/third-person-camera-component.d.ts +7 -0
- package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
- package/dist/gameplay/ai/behavior-tree/move.d.ts +5 -0
- package/dist/gameplay/ai/behavior-tree/move.js +1 -1
- package/dist/gameplay/ai/behavior-tree/move.test.d.ts +2 -0
- package/dist/gameplay/ai/behavior-tree/move.test.js +4 -0
- package/dist/gameplay/animation/root-motion.js +1 -1
- package/dist/gameplay/input/input-service.d.ts +9 -1
- package/dist/gameplay/input/input-service.js +1 -1
- package/dist/gameplay/services/physics/physics-system.d.ts +2 -0
- package/dist/gameplay/services/physics/physics-system.js +1 -1
- package/dist/gameplay/services/render.d.ts +4 -1
- package/dist/gameplay/services/render.js +1 -1
- package/dist/gameplay/services/world.d.ts +5 -0
- package/dist/rendering/node-material-webgpu-resolver.js +1 -1
- package/dist/rendering/webgpu-experimental-backend.d.ts +4 -2
- package/dist/rendering/webgpu-experimental-backend.js +1 -1
- package/dist/rendering.d.ts +17 -2
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +4 -0
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/collision/collision-shape-import.js +1 -1
- package/dist/scene/collision/rapier-shape.js +1 -1
- package/dist/scene/landscape/landscape-geometry.d.ts +24 -0
- package/dist/scene/landscape/landscape-geometry.js +4 -0
- package/dist/scene/landscape/landscape-manager.d.ts +1 -0
- package/dist/scene/landscape/landscape-manager.js +1 -1
- package/dist/scene/materializer.d.ts +7 -1
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/scene-data-service.d.ts +2 -1
- package/dist/scene/scene-data-service.js +1 -1
- package/dist/scene/sky.d.ts +2 -0
- package/dist/scene/sky.js +1 -1
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/graph/registry.js +1 -1
- package/dist/shader/parameter.js +1 -1
- package/dist/shader/sprite-shader.js +1 -1
- package/dist/shader-nodes/depth.d.ts +6 -4
- package/dist/shader-nodes/depth.js +1 -1
- package/dist/shader-nodes/index.d.ts +2 -1
- package/dist/shader-nodes/index.js +1 -1
- package/dist/shader-nodes/surface-reflection.d.ts +9 -0
- package/dist/shader-nodes/surface-reflection.js +4 -0
- package/dist/shader-nodes/water-volume.d.ts +6 -2
- package/dist/shader-nodes/water-volume.js +1 -1
- package/dist/test/asset-resource-loader-texture-array.test.js +1 -1
- package/dist/test/character-movement-solve.test.js +1 -1
- package/dist/test/collision-shape-import.test.js +1 -1
- package/dist/test/first-person-camera-component.test.js +1 -1
- package/dist/test/frame-stats.test.js +1 -1
- package/dist/test/gpu-sprite-compiler.test.js +1 -1
- package/dist/test/input.test.js +1 -1
- package/dist/test/landscape-geometry.test.d.ts +2 -0
- package/dist/test/landscape-geometry.test.js +4 -0
- package/dist/test/material-assignment.test.js +1 -1
- package/dist/test/materializer-dynamic-transform.test.js +1 -1
- package/dist/test/materializer-prefetch.test.js +1 -1
- package/dist/test/net-character-movement.test.js +1 -1
- package/dist/test/node-material-webgpu-resolver.test.js +1 -1
- package/dist/test/parameter-definition.test.js +1 -1
- package/dist/test/physics-hitstop.test.d.ts +2 -0
- package/dist/test/physics-hitstop.test.js +4 -0
- package/dist/test/physics-ray-object.test.js +1 -1
- package/dist/test/post-process-effect.test.js +1 -1
- package/dist/test/rapier-trimesh.test.d.ts +2 -0
- package/dist/test/rapier-trimesh.test.js +4 -0
- package/dist/test/sequence-animation-retiming.test.js +1 -1
- package/dist/test/sequence-vfx.test.js +1 -1
- package/dist/test/surface-reflection.test.d.ts +2 -0
- package/dist/test/surface-reflection.test.js +4 -0
- package/dist/test/water-spline-volume-actor.test.js +1 -1
- package/dist/utils/three/frame-stats.d.ts +8 -0
- package/dist/utils/three/frame-stats.js +1 -1
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as e}from"tslib";import{Service as t}from"typedi";import{inject as s}from"../inject.js";import{ViewController as i}from"../services/render.js";import{MathUtils as n}from"three";import{Subject as a}from"rxjs";let o=class{constructor(){this.view=s(i),this.inputs=new Map,this.deltaCallbacks=new Map,this.toggleCallbacks=new Map,this.keybinds=new Map,this.mousebinds=new Map,this.touchmoveBinds=new Map,this.wheelbinds=new Map,this.gamepadButtonBinds=new Map,this.gamepadAxisBinds=new Map,this.lastActiveDevice="kbm",this.onDeviceChanged=new a,this.prevGamepadButtonStates=new Map,this.suppressedGamepadButtons=new Map,this.sampledGamepadButtonStates=new Map,this.pendingGamepadButtonTransitions=new Map,this.frameGamepadButtonTransitions=new Map,this.onKeyDown=e=>{this.setLastActiveDevice("kbm"),this.view.paused||"button"in e&&!h()||this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!0);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!0);this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s))<0&&this.activeToggleCallbacks.push({keybind:i,toggle:this.toggleCallbacks.get(s)})}else console.warn("No input callback for registered for key bind "+i.display())})},this.activeToggleCallbacks=[],this.onKeyUp=e=>{this.setLastActiveDevice("kbm"),this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!1);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!1);const e=this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s));e>=0&&this.activeToggleCallbacks.splice(e,1);for(const e of this.activeToggleCallbacks)e.toggle(!0)}else console.warn("No input callback for registered for key bind "+i.display())})},this.onMouseMove=e=>{if((Math.abs(e.movementX)>1||Math.abs(e.movementY)>1)&&this.setLastActiveDevice("kbm"),this.view.paused)return;if(!h())return;const t=n.clamp(e.movementX,-50,50),s=n.clamp(e.movementY,-50,50);Math.abs(t)>200||Math.abs(s)>200||this.mousebinds.forEach((e,i)=>{const n=this.inputs.get(i)??this.deltaCallbacks.get(i);if(null!=n)switch(e.axis){case"x":n(t*e.multiplier);break;case"y":n(s*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)})},this.onTouchStart=e=>{if(this.setLastActiveDevice("kbm"),!this.view.paused){for(let t=0;t<=e.touches.length;t++){const s=e.touches[t];if(s?.target instanceof HTMLCanvasElement)return void(this.prevTouchEvent=s)}e.preventDefault()}},this.onTouchMove=e=>{if(this.view.paused)return;if(null==this.prevTouchEvent)return;let t=null;for(let s=0;s<=e.touches.length;s++){const i=e.touches[s];if(i&&i.target instanceof HTMLCanvasElement&&i.identifier===this.prevTouchEvent.identifier){t=i;break}}null!=t&&(this.touchmoveBinds.forEach((e,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);if(null!=i)switch(e.axis){case"x":i((t.clientX-this.prevTouchEvent.clientX)*e.multiplier);break;case"y":i((t.clientY-this.prevTouchEvent.clientY)*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)}),this.prevTouchEvent=t,e.preventDefault())},this.onTouchEnd=e=>{this.prevTouchEvent=null,e.preventDefault()},this.onWheel=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.wheelbinds.forEach((t,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);null!=i?i(e.deltaY*t.multiplier):console.warn("No input callback for registered for wheel bind")})}}getLastActiveDevice(){return this.lastActiveDevice}suppressHeldGamepadButtonsUntilRelease(){const e=navigator.getGamepads();this.sampleGamepadButtonsFrom(e,!1);for(let t=0;t<e.length;t++){const s=e[t];if(!s||"standard"!==s.mapping)continue;const i=this.suppressedGamepadButtons.get(t),n=this.pendingGamepadButtonTransitions.get(t),a=this.prevGamepadButtonStates.get(t),o=this.frameGamepadButtonTransitions.get(t);for(let e=0;e<s.buttons.length;e++)s.buttons[e].pressed&&(i[e]=!0),n[e]=0,a[e]=!1,o[e]=0}}setLastActiveDevice(e){this.lastActiveDevice!==e&&(this.lastActiveDevice=e,this.onDeviceChanged.next(e))}start(){document.addEventListener("keydown",this.onKeyDown),document.addEventListener("mousedown",this.onKeyDown),document.addEventListener("mouseup",this.onKeyUp),document.addEventListener("keyup",this.onKeyUp),document.addEventListener("mousemove",this.onMouseMove),this.view.htmlElement.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.view.htmlElement.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.view.htmlElement.addEventListener("touchend",this.onTouchEnd,{passive:!1}),document.addEventListener("wheel",this.onWheel)}stop(){document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("mousedown",this.onKeyDown),document.removeEventListener("mouseup",this.onKeyUp),document.removeEventListener("keyup",this.onKeyUp),document.removeEventListener("mousemove",this.onMouseMove),this.view.htmlElement.removeEventListener("touchstart",this.onTouchStart),this.view.htmlElement.removeEventListener("touchmove",this.onTouchMove),this.view.htmlElement.removeEventListener("touchend",this.onTouchEnd),document.removeEventListener("wheel",this.onWheel)}sampleGamepadButtons(e=!1){this.sampleGamepadButtonsFrom(navigator.getGamepads(),e)}sampleGamepadButtonsFrom(e,t){for(let s=0;s<e.length;s++){const i=e[s];if(!i||"standard"!==i.mapping)continue;let n=this.sampledGamepadButtonStates.get(s);null==n&&(n=new Array(i.buttons.length).fill(!1),this.sampledGamepadButtonStates.set(s,n),this.pendingGamepadButtonTransitions.set(s,new Array(i.buttons.length).fill(0)),this.frameGamepadButtonTransitions.set(s,new Array(i.buttons.length).fill(0)),this.prevGamepadButtonStates.set(s,new Array(i.buttons.length).fill(!1)),this.suppressedGamepadButtons.set(s,new Array(i.buttons.length).fill(!1)));const a=this.pendingGamepadButtonTransitions.get(s),o=this.suppressedGamepadButtons.get(s),h=this.prevGamepadButtonStates.get(s);for(let e=0;e<i.buttons.length;e++){const s=i.buttons[e].pressed;t?(a[e]=h[e]?1:0,s&&(o[e]=!0)):o[e]||s===n[e]||a[e]++,o[e]&&!s&&(o[e]=!1,a[e]=h[e]?1:0),n[e]=s}}}update(e){if(this.view.paused)return;const t=navigator.getGamepads();this.sampleGamepadButtonsFrom(t,!1);for(let e=0;e<t.length;e++){const s=t[e];if(!s||"standard"!==s.mapping)continue;const i=this.prevGamepadButtonStates.get(e),n=this.suppressedGamepadButtons.get(e),a=this.pendingGamepadButtonTransitions.get(e),o=this.frameGamepadButtonTransitions.get(e);for(let e=0;e<s.buttons.length;e++){o[e]=0===a[e]?0:i[e]?a[e]>1?3:2:1;const t=o[e];0!==t&&(i[e]=!!(1&t),a[e]-=3===t?2:1)}this.gamepadButtonBinds.forEach((e,t)=>{for(const a of e){const e=a.button,h=s.buttons[e];if(!h)continue;const l=h.pressed,d=h.value,r=o[e],u=0===r?i[e]:!!(2&r);if(n[e]&&2!==r)continue;if(0!==r){this.setLastActiveDevice("gamepad");const s=this.toggleCallbacks.get(t);s&&(2&r&&s(!1),1&o[e]&&!n[e]&&s(!0))}if(n[e])continue;const c=this.inputs.get(t)??this.deltaCallbacks.get(t);c&&(d>0||l||u&&0===d)&&"gamepad"===this.lastActiveDevice&&c(d)}}),this.gamepadAxisBinds.forEach((e,t)=>{for(const i of e){let e=s.axes[i.axis];if(e=Math.abs(e)<i.deadzone?0:(e-Math.sign(e)*i.deadzone)/(1-i.deadzone),0!==e&&this.setLastActiveDevice("gamepad"),"gamepad"!==this.lastActiveDevice)break;e*=i.multiplier;const n=this.inputs.get(t)??this.deltaCallbacks.get(t);n&&n(e)}})}}bind(e,t){this.inputs.set(e,t)}bindToggle(e,t){this.toggleCallbacks.set(e,t)}bindDelta(e,t){this.deltaCallbacks.set(e,t)}unbind(e){this.inputs.delete(e),this.toggleCallbacks.delete(e),this.deltaCallbacks.delete(e)}setKeybind(e,t){this.keybinds.has(e)||this.keybinds.set(e,[]),this.keybinds.get(e).push(t)}setMousebind(e,t){this.mousebinds.set(e,t)}setTouchMoveBind(e,t){this.touchmoveBinds.set(e,t)}setWheelbind(e,t){this.wheelbinds.set(e,t)}setGamepadButtonBind(e,t){this.gamepadButtonBinds.has(e)||this.gamepadButtonBinds.set(e,[]),this.gamepadButtonBinds.get(e).push(t)}setGamepadAxisBind(e,t){this.gamepadAxisBinds.has(e)||this.gamepadAxisBinds.set(e,[]),this.gamepadAxisBinds.get(e).push(t)}removeKeybind(e){this.keybinds.delete(e)}removeMousebind(e){this.mousebinds.delete(e)}removeWheelbind(e){this.wheelbinds.delete(e)}removeGamepadButtonBind(e){this.gamepadButtonBinds.delete(e)}removeGamepadAxisBind(e){this.gamepadAxisBinds.delete(e)}vibrate(e,t=1,s=1){const i=navigator.getGamepads();for(const n of i)n&&n.vibrationActuator&&n.vibrationActuator.playEffect("dual-rumble",{startDelay:0,duration:e,weakMagnitude:s,strongMagnitude:t})}};o=e([t()],o);export{o as InputService};function h(){return null!=document.pointerLockElement||null!=document.mozPointerLockElement}/*
|
|
1
|
+
import{__decorate as e}from"tslib";import{Service as t}from"typedi";import{inject as s}from"../inject.js";import{ViewController as i}from"../services/render.js";import{MathUtils as n}from"three";import{Subject as a}from"rxjs";let o=class{constructor(){this.view=s(i),this.inputs=new Map,this.deltaCallbacks=new Map,this.toggleCallbacks=new Map,this.keybinds=new Map,this.mousebinds=new Map,this.touchmoveBinds=new Map,this.wheelbinds=new Map,this.gamepadButtonBinds=new Map,this.gamepadAxisBinds=new Map,this.lastActiveDevice="kbm",this.onDeviceChanged=new a,this.prevGamepadButtonStates=new Map,this.suppressedGamepadButtons=new Map,this.sampledGamepadButtonStates=new Map,this.pendingGamepadButtonTransitions=new Map,this.frameGamepadButtonTransitions=new Map,this.onKeyDown=e=>{this.setLastActiveDevice("kbm"),this.view.paused||"button"in e&&!d()||this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!0);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!0);this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s))<0&&this.activeToggleCallbacks.push({keybind:i,toggle:this.toggleCallbacks.get(s)})}else console.warn("No input callback for registered for key bind "+i.display())})},this.activeToggleCallbacks=[],this.onKeyUp=e=>{this.setLastActiveDevice("kbm"),this.keybinds.forEach((t,s)=>{for(const i of t)if(i.test(e))if(this.inputs.has(s))this.inputs.get(s)(!1);else if(this.toggleCallbacks.has(s)){this.toggleCallbacks.get(s)(!1);const e=this.activeToggleCallbacks.findIndex(e=>e.keybind===i&&e.toggle===this.toggleCallbacks.get(s));e>=0&&this.activeToggleCallbacks.splice(e,1);for(const e of this.activeToggleCallbacks)e.toggle(!0)}else console.warn("No input callback for registered for key bind "+i.display())})},this.onMouseMove=e=>{if((Math.abs(e.movementX)>1||Math.abs(e.movementY)>1)&&this.setLastActiveDevice("kbm"),this.view.paused)return;if(!d())return;const t=n.clamp(e.movementX,-50,50),s=n.clamp(e.movementY,-50,50);Math.abs(t)>200||Math.abs(s)>200||this.mousebinds.forEach((e,i)=>{const n=this.inputs.get(i)??this.deltaCallbacks.get(i);if(null!=n)switch(e.axis){case"x":n(t*e.multiplier);break;case"y":n(s*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)})},this.onTouchStart=e=>{if(this.setLastActiveDevice("kbm"),!this.view.paused){for(let t=0;t<=e.touches.length;t++){const s=e.touches[t];if(s?.target instanceof HTMLCanvasElement)return void(this.prevTouchEvent=s)}e.preventDefault()}},this.onTouchMove=e=>{if(this.view.paused)return;if(null==this.prevTouchEvent)return;let t=null;for(let s=0;s<=e.touches.length;s++){const i=e.touches[s];if(i&&i.target instanceof HTMLCanvasElement&&i.identifier===this.prevTouchEvent.identifier){t=i;break}}null!=t&&(this.touchmoveBinds.forEach((e,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);if(null!=i)switch(e.axis){case"x":i((t.clientX-this.prevTouchEvent.clientX)*e.multiplier);break;case"y":i((t.clientY-this.prevTouchEvent.clientY)*e.multiplier)}else console.warn("No input callback for registered for mouse bind "+e.axis)}),this.prevTouchEvent=t,e.preventDefault())},this.onTouchEnd=e=>{this.prevTouchEvent=null,e.preventDefault()},this.onWheel=e=>{this.setLastActiveDevice("kbm"),this.view.paused||this.wheelbinds.forEach((t,s)=>{const i=this.inputs.get(s)??this.deltaCallbacks.get(s);null!=i?i(e.deltaY*t.multiplier):console.warn("No input callback for registered for wheel bind")})},this.onFocusLost=()=>this.stopVibration(),this.onVisibilityChanged=()=>{document.hidden&&this.stopVibration()},this.onGamepadDisconnected=e=>{e.gamepad.index===this.activeGamepadIndex&&(this.stopVibration(),this.activeGamepadIndex=void 0)}}getLastActiveDevice(){return this.lastActiveDevice}suppressHeldGamepadButtonsUntilRelease(){const e=navigator.getGamepads();this.sampleGamepadButtonsFrom(e,!1);for(let t=0;t<e.length;t++){const s=e[t];if(!s||"standard"!==s.mapping)continue;const i=this.suppressedGamepadButtons.get(t),n=this.pendingGamepadButtonTransitions.get(t),a=this.prevGamepadButtonStates.get(t),o=this.frameGamepadButtonTransitions.get(t);for(let e=0;e<s.buttons.length;e++)s.buttons[e].pressed&&(i[e]=!0),n[e]=0,a[e]=!1,o[e]=0}}setLastActiveDevice(e,t){"gamepad"===e&&this.activeGamepadIndex===t||this.stopVibration(),this.activeGamepadIndex=t,this.lastActiveDevice!==e&&(this.lastActiveDevice=e,this.onDeviceChanged.next(e))}start(){this.pauseSubscription?.unsubscribe(),this.pauseSubscription=this.view.pausedChanged.subscribe(e=>{e&&this.stopVibration()}),window.addEventListener("blur",this.onFocusLost),window.addEventListener("gamepaddisconnected",this.onGamepadDisconnected),document.addEventListener("visibilitychange",this.onVisibilityChanged),document.addEventListener("keydown",this.onKeyDown),document.addEventListener("mousedown",this.onKeyDown),document.addEventListener("mouseup",this.onKeyUp),document.addEventListener("keyup",this.onKeyUp),document.addEventListener("mousemove",this.onMouseMove),this.view.htmlElement.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.view.htmlElement.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.view.htmlElement.addEventListener("touchend",this.onTouchEnd,{passive:!1}),document.addEventListener("wheel",this.onWheel)}stop(){this.stopVibration(),this.activeGamepadIndex=void 0,this.pauseSubscription?.unsubscribe(),this.pauseSubscription=void 0,window.removeEventListener("blur",this.onFocusLost),window.removeEventListener("gamepaddisconnected",this.onGamepadDisconnected),document.removeEventListener("visibilitychange",this.onVisibilityChanged),document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("mousedown",this.onKeyDown),document.removeEventListener("mouseup",this.onKeyUp),document.removeEventListener("keyup",this.onKeyUp),document.removeEventListener("mousemove",this.onMouseMove),this.view.htmlElement.removeEventListener("touchstart",this.onTouchStart),this.view.htmlElement.removeEventListener("touchmove",this.onTouchMove),this.view.htmlElement.removeEventListener("touchend",this.onTouchEnd),document.removeEventListener("wheel",this.onWheel)}sampleGamepadButtons(e=!1){this.sampleGamepadButtonsFrom(navigator.getGamepads(),e)}sampleGamepadButtonsFrom(e,t){for(let s=0;s<e.length;s++){const i=e[s];if(!i||"standard"!==i.mapping)continue;let n=this.sampledGamepadButtonStates.get(s);null==n&&(n=new Array(i.buttons.length).fill(!1),this.sampledGamepadButtonStates.set(s,n),this.pendingGamepadButtonTransitions.set(s,new Array(i.buttons.length).fill(0)),this.frameGamepadButtonTransitions.set(s,new Array(i.buttons.length).fill(0)),this.prevGamepadButtonStates.set(s,new Array(i.buttons.length).fill(!1)),this.suppressedGamepadButtons.set(s,new Array(i.buttons.length).fill(!1)));const a=this.pendingGamepadButtonTransitions.get(s),o=this.suppressedGamepadButtons.get(s),h=this.prevGamepadButtonStates.get(s);for(let e=0;e<i.buttons.length;e++){const s=i.buttons[e].pressed;t?(a[e]=h[e]?1:0,s&&(o[e]=!0)):o[e]||s===n[e]||a[e]++,o[e]&&!s&&(o[e]=!1,a[e]=h[e]?1:0),n[e]=s}}}update(e){if(this.view.paused)return;const t=navigator.getGamepads();this.sampleGamepadButtonsFrom(t,!1);for(let e=0;e<t.length;e++){const s=t[e];if(!s||"standard"!==s.mapping)continue;const i=this.prevGamepadButtonStates.get(e),n=this.suppressedGamepadButtons.get(e),a=this.pendingGamepadButtonTransitions.get(e),o=this.frameGamepadButtonTransitions.get(e);for(let e=0;e<s.buttons.length;e++){o[e]=0===a[e]?0:i[e]?a[e]>1?3:2:1;const t=o[e];0!==t&&(i[e]=!!(1&t),a[e]-=3===t?2:1)}this.gamepadButtonBinds.forEach((t,a)=>{for(const h of t){const t=h.button,d=s.buttons[t];if(!d)continue;const l=d.pressed,c=d.value,r=o[t],u=0===r?i[t]:!!(2&r);if(n[t]&&2!==r)continue;if(0!==r){this.setLastActiveDevice("gamepad",e);const s=this.toggleCallbacks.get(a);s&&(2&r&&s(!1),1&o[t]&&!n[t]&&s(!0))}if(n[t])continue;const p=this.inputs.get(a)??this.deltaCallbacks.get(a);p&&(c>0||l||u&&0===c)&&"gamepad"===this.lastActiveDevice&&p(c)}}),this.gamepadAxisBinds.forEach((t,i)=>{for(const n of t){let t=s.axes[n.axis];if(t=Math.abs(t)<n.deadzone?0:(t-Math.sign(t)*n.deadzone)/(1-n.deadzone),0!==t&&this.setLastActiveDevice("gamepad",e),"gamepad"!==this.lastActiveDevice)break;t*=n.multiplier;const a=this.inputs.get(i)??this.deltaCallbacks.get(i);a&&a(t)}})}}bind(e,t){this.inputs.set(e,t)}bindToggle(e,t){this.toggleCallbacks.set(e,t)}bindDelta(e,t){this.deltaCallbacks.set(e,t)}unbind(e){this.inputs.delete(e),this.toggleCallbacks.delete(e),this.deltaCallbacks.delete(e)}setKeybind(e,t){this.keybinds.has(e)||this.keybinds.set(e,[]),this.keybinds.get(e).push(t)}setMousebind(e,t){this.mousebinds.set(e,t)}setTouchMoveBind(e,t){this.touchmoveBinds.set(e,t)}setWheelbind(e,t){this.wheelbinds.set(e,t)}setGamepadButtonBind(e,t){this.gamepadButtonBinds.has(e)||this.gamepadButtonBinds.set(e,[]),this.gamepadButtonBinds.get(e).push(t)}setGamepadAxisBind(e,t){this.gamepadAxisBinds.has(e)||this.gamepadAxisBinds.set(e,[]),this.gamepadAxisBinds.get(e).push(t)}removeKeybind(e){this.keybinds.delete(e)}removeMousebind(e){this.mousebinds.delete(e)}removeWheelbind(e){this.wheelbinds.delete(e)}removeGamepadButtonBind(e){this.gamepadButtonBinds.delete(e)}removeGamepadAxisBind(e){this.gamepadAxisBinds.delete(e)}vibrate(e,t=1,s=1){if("gamepad"!==this.lastActiveDevice||null==this.activeGamepadIndex||this.view.paused||document.hidden||!document.hasFocus()||!Number.isFinite(e)||e<=0||!Number.isFinite(t)||!Number.isFinite(s))return!1;try{const i=navigator.getGamepads()[this.activeGamepadIndex],a=i?.connected?i.vibrationActuator:void 0;return!!a?.playEffect&&(this.vibrationActuator=a,a.playEffect("dual-rumble",{startDelay:0,duration:e,weakMagnitude:n.clamp(s,0,1),strongMagnitude:n.clamp(t,0,1)}).catch(h),!0)}catch{return!1}}stopVibration(){const e=this.vibrationActuator;this.vibrationActuator=void 0;try{e?.reset().catch(h)}catch{}}};o=e([t()],o);export{o as InputService};function h(){}function d(){return null!=document.pointerLockElement||null!=document.mozPointerLockElement}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -59,6 +59,8 @@ export interface RayTestOptions {
|
|
|
59
59
|
resolveActor?: boolean;
|
|
60
60
|
}
|
|
61
61
|
interface ShapeCastOptions {
|
|
62
|
+
/** Allow exiting an initial overlap when false. Defaults to true. */
|
|
63
|
+
stopAtPenetration?: boolean;
|
|
62
64
|
collisionFilter?: InteractionGroups;
|
|
63
65
|
excludeActor?: BaseActor;
|
|
64
66
|
excludeTriggers?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t,__metadata as e}from"tslib";import{createRapierCollisionShape as i}from"../../../scene/collision/rapier-shape.js";import*as s from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as o}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as n,distinctUntilChanged as r,filter as a,map as l,Subject as c,takeUntil as d}from"rxjs";import*as h from"three";import{ArrowHelper as u,BufferAttribute as p,BufferGeometry as y,Group as g,LineSegments as m,Matrix4 as b,Object3D as w,Quaternion as f,Raycaster as v,Scene as x,Vector3 as B}from"three";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{ConvexPolyhedronCollisionShape as R,PhysicalShapeMesh as E,toInstancedCollisionShape as M}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as T}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as P,LandscapeMesh as z}from"../../../scene/landscape/landscape.js";import{ViewController as F}from"../render.js";import{World as j}from"../world.js";import{AbstractPhysicsSystem as I}from"./abstract-physics-system.js";import{NetRole as _}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const N=new B,W=new B,O=new f,L=new f,k=new f;let V=class extends I{isLandscapeNavigationCollider(t){return this.colliderObjects.get(t)?.object instanceof z}forEachStaticActorNavigationCollider(t,e){const i=this.actorBodies.get(t.id);if(i?.isFixed()&&i.isEnabled()&&!0!==i.userData?.ignoreForNavMesh)for(let t=0;t<i.numColliders();t++){const s=i.collider(t);s.isEnabled()&&!s.isSensor()&&e(s)}}set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.colliderObjects=new WeakMap,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new c,this.beforeStep=new c,this.afterStep=new c,this.shouldRenderDebug=!1,this.viewController=C(F),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new v,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(N),i=t.getSize(W),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,O,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,O,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,O)&&o.push(n)}return o}createDebugMesh(){const t=new m(new y,new h.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new p(t,3);o.setUsage(h.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(o.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(o.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await nt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!this._isStopped){t=Math.min(.04,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===_.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.lastEmptyPhysicsWorld=void 0,this.world.timestep=0,this.world.step()}updatePhysics(t){if(this._isStopped)return;this.world.timestep=t;const e=0===this.world.bodies.len()&&0===this.world.colliders.len();e&&this.lastEmptyPhysicsWorld===this.world||this.world.step(this.eventQueue),this.lastEmptyPhysicsWorld=e?this.world:void 0,this.eventQueue.drainCollisionEvents(this.handleCollisionEvent)}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(et,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult),i.hasHit=!1,i.actor=void 0,i.object=void 0,i.instanceId=void 0,i.batchId=void 0;const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==yt&&(yt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),rt(yt.origin,t),rt(yt.dir,r);const l=this.world.castRayAndGetNormal(yt,a,!1,s?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit){const e=this.colliderObjects.get(l.collider);if(i.object=e?.object,i.instanceId=e?.instanceId,i.batchId=e?.batchId,i._internal=l,lt(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==s?.resolveActor){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}}return this.showDebug&&!1!==s?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,s?.debugColor,s?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new u(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return X.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ct(t,t=>t.setActiveEvents(s.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof E&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof T){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof P?this.addLandscapeGroup(t):(t instanceof g||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new b;if(t instanceof h.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof T&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new w;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);const d=this.createStaticBody(c,l),h={object:t,batchId:n};ct(d,t=>this.colliderObjects.set(t,h))}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new w;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);const n=this.createStaticBody(o,s),r={object:t,instanceId:e};ct(n,t=>this.colliderObjects.set(t,r))}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>M(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,s=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,o.EXCLUDE_SENSORS,s,void 0);const a=e.computedMovement();return lt(dt,a),dt}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(pt)??q,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),J.set(0,s,0).multiply(r),rt(H,J),n.setTranslationWrtParent(H),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,s,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(pt)??q,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,s*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(k)??O;J.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(J,u,h,o.EXCLUDE_SENSORS,r??void 0,void 0,a,ut)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,s=null){const n=t.collider;e.computeColliderMovement(n,i,o.EXCLUDE_SENSORS,s,void 0);const r=e.computedMovement();return lt(dt,r),dt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(H);s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(U),s=e.getWorldQuaternion(K);t.setNextKinematicTranslation(it(i)),t.setNextKinematicRotation(st(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setAngvel(H,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setLinvel(H,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(it(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setRotation(st(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,i=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(l,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=i.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=s.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(h,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);ht.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),ct(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),G(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.addTorque(H,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyTorqueImpulse(H,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.addForce(H,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyImpulse(H,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s?.addForce(H,!0):(rt(Q,i),s?.addForceAtPoint(H,Q,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s.applyImpulse(H,!0):(rt(Q,i),s.applyImpulseAtPoint(H,Q,!0))}applyRadialImpulse(t,e,i){return e<=0||0===i?0:this.applyImpulseToBodiesInRadius(t,e,(t,s,o)=>{o<=1e-6?s.set(0,1,0):s.multiplyScalar(1/o),s.multiplyScalar(i*Math.max(0,1-o/e)),rt(H,s),t.applyImpulse(H,!0)})}applyDirectionalImpulse(t,e,i,s,o){if(i<=0||0===o||e.lengthSq()<=1e-12)return 0;Y.copy(e).normalize();const n=Math.cos(Math.max(0,Math.min(Math.PI,s)));return this.applyImpulseToBodiesInRadius(t,i,(t,e,i)=>{if(i>1e-6&&e.multiplyScalar(1/i).dot(Y)<n)return!1;H.x=Y.x*o,H.y=Y.y*o,H.z=Y.z*o,t.applyImpulse(H,!0)})}applyImpulseToBodiesInRadius(t,e,i){const s=$,n=tt;s.clear(),n.length=0;let r=0;this.world.intersectionsWithShape(t,O,this.getBallShape(e),t=>{const e=t.parent();return null==e||s.has(e.handle)||(s.add(e.handle),n.push(e)),!0},o.ONLY_DYNAMIC|o.EXCLUDE_SENSORS);for(const e of n)lt(Z,e.worldCom()),Z.sub(t),!1!==i(e,Z,Z.length())&&r++;return s.clear(),n.length=0,r}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof P){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(({started:t})=>t===i),l(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),a(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),l(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>!t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new n(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(r())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(G(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,s,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);H.x=i.x,H.y=i.y,H.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,O,H,a,.01,s,!0,r?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){lt(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return lt(s.hitPoint,u.witness1),mt(t.rotation(),u.normal1,s.normal,L),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,i){const o=i?.type===PhysicsBodyType.dynamic?s.RigidBodyDesc.dynamic():s.RigidBodyDesc.fixed(),n=this.world.createRigidBody(o);i?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);let r=0;for(const s of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==s){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,s,t);null!=o&&(null!=i?.friction&&o.setFriction(i.friction),null!=i?.density&&o.setDensity(i.density),null!=i?.mass&&o.setMass(i.mass/e.length),null!=i?.restitution&&o.setRestitution(i.restitution))}return G(n,t),n.userData=t.uuid,n.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(pt)??q,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);rt(o.translation,n);const r=(new f).setFromEuler(e.rotation);at(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{const s=this.world.createCollider(o,t),n=i??(e instanceof R&&e.mesh instanceof w?e.mesh:void 0);return null!=n&&this.colliderObjects.set(s,{object:n}),s}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=s.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=s.MassPropsMode.Mass)}createShape(t,e){return i(this.rapier,t,e)}createCharacterCollision(){return new this.rapier.CharacterCollision}};V=t([D(),e("design:paramtypes",[])],V);export{V as PhysicsSystem};const U=new B,K=new h.Quaternion;function G(t,e){const i=e.getWorldPosition(U),s=e.getWorldQuaternion(K);t.setTranslation(it(i),!1),t.setRotation(st(s),!1)}const X=new B,q=new B(1,1,1),H=new s.Vector3(0,0,0),Q=new s.Vector3(0,0,0),J=new B,Y=new B,Z=new B,$=new Set,tt=[],et=new h.Vector2;function it(t){return rt(H,t),H}function st(t){return at(L,t),L}let ot=null;const nt=async()=>(null==ot&&(ot=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ot);function rt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function at(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const dt=new B,ht=new WeakMap,ut=t=>ht.get(t)??!0,pt=new B;let yt,gt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(V),this.world=C(j)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};gt=t([A()],gt);export{extractFloat32Array}from"../../../scene/collision/rapier-shape.js";function mt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new c,this.onBeginOverlapActor=new c,this.onEndOverlapActor=new c}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return s.RigidBodyType.Dynamic;case PhysicsBodyType.static:return s.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return s.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return s.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
|
|
1
|
+
import{__decorate as t,__metadata as e}from"tslib";import{createRapierCollisionShape as i}from"../../../scene/collision/rapier-shape.js";import*as s from"@dimforge/rapier3d-simd-compat";import{QueryFilterFlags as o}from"@dimforge/rapier3d-simd-compat";import{BehaviorSubject as n,distinctUntilChanged as r,filter as a,map as l,Subject as c,takeUntil as d}from"rxjs";import*as h from"three";import{ArrowHelper as u,BufferAttribute as p,BufferGeometry as y,Group as g,LineSegments as m,Matrix4 as b,Object3D as w,Quaternion as f,Raycaster as v,Scene as x,Vector3 as B}from"three";import{Service as D}from"typedi";import{ActorComponent as S,Component as A}from"../../../gameplay/actors/component.js";import{inject as C}from"../../../gameplay/inject.js";import{ConvexPolyhedronCollisionShape as R,PhysicalShapeMesh as E,toInstancedCollisionShape as M}from"../../../scene/collision/collision-shape.js";import{AssetMeshInstance as T}from"../../../scene/asset-resource-loader.js";import{LandscapeGroup as P,LandscapeMesh as z}from"../../../scene/landscape/landscape.js";import{ViewController as F}from"../render.js";import{World as j}from"../world.js";import{AbstractPhysicsSystem as I}from"./abstract-physics-system.js";import{NetRole as _}from"../../net/index.js";export{ActorComponent,attach,Attach,Component}from"../../actors/component.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}export class ShapeCastResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.normal=new B}reset(){this.actor=void 0,this.hasHit=!1,this.distance=0,this.hitPoint.set(0,0,0),this.normal.set(0,0,0)}}ShapeCastResult.shared=new ShapeCastResult;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));const N=new B,W=new B,O=new f,L=new f,k=new f;let V=class extends I{isLandscapeNavigationCollider(t){return this.colliderObjects.get(t)?.object instanceof z}forEachStaticActorNavigationCollider(t,e){const i=this.actorBodies.get(t.id);if(i?.isFixed()&&i.isEnabled()&&!0!==i.userData?.ignoreForNavMesh)for(let t=0;t<i.numColliders();t++){const s=i.collider(t);s.isEnabled()&&!s.isSensor()&&e(s)}}set showDebug(t){this.shouldRenderDebug=t,t||this.clearRayDebugArrows(),this.debugMesh&&(this.debugMesh.visible=t),this.staticDebugMesh&&(this.staticDebugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(){super(),this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.colliders=new Map,this.colliderObjects=new WeakMap,this.rayDebugArrowPool=[],this.activeRayDebugArrows=[],this.nonFixedBodies=new Set,this.collisionEvents=new c,this.beforeStep=new c,this.afterStep=new c,this.shouldRenderDebug=!1,this.viewController=C(F),this.shapeCacheBox=new Map,this.shapeCacheBall=new Map,this.staticDebugNeedsUpdate=!0,this.invalidateStaticDebug=()=>{this.staticDebugNeedsUpdate=!0},this.handleCollisionEvent=(t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})},this._raycaster=new v,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this._isStopped=!1,this.ready=this.setup()}getBallShape(t){let e=this.shapeCacheBall.get(t);return null==e&&(e=new this.rapier.Ball(t),this.shapeCacheBall.set(t,e)),e}getBoxShape(t,e,i){const s=t+1e6*e+1e12*i;let o=this.shapeCacheBox.get(s);return null==o&&(o=new this.rapier.Cuboid(t,e,i),this.shapeCacheBox.set(s,o)),o}hasBoxIntersection(t){const e=t.getCenter(N),i=t.getSize(W),s=this.getBoxShape(i.x/2,i.y/2,i.z/2);return null!=this.world.intersectionWithShape(e,O,s)}hasSphereIntersection(t){const e=this.getBallShape(t.radius);return null!=this.world.intersectionWithShape(t.center,O,e)}findActorsInRadius(t,e,i){const s=this.getBallShape(e),o=[];for(const[e,n]of this.bodyActors)if(null==i||n instanceof i)for(let i=0,r=e.numColliders();i<r;i++){e.collider(i).intersectsShape(s,t,O)&&o.push(n)}return o}createDebugMesh(){const t=new m(new y,new h.LineBasicMaterial({color:255}));return t.frustumCulled=!1,t}updateDebugMesh(t,e){const i=t.geometry,s=i.getAttribute("position");if(null==s||s.array.length<e.length){null!=s&&i.dispose();const t=new Float32Array(e.length);t.set(e);const o=new p(t,3);o.setUsage(h.DynamicDrawUsage),i.setAttribute("position",o)}else e.length>0&&(s.array.set(e),s.clearUpdateRanges(),s.addUpdateRange(0,e.length),s.needsUpdate=!0);i.setDrawRange(0,e.length/3)}async start(){return await this.ready,this.handleTick(),this.handleCollisionEvents(),this.ready}handleCollisionEvents(){this.collisionSub=this.collisionEvents.subscribe(t=>{const e=this.colliders.get(t.handle1);if(null==e)return;const i=this.world.getCollider(t.handle2);if(null==i||null==i.parent())return;const s=this.bodyActors.get(i.parent());null!=s&&(t.started?e.onBeginOverlapActor.next({actor:s}):e.onEndOverlapActor.next({actor:s}))})}renderDebug(){if(null==this.scene)return;if(null==this.staticDebugMesh&&(this.staticDebugMesh=this.createDebugMesh(),this.staticDebugMesh.visible=this.shouldRenderDebug,this.staticDebugMesh.raycast=function(){},this.scene.add(this.staticDebugMesh)),null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.scene.add(this.debugMesh)),this.staticDebugNeedsUpdate){const t=this.world.debugRender(o.ONLY_FIXED);this.updateDebugMesh(this.staticDebugMesh,t.vertices),this.staticDebugNeedsUpdate=!1}const t=this.world.debugRender(o.EXCLUDE_FIXED);this.updateDebugMesh(this.debugMesh,t.vertices)}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await nt(),this.eventQueue=new this.rapier.EventQueue(!0),this.setupWorld()}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe(t=>{if(!(this._isStopped||t<=0)){t=Math.min(.04,t),this.beforeStep.next(t),this.updatePhysics(t),this.showDebug&&this.renderDebug(),this.releaseExpiredRayDebugArrows();for(const t of this.nonFixedBodies){let e,i=this.staticMeshes.get(t);if(null==i){if(e=this.bodyActors.get(t),e?.netRole===_.simulatedProxy)continue;i=e?.object}null!=i&&i.parent instanceof x&&(t.translation(i.position),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(e?.id))&&t.rotation(i.quaternion),i.matrixWorldNeedsUpdate=!0)}this.afterStep.next(t)}})}_updateWorld(){this.lastEmptyPhysicsWorld=void 0,this.world.timestep=0,this.world.step()}updatePhysics(t){if(this._isStopped)return;this.world.timestep=t;const e=0===this.world.bodies.len()&&0===this.world.colliders.len();e&&this.lastEmptyPhysicsWorld===this.world||this.world.step(this.eventQueue),this.lastEmptyPhysicsWorld=e?this.world:void 0,this.eventQueue.drainCollisionEvents(this.handleCollisionEvent)}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(et,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,s){null==i&&(i=this._reusableResult),i.hasHit=!1,i.actor=void 0,i.object=void 0,i.instanceId=void 0,i.batchId=void 0;const n=this._raytestDiff,r=this._raytestDirection;n.subVectors(e,t);const a=n.length();if(0===a)return console.warn("Ray test called with to and from being equal"),i;r.copy(n).multiplyScalar(1/a),null==yt&&(yt=new this.rapier.Ray(new this.rapier.Vector3(0,0,0),new this.rapier.Vector3(0,1,0))),rt(yt.origin,t),rt(yt.dir,r);const l=this.world.castRayAndGetNormal(yt,a,!1,s?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,s?.collisionFilter,void 0,null!=s?.excludeActor?this.actorBodies.get(s.excludeActor.id):void 0);if(i.hasHit=null!=l,i.actor=void 0,i.hasHit){const e=this.colliderObjects.get(l.collider);if(i.object=e?.object,i.instanceId=e?.instanceId,i.batchId=e?.batchId,i._internal=l,lt(i.hitNormal,l.normal),i.hitPoint.copy(t).addScaledVector(r,l.timeOfImpact),i.distance=l.timeOfImpact,!1!==s?.resolveActor){const t=l.collider.parent();i.actor=null!=t?this.bodyActors.get(t):null}}return this.showDebug&&!1!==s?.debug&&null!=this.scene&&this.drawRayDebugArrow(r,t,a,s?.debugColor,s?.debugLifetime),i}drawRayDebugArrow(t,e,i,s=255,o=200){let n=this.rayDebugArrowPool.pop();null==n?n=new u(t,e,i,s,.2,.1):(n.setDirection(t),n.position.copy(e),n.setLength(i,.2,.1),n.setColor(s)),n.userData.physicsRayDebugExpiresAt=performance.now()+o,this.activeRayDebugArrows.push(n),this.scene.add(n)}releaseExpiredRayDebugArrows(){if(0===this.activeRayDebugArrows.length)return;const t=performance.now();let e=0;for(let i=0;i<this.activeRayDebugArrows.length;i++){const s=this.activeRayDebugArrows[i];s.userData.physicsRayDebugExpiresAt<=t?(s.removeFromParent(),this.rayDebugArrowPool.push(s)):this.activeRayDebugArrows[e++]=s}this.activeRayDebugArrows.length=e}clearRayDebugArrows(){for(const t of this.activeRayDebugArrows)t.removeFromParent(),this.rayDebugArrowPool.push(t);this.activeRayDebugArrows.length=0}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return X.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())ct(t,t=>t.setActiveEvents(s.ActiveEvents.COLLISION_EVENTS))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof E&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof T){const e=!1!==t.userData?.src?.collisionDetection;if(t.children[0]&&(t.children[0].instanceMatrix&&e||t.children[0].isBatchedMesh))this.createForInstancedMesh(t.children[0],t.collisionShapes);else if(e&&t.children.length>0){const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}0===t.children.length&&(t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1)}else t instanceof P?this.addLandscapeGroup(t):(t instanceof g||t instanceof x)&&t.children.forEach(t=>this.addRecursively(t))}createForInstancedMesh(t,e){const i=new b;if(t instanceof h.BatchedMesh){const e=t._instanceInfo??t._drawInfo,s=new Map,o=t.userData.collisionMatrices;for(let n=0;n<e.length;n++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[n])continue;const e=t.userData.collisionShapes;let r=e?.[n];if(null==r&&null==e&&t.parent instanceof T&&(r=t.parent.collisionShapes),null==r)continue;const a=o?.[n];let l=r;null==a&&(l=s.get(r),null==l&&(l=this.instancedShapeReset(r),s.set(r,l)));const c=new w;c.matrix.identity(),null!=a?i.copy(a):t.getMatrixAt(n,i),c.applyMatrix4(i);const d=this.createStaticBody(c,l),h={object:t,batchId:n};ct(d,t=>this.colliderObjects.set(t,h))}}else{const s=this.instancedShapeReset(e);for(let e=0;e<t.count;e++){if(null!=t.userData.hasCollision&&!t.userData.hasCollision[e])continue;const o=new w;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*e),o.applyMatrix4(i);const n=this.createStaticBody(o,s),r={object:t,instanceId:e};ct(n,t=>this.colliderObjects.set(t,r))}}}instancedShapeReset(t){return t.filter(t=>null!=t).map(t=>M(t))}getCharacterController(t){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i,s=null){const n=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=n.collider(0);e.computeColliderMovement(r,i,o.EXCLUDE_SENSORS,s,void 0);const a=e.computedMovement();return lt(dt,a),dt}setActorCapsuleCollider(t,e,i,s){const o=this.actorBodies.get(t.id),n=o?.collider(0);if(null==o||null==n)return!1;const r=t.object?.getWorldScale(pt)??q,a=Math.max(0,e*Math.abs(r.y)),l=Math.max(.001,i*Math.max(Math.abs(r.x),Math.abs(r.z)));return n.setHalfHeight(a/2),n.setRadius(l),J.set(0,s,0).multiply(r),rt(H,J),n.setTranslationWrtParent(H),o.recomputeMassPropertiesFromColliders(),o.isFixed()&&this.invalidateStaticDebug(),!0}hasActorCapsuleIntersection(t,e,i,s,n,r=null){const a=this.actorBodies.get(t.id),l=t.object?.getWorldScale(pt)??q,c=Math.max(0,i*Math.abs(l.y)),d=Math.max(.001,s*Math.max(Math.abs(l.x),Math.abs(l.z))),h=new this.rapier.Capsule(c/2,d),u=t.object?.getWorldQuaternion(k)??O;J.set(0,n,0).multiply(l).applyQuaternion(u).add(e);return null!=this.world.intersectionWithShape(J,u,h,o.EXCLUDE_SENSORS,r??void 0,void 0,a,ut)}createCollider(t,e){const i=this.addShape(e?.body,t),s=new PhysicsCollider(i,this.world,this.invalidateStaticDebug);return this.colliders.set(i.handle,s),(null==e||e.body.isFixed())&&this.invalidateStaticDebug(),s.disposed.subscribe(()=>{this.colliders.delete(i.handle)}),s}createBody(t=PhysicsBodyType.dynamic,e={}){const i=(()=>{switch(t){case PhysicsBodyType.dynamic:return this.rapier.RigidBodyDesc.dynamic();case PhysicsBodyType.static:return this.rapier.RigidBodyDesc.fixed();case PhysicsBodyType.kinematic:return this.rapier.RigidBodyDesc.kinematicPositionBased();case PhysicsBodyType.kinematicVelocityBased:return this.rapier.RigidBodyDesc.kinematicVelocityBased();default:return this.rapier.RigidBodyDesc.dynamic()}})();e.position&&i.setTranslation(e.position.x,e.position.y,e.position.z),e.rotation&&i.setRotation({x:e.rotation.x,y:e.rotation.y,z:e.rotation.z,w:e.rotation.w}),"boolean"==typeof e.canSleep&&i.setCanSleep(e.canSleep),"boolean"==typeof e.ccdEnabled&&i.setCcdEnabled(e.ccdEnabled),"number"==typeof e.gravityScale&&i.setGravityScale(e.gravityScale),"number"==typeof e.mass&&i.setAdditionalMass(e.mass),void 0!==e.userData&&(i.userData=e.userData);const s=this.world.createRigidBody(i);return s.isFixed()?this.invalidateStaticDebug():this.nonFixedBodies.add(s),new PhysicsBody(s,this.world,this.invalidateStaticDebug)}createJoint(t,e,i){let s,o;switch(i.type){case"fixed":s=this.rapier.JointData.fixed(i.anchor1,i.frame1,i.anchor2,i.frame2);break;case"spherical":s=this.rapier.JointData.spherical(i.anchor1,i.anchor2);break;case"revolute":s=this.rapier.JointData.revolute(i.anchor1,i.anchor2,i.axis),null!=i.limits&&(o=i.limits)}const n=this.world.createImpulseJoint(s,t.body,e.body,!0);if(null!=o){n.setLimits(o[0],o[1])}return n.setContactsEnabled(i.contactsEnabled??!1),new PhysicsJoint(n,this.world)}getCharacterComputedMovement(t,e,i,s=null){const n=t.collider;e.computeColliderMovement(n,i,o.EXCLUDE_SENSORS,s,void 0);const r=e.computedMovement();return lt(dt,r),dt}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation(H);s.x+=e.x,s.y+=e.y,s.z+=e.z,i?.setNextKinematicTranslation(s)}setNextKinematicPosition(t,e){this.actorBodies.get(t.id).setNextKinematicTranslation(e)}setNextKinematicRotation(t,e){this.actorBodies.get(t.id).setNextKinematicRotation(e)}setNextKinematicTransform(t){!function(t,e){const i=e.getWorldPosition(U),s=e.getWorldQuaternion(K);t.setNextKinematicTranslation(it(i)),t.setNextKinematicRotation(st(s))}(this.actorBodies.get(t.id),t.object)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setAngvel(H,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.setLinvel(H,!0)}getLinearVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.linvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}getAngularVelocity(t,e=new B){const i=this.actorBodies.get(t.id);if(null==i)return e.set(0,0,0);const s=i.angvel();return e.x=s.x,e.y=s.y,e.z=s.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);i?.setLinearDamping(e)}getLienarDamping(t){const e=this.actorBodies.get(t.id);return e?.linearDamping()??0}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}getAngularDamping(t){const e=this.actorBodies.get(t.id);e?.angularDamping()}setPosition(t,e){const i=this.actorBodies.get(t.id);i?.setTranslation(it(e),!1)}getPosition(t,e=new B){const i=this.actorBodies.get(t.id);i&&i.translation(e)}setRotation(t,e){const i=this.actorBodies.get(t.id);i?.setRotation(st(e),!1)}getRotation(t,e=new f){const i=this.actorBodies.get(t.id);i&&function(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}(e,i.rotation())}lockTranslations(t,e){const i=this.actorBodies.get(t.id);i?.lockTranslations(e,!1)}lockRotations(t,e){const i=this.actorBodies.get(t.id);i?.lockRotations(e,!1)}setEnabledTranslations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledTranslations(e,i,s,!1)}setEnabledRotations(t,e,i,s){const o=this.actorBodies.get(t.id);o?.setEnabledRotations(e,i,s,!1)}addLandscapeGroup(t){this.invalidateStaticDebug();const e=t.userData.src,i=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));var o=n.getWorldPosition(new B);if(e.landscape.holes&&e.landscape.holes.some(t=>t.m===n.name&&0!==t.w[0])){const t=n.geometry.clone(),i=n.scale,s=n.geometry.getAttribute("hole"),r=new Float32Array(t.getAttribute("position").array);for(let t=0;t<r.length;t+=3)r[t]*=i.x,r[t+1]*=i.y,r[t+2]*=i.z;const a=t.index;for(let t=0;t<a.count;t+=3){const e=s.getX(a.getX(t)),i=s.getX(a.getY(t)),o=s.getX(a.getZ(t));(e>.5||i>.5||o>.5)&&(a.setX(t,0),a.setY(t,0),a.setZ(t,0))}const l=this.rapier.ColliderDesc.trimesh(r,new Uint32Array(t.getIndex().array));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(l,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}continue}const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=i.find(t=>t.x===n.x&&t.y==n.y);if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const c=e.landscape.options.density,d=a.flatMap(t=>t.reverse()),h=s.ColliderDesc.heightfield(c,c,new Float32Array(d),new this.rapier.Vector3(r,r,r));if(!1!==e.collisionDetection){const t=this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed()),e=new this.rapier.Vector3(0,0,0);rt(e,o),t.setTranslation(e,!1);const i=this.world.createCollider(h,t);this.colliderObjects.set(i,{object:n}),this.staticBodies.set(n,t)}}}setEnabled(t,e){const i=this.actorBodies.get(t.id);i?.setEnabled(e),i?.isFixed()&&this.invalidateStaticDebug()}addActor(t,e,i={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const s=t.object;let o;switch(i.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:o=this.rapier.RigidBodyDesc.dynamic(),o.mass=i.mass??1;break;case PhysicsBodyType.kinematic:o=this.rapier.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:o=this.rapier.RigidBodyDesc.kinematicVelocityBased();break;default:o=i.isTrigger?this.rapier.RigidBodyDesc.kinematicVelocityBased():this.rapier.RigidBodyDesc.fixed()}const n=this.world.createRigidBody(o);n.enableCcd(1==i.continousCollisionDetection);for(const t of e){const e=this.addShape(n,t,s);ht.set(e,!i.isTrigger)}return i.type!==PhysicsBodyType.static&&this.nonFixedBodies.add(n),ct(n,t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(this.rapier.ActiveCollisionTypes.ALL),t.setActiveEvents(this.rapier.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.density&&t.setDensity(i.density),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)}),G(n,s),!0===i.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t),n.isFixed()&&this.invalidateStaticDebug(),new PhysicsBody(n,this.world,this.invalidateStaticDebug)}applyTorque(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.addTorque(H,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyTorqueImpulse(H,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.addForce(H,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);H.x=e.x,H.y=e.y,H.z=e.z,i?.applyImpulse(H,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s?.addForce(H,!0):(rt(Q,i),s?.addForceAtPoint(H,Q,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);rt(H,e),null==i?s.applyImpulse(H,!0):(rt(Q,i),s.applyImpulseAtPoint(H,Q,!0))}applyRadialImpulse(t,e,i){return e<=0||0===i?0:this.applyImpulseToBodiesInRadius(t,e,(t,s,o)=>{o<=1e-6?s.set(0,1,0):s.multiplyScalar(1/o),s.multiplyScalar(i*Math.max(0,1-o/e)),rt(H,s),t.applyImpulse(H,!0)})}applyDirectionalImpulse(t,e,i,s,o){if(i<=0||0===o||e.lengthSq()<=1e-12)return 0;Y.copy(e).normalize();const n=Math.cos(Math.max(0,Math.min(Math.PI,s)));return this.applyImpulseToBodiesInRadius(t,i,(t,e,i)=>{if(i>1e-6&&e.multiplyScalar(1/i).dot(Y)<n)return!1;H.x=Y.x*o,H.y=Y.y*o,H.z=Y.z*o,t.applyImpulse(H,!0)})}applyImpulseToBodiesInRadius(t,e,i){const s=$,n=tt;s.clear(),n.length=0;let r=0;this.world.intersectionsWithShape(t,O,this.getBallShape(e),t=>{const e=t.parent();return null==e||s.has(e.handle)||(s.add(e.handle),n.push(e)),!0},o.ONLY_DYNAMIC|o.EXCLUDE_SENSORS);for(const e of n)lt(Z,e.worldCom()),Z.sub(t),!1!==i(e,Z,Z.length())&&r++;return s.clear(),n.length=0,r}removeActor(t){if(null==t)return;this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(e.isFixed()&&this.invalidateStaticDebug(),this.bodyActors.delete(e),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.actorBodies.delete(t.id)}removeRemoved(t){if(null==t)return;const e=new Set;t.traverse(t=>{e.add(t.uuid)});for(const[t,i]of this.staticBodies.entries())e.has(t.uuid)&&this.world.getRigidBody(i.handle)&&(this.invalidateStaticDebug(),this.staticBodies.delete(t),this.world.removeRigidBody(i),this.nonFixedBodies.delete(i))}removeSceneObject(t){if(t instanceof P){for(const e of t.sections)this.removeSceneObject(e);return}let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&(this.invalidateStaticDebug(),this.world.removeRigidBody(e),this.nonFixedBodies.delete(e)),this.staticBodies.delete(t)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(({started:t})=>t===i),l(({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t)?.parent()),a2:this.bodyActors.get(this.world.getCollider(e)?.parent()),started:i})),a(({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s)),l(({a2:t})=>t))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(d(t.disposed),a(t=>!t.started),a(({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e)?.parent());return null!=i&&i.id===t.id}),l(t=>t.handle2))}onHasContactChanged(t){const e=new Set,i=new n(!1);return this.onBeginContact(t).subscribe(t=>{e.add(t),i.next(e.size>0)}),this.onEndContact(t).subscribe(t=>{e.delete(t),i.next(e.size>0)}),i.pipe(r())}onBeginOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!0)}onEndOverlap(t){return this._onCollisionWithActorEvent(t,()=>!0,!1)}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>i instanceof e,!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,(t,i)=>e.id===i.id,!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e&&(G(e,t.object),e.isFixed()&&this.invalidateStaticDebug())}flushModifiedBodyPositionsToColliders(){this.world.propagateModifiedBodyPositionsToColliders()}setupWorld(){const t=new this.rapier.World({x:0,y:-9.81,z:0});this.world=t,this.invalidateStaticDebug()}sphereCast(t,e,i,s,n=ShapeCastResult.shared,r){n.reset();const a=this.getBallShape(e);H.x=i.x,H.y=i.y,H.z=i.z;const l=r?.excludeActor?this.actorBodies.get(r.excludeActor.id):null,c=this.world.castShape(t,O,H,a,.01,s,r?.stopAtPenetration??!0,r?.excludeTriggers?o.EXCLUDE_SENSORS:void 0,r?.collisionFilter??void 0,null,l);if(null!=c){lt(n.hitPoint,c.witness1),n.normal.set(c.normal1.x,c.normal1.y,c.normal1.z),n.distance=c.time_of_impact,n.hasHit=!0;const t=c.collider.parent();if(t){const e=this.bodyActors.get(t);e&&(n.actor=e)}}return n}castActorShape(t,e,i,s=ShapeCastResult.shared,o=void 0){s.reset();const n=this.actorBodies.get(t.id);if(n&&n.numColliders()>0){for(let t=0;t<n.numColliders();t++){const r=n.collider(t);let a=r.shape,l=r.translation(),c=r.rotation(),d=e,h=i;const u=this.world.castShape(l,c,d,a,.01,h,!0,null,o,null,n,void 0);if(null!=u){u.collider;const t=r;return lt(s.hitPoint,u.witness1),mt(t.rotation(),u.normal1,s.normal,L),s.distance=u.time_of_impact,s.actor=this.bodyActors.get(u.collider.parent()),s.hasHit=!0,s}}return s}return console.warn("Actor is not added to the physics system"),s}stop(){if(!this._isStopped){this._isStopped=!0,this.bodyActors.clear(),this.actorBodies.clear(),this.staticBodies.clear(),this.staticMeshes.clear(),this.colliders.clear(),this.fixedupdateSub?.unsubscribe(),this.collisionSub?.unsubscribe(),this.world?.bodies.forEach(t=>{this.world.removeRigidBody(t),this.nonFixedBodies.delete(t)});try{this.eventQueue?.free()}catch(t){console.warn("Error when freeing physics event queue",t)}try{this.world?.free(),this.world=void 0}catch(t){console.warn("Error while freeing physics world",t)}this.clearRayDebugArrows();for(const t of this.rayDebugArrowPool)t.dispose();this.rayDebugArrowPool.length=0}}createStaticBody(t,e,i){const o=i?.type===PhysicsBodyType.dynamic?s.RigidBodyDesc.dynamic():s.RigidBodyDesc.fixed(),n=this.world.createRigidBody(o);i?.type===PhysicsBodyType.dynamic&&this.nonFixedBodies.add(n);let r=0;for(const s of e){if(r>128){console.warn("Too many collision shapes for object",t);break}if(r++,null==s){console.warn("Collision shape is missing for object",t);continue}const o=this.addShape(n,s,t);null!=o&&(null!=i?.friction&&o.setFriction(i.friction),null!=i?.density&&o.setDensity(i.density),null!=i?.mass&&o.setMass(i.mass/e.length),null!=i?.restitution&&o.setRestitution(i.restitution))}return G(n,t),n.userData=t.uuid,n.isFixed()&&this.invalidateStaticDebug(),n}addShape(t=void 0,e,i){const s=i?.getWorldScale(pt)??q,o=this.createShape(e,s);if(null==o)return void console.error("Failed to create physics shape. This can happen if the geometry is degenerate or zero-scaled.",{shapeInfo:e,object:i});this.applyShapeSettings(o,e);const n=e.offset.clone().multiply(s);rt(o.translation,n);const r=(new f).setFromEuler(e.rotation);at(o.rotation,r),null!=t&&t.numColliders()>128&&console.warn(`Rigid body has many colliders (${t.numColliders()}). Consider using a Trimesh if this is static geometry.`,t);try{const s=this.world.createCollider(o,t),n=i??(e instanceof R&&e.mesh instanceof w?e.mesh:void 0);return null!=n&&this.colliderObjects.set(s,{object:n}),s}catch(t){return void console.error("Failed to create collider",t)}}applyShapeSettings(t,e){null!=e.collisionGroup&&t.setCollisionGroups(e.collisionGroup),t.friction=e.friction??.1,null!=e.restitution&&(t.restitution=e.restitution),null!=e.density&&(t.density=e.density,t.massPropsMode=s.MassPropsMode.Density),null!=e.mass&&(t.mass=e.mass,t.massPropsMode=s.MassPropsMode.Mass)}createShape(t,e){return i(this.rapier,t,e)}createCharacterCollision(){return new this.rapier.CharacterCollision}};V=t([D(),e("design:paramtypes",[])],V);export{V as PhysicsSystem};const U=new B,K=new h.Quaternion;function G(t,e){const i=e.getWorldPosition(U),s=e.getWorldQuaternion(K);t.setTranslation(it(i),!1),t.setRotation(st(s),!1)}const X=new B,q=new B(1,1,1),H=new s.Vector3(0,0,0),Q=new s.Vector3(0,0,0),J=new B,Y=new B,Z=new B,$=new Set,tt=[],et=new h.Vector2;function it(t){return rt(H,t),H}function st(t){return at(L,t),L}let ot=null;const nt=async()=>(null==ot&&(ot=(async()=>{let t=await import("@dimforge/rapier3d-simd-compat");return await t.init(),t})()),ot);function rt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function at(t,e){t.x=e.x,t.y=e.y,t.z=e.z,t.w=e.w}function lt(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function ct(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const dt=new B,ht=new WeakMap,ut=t=>ht.get(t)??!0,pt=new B;let yt,gt=class extends S{constructor(){super(...arguments),this._active=!0,this.physics=C(V),this.world=C(j)}set active(t){this._active=t,t?(this.world.scene.remove(this.actor.object),this.physics.setEnabled(this.actor,t)):(this.world.scene.add(this.actor.object),this.physics.setEnabled(this.actor,t))}get active(){return this._active}};gt=t([A()],gt);export{extractFloat32Array}from"../../../scene/collision/rapier-shape.js";function mt(t,e,i,s){return s.set(t.x,t.y,t.z,t.w),i.set(e.x,e.y,e.z),i.applyQuaternion(s),i}export class PhysicsCollider{constructor(t,e,i){this.collider=t,this.world=e,this.invalidateStaticDebug=i,this.disposed=new c,this.onBeginOverlapActor=new c,this.onEndOverlapActor=new c}dispose(){const t=this.collider.parent();(null==t||t.isFixed())&&this.invalidateStaticDebug?.(),this.world.removeCollider(this.collider,!1),this.disposed.next(!0),this.disposed.complete(),this.onBeginOverlapActor.complete(),this.onEndOverlapActor.complete()}set mass(t){this.collider.setMass(t)}get mass(){return this.collider.mass()}set friction(t){this.collider.setFriction(t)}get friction(){return this.collider.friction()}set restitution(t){this.collider.setRestitution(t)}get restitution(){return this.collider.restitution()}set density(t){this.collider.setDensity(t)}get density(){return this.collider.density()}set isTrigger(t){this.collider.setSensor(t)}get isTrigger(){return this.collider.isSensor()}set collisionGroups(t){this.collider.setCollisionGroups(t)}get collisionGroups(){return this.collider.collisionGroups()}set enabled(t){this.collider.setEnabled(t);const e=this.collider.parent();(null==e||e.isFixed())&&this.invalidateStaticDebug?.()}get enabled(){return this.collider.isEnabled()}}export class PhysicsBody{constructor(t,e,i){this.invalidateStaticDebug=i,this.body=t,this.world=e}dispose(){this.body.isFixed()&&this.invalidateStaticDebug?.(),this.world.removeRigidBody(this.body)}setEnabled(t){this.body.setEnabled(t),this.body.isFixed()&&this.invalidateStaticDebug?.()}isEnabled(){return this.body.isEnabled()}getPosition(t){return this.body.translation(t)}setPosition(t){this.body.setTranslation({x:t.x,y:t.y,z:t.z},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getRotation(t){const e=this.body.rotation();return t.set(e.x,e.y,e.z,e.w),t}setRotation(t){this.body.setRotation({x:t.x,y:t.y,z:t.z,w:t.w},!0),this.body.isFixed()&&this.invalidateStaticDebug?.()}getLinearVelocity(t){const e=this.body.linvel();return t.set(e.x,e.y,e.z),t}setLinearVelocity(t){this.body.setLinvel({x:t.x,y:t.y,z:t.z},!0)}getAngularVelocity(t){const e=this.body.angvel();return t.set(e.x,e.y,e.z),t}setAngularVelocity(t){this.body.setAngvel({x:t.x,y:t.y,z:t.z},!0)}setLinearDamping(t){this.body.setLinearDamping(t)}setAngularDamping(t){this.body.setAngularDamping(t)}applyImpulse(t,e=!0){this.body.applyImpulse({x:t.x,y:t.y,z:t.z},e)}applyTorqueImpulse(t,e=!0){this.body.applyTorqueImpulse({x:t.x,y:t.y,z:t.z},e)}setNextKinematicPosition(t){this.body.setNextKinematicTranslation(t)}setNextKinematicRotation(t){this.body.setNextKinematicRotation(t)}setType(t){const e=this.body.isFixed();this.body.setBodyType(function(t){switch(t){case PhysicsBodyType.dynamic:return s.RigidBodyType.Dynamic;case PhysicsBodyType.static:return s.RigidBodyType.Fixed;case PhysicsBodyType.kinematic:return s.RigidBodyType.KinematicPositionBased;case PhysicsBodyType.kinematicVelocityBased:return s.RigidBodyType.KinematicVelocityBased}}(t),t!==PhysicsBodyType.static),(e||this.body.isFixed())&&this.invalidateStaticDebug?.()}setGravityScale(t){this.body.setGravityScale(t,!1)}getGravityScale(){return this.body.gravityScale()}isDynamic(){return this.body.isDynamic()}isKinematic(){return this.body.isKinematic()}isStatic(){return this.body.isFixed()}sleep(){this.body.sleep()}wakeUp(){this.body.wakeUp()}}export class PhysicsJoint{constructor(t,e){this.joint=t,this.world=e}dispose(){this.joint.isValid()&&this.world.removeImpulseJoint(this.joint,!0)}setContactsEnabled(t){this.joint.setContactsEnabled(t)}get contactsEnabled(){return this.joint.contactsEnabled()}}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -8,7 +8,7 @@ import { BaseActor } from '../../gameplay/actors/actor.js';
|
|
|
8
8
|
import { PostProcessVolume } from '../actors/builtin/post-process-volume-actor.js';
|
|
9
9
|
import type { PostProcessEffect, PostProcessEffectOptions } from '../../rendering/post-process-effect.js';
|
|
10
10
|
import type { PostProcessMaterialSource } from "../../shader/post-process-shader.js";
|
|
11
|
-
import type { ActiveRenderingBackend, ExperimentalWebGpuRenderGraphExtension } from '../../rendering.js';
|
|
11
|
+
import type { ActiveRenderingBackend, ExperimentalWebGpuRenderGraphExtension, RenderingStatsStyle } from '../../rendering.js';
|
|
12
12
|
import type { VfxBackendPreference } from '../../effects/vfx/gpu-sprite-compiler.js';
|
|
13
13
|
import { type CameraShakeRequest } from "./camera-shake.js";
|
|
14
14
|
export type { CameraShakeRequest, CameraShakeSample, CameraShakeSettings, CameraShakeVector3, } from "./camera-shake.js";
|
|
@@ -78,6 +78,9 @@ export declare class ViewController {
|
|
|
78
78
|
get fpsCap(): number | null;
|
|
79
79
|
set showStats(value: boolean);
|
|
80
80
|
get showStats(): boolean;
|
|
81
|
+
/** Player overlay or detailed engine diagnostics. Defaults to detailed. */
|
|
82
|
+
set statsStyle(value: RenderingStatsStyle);
|
|
83
|
+
get statsStyle(): RenderingStatsStyle;
|
|
81
84
|
/** Enables renderer timing collection without requiring the HTML stats UI. */
|
|
82
85
|
setProfilingEnabled(enabled: boolean): void;
|
|
83
86
|
/** Returns the latest completed WebGPU frame profile when profiling is enabled. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as e,__metadata as t}from"tslib";import{Service as a}from"typedi";import{Camera as i}from"three";import{FrameAudioListener as r}from"../../utils/three/frame-audio-listener.js";import{RenderingView as s}from"../../rendering.js";import{BehaviorSubject as n,Subject as h,takeUntil as o}from"rxjs";import*as m from"three";import{GameTimeScheduler as u}from"./game-time-scheduler.js";import{createCameraShakeSample as l,resetCameraShakeSample as c,sampleCameraShake as d}from"./camera-shake.js";export{defaultPostProcessEffectStage,postProcessEffectStages}from"../../rendering/post-process-effect.js";let p=class{constructor(e){this.view=e,this.tick=new h,this.lateTick=new h,this.audioListener=new r,this.pausedChanged=new n(!1),this.mutedChanged=new n(!1),this._muted=!1,this._masterVolume=1,this._cameraShakeIntensity=1,this._timeScale=1,this._hitStopRemaining=0,this.scheduler=new u,this.cameraOverrideId=0,this.cameraOverrides=[],this.cameraShakeId=0,this.gameplayCameraShakes=[],this.cameraShakeContributions=new Map,this.presentationCamera=null,this.accumulatedCameraShakeSample=l(),this.scratchCameraShakeSample=l(),this._updateFrameIndex=0,this.outlined=[],this.baseCamera=e.camera,this.sourceCamera=e.camera,e.onLoop(e=>{this.handleFrame(e)}),e.camera.add(this.audioListener),window.hology_view=this}get activeBackend(){return this.view.activeBackend}get requestedBackend(){return this.view.requestedBackend}get vfxBackendPreference(){return this.view.vfxBackendPreference}get webgpuVfxInstancesPerTemplate(){return this.view.webgpuVfxInstancesPerTemplate}get webgpuVfxTemplateMemoryBudgetBytes(){return this.view.webgpuVfxTemplateMemoryBudgetBytes}get webgpuVfxWorldMemoryBudgetBytes(){return this.view.webgpuVfxWorldMemoryBudgetBytes}get webgpuVfxColdTemplateSeconds(){return this.view.webgpuVfxColdTemplateSeconds}get webGpuDevice(){return this.view.webGpuDevice}get experimentalWebGpuDevice(){return this.webGpuDevice}registerWebGpuRenderGraphExtension(e){return this.view.registerWebGpuRenderGraphExtension(e)}registerExperimentalWebGpuRenderGraphExtension(e){return this.registerWebGpuRenderGraphExtension(e)}get updateFrameIndex(){return this._updateFrameIndex}handleFrame(e){this._updateFrameIndex++;let t=this._timeScale,a=0;this._hitStopRemaining>0?(this._hitStopRemaining-=1e3*e,this._hitStopRemaining<=0&&(this._hitStopRemaining=0),t=0):a=e*this._timeScale,this.advanceGameplayCameraShakes(a),this.tick.next(a),this.scheduler.update(1e3*a),this.lateTick.next(a),this.view.simulationTimeScale=t,this.refreshCameraPresentation()}set timeScale(e){this._timeScale=Math.max(0,e)}get timeScale(){return this._timeScale}get time(){return performance.now()/1e3}applyHitStop(e){this._hitStopRemaining=Math.max(this._hitStopRemaining,e)}set fpsCap(e){this.view.fpsCap=e}get fpsCap(){return this.view.fpsCap}set showStats(e){this.view.showStats=e}get showStats(){return this.view.showStats}setProfilingEnabled(e){this.view.setProfilingEnabled(e)}getLastFrameProfile(){return this.view.getLastFrameProfile()}setLightVolume(e){this.view.lightVolume=e}getLightVolume(){return this.view.lightVolume}addPostProcessVolume(e){this.view.addPostProcessVolume(e)}removePostProcessVolume(e){this.view.removePostProcessVolume(e)}addPostProcessEffect(e,t){return this.view.addPostProcessEffect(e,t)}onUpdate(e){return null==e?this.tick:this.tick.pipe(o(e.disposed))}onLateUpdate(e){return null==e?this.lateTick:this.lateTick.pipe(o(e.disposed))}setCamera(e){const t=e instanceof i?e:e.camera.instance;this.baseCamera=t,0===this.cameraOverrides.length&&(this.sourceCamera=t,this.refreshCameraPresentation())}getCamera(){return this.view.camera}getSourceCamera(){return this.sourceCamera}getBaseCamera(){return this.baseCamera}applyCameraShake(e){const t=function(e){return{duration:Math.max(0,e.duration??0),attack:e.attack??0,decay:e.decay??0,frequency:e.frequency??24,positionAmplitude:e.positionAmplitude?[...e.positionAmplitude]:[0,0,0],rotationAmplitude:e.rotationAmplitude?[...e.rotationAmplitude]:[0,0,0],seed:e.seed}}(e);if(t.duration<=0)return{release:()=>{}};const a={id:++this.cameraShakeId,request:t,elapsedTime:0,seedOverride:t.seed};this.gameplayCameraShakes.push(a),this.refreshCameraPresentation();let i=!1;return{release:()=>{i||(i=!0,this.releaseGameplayCameraShake(a.id))}}}setCameraShakeContribution(e,t,a,i,r){if(a.duration<=0)return void this.removeCameraShakeContribution(e,t);let s=this.cameraShakeContributions.get(e);s||(s=new Map,this.cameraShakeContributions.set(e,s));const n=s.get(t);n?(n.request=a,n.elapsedTime=Math.max(0,i),n.seedOverride=r):s.set(t,{key:t,request:a,elapsedTime:Math.max(0,i),seedOverride:r}),this.refreshCameraPresentation()}removeCameraShakeContribution(e,t){const a=this.cameraShakeContributions.get(e);a?.delete(t)&&(0===a.size&&this.cameraShakeContributions.delete(e),this.refreshCameraPresentation())}clearCameraShakeContributionsForOwner(e){this.cameraShakeContributions.delete(e)&&this.refreshCameraPresentation()}pushCameraOverride(e,t,a=0){const i={id:++this.cameraOverrideId,camera:e,owner:t,priority:a};this.cameraOverrides.push(i),this.applyTopCameraOverride();let r=!1;return{release:()=>{r||(r=!0,this.releaseCameraOverrideEntry(i))}}}releaseCameraOverridesForOwner(e){const t=this.cameraOverrides.filter(t=>t.owner!==e);t.length!==this.cameraOverrides.length&&(this.cameraOverrides=t,this.applyTopCameraOverride())}releaseCameraOverrideEntry(e){const t=this.cameraOverrides.indexOf(e);-1!==t&&(this.cameraOverrides.splice(t,1),this.applyTopCameraOverride())}applyTopCameraOverride(){const e=this.getTopCameraOverride();this.sourceCamera=e?.camera??this.baseCamera,this.refreshCameraPresentation()}getTopCameraOverride(){let e;for(const t of this.cameraOverrides)(!e||t.priority>e.priority||t.priority===e.priority&&t.id>e.id)&&(e=t);return e}applyRenderedCamera(e){this.view.camera!==e&&this.view.setCamera(e),e.add(this.audioListener)}releaseGameplayCameraShake(e){const t=this.gameplayCameraShakes.findIndex(t=>t.id===e);-1!==t&&(this.gameplayCameraShakes.splice(t,1),this.refreshCameraPresentation())}advanceGameplayCameraShakes(e){if(!(e<=0||0===this.gameplayCameraShakes.length))for(let t=this.gameplayCameraShakes.length-1;t>=0;t--){const a=this.gameplayCameraShakes[t];a.elapsedTime+=e,a.elapsedTime>a.request.duration&&this.gameplayCameraShakes.splice(t,1)}}refreshCameraPresentation(){if(!this.hasActiveCameraShake())return void this.applyRenderedCamera(this.sourceCamera);const e=this.ensurePresentationCamera();this.copyCameraState(this.sourceCamera,e),this.accumulateCameraShakeSamples(),this.applyCameraShakeSample(e),this.applyRenderedCamera(e)}hasActiveCameraShake(){if(this.gameplayCameraShakes.length>0)return!0;for(const e of this.cameraShakeContributions.values())if(e.size>0)return!0;return!1}ensurePresentationCamera(){return this.presentationCamera||(this.presentationCamera=new m.PerspectiveCamera,this.presentationCamera.name="View Controller Presentation Camera"),this.presentationCamera}copyCameraState(e,t){e.updateWorldMatrix(!0,!1),t.position.copy(e.getWorldPosition(f)),t.quaternion.copy(e.getWorldQuaternion(k)),t.scale.copy(e.getWorldScale(w)),t.layers.mask=e.layers.mask,e instanceof m.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect,t.zoom=e.zoom,t.focus=e.focus,t.filmGauge=e.filmGauge,t.filmOffset=e.filmOffset,t.view=null==e.view?null:{enabled:e.view.enabled,fullWidth:e.view.fullWidth,fullHeight:e.view.fullHeight,offsetX:e.view.offsetX,offsetY:e.view.offsetY,width:e.view.width,height:e.view.height},t.updateProjectionMatrix()):(t.projectionMatrix.copy(e.projectionMatrix),t.projectionMatrixInverse.copy(e.projectionMatrixInverse))}accumulateCameraShakeSamples(){c(this.accumulatedCameraShakeSample);for(let e=0;e<this.gameplayCameraShakes.length;e++)this.accumulateCameraShakeEntry(this.gameplayCameraShakes[e]);for(const e of this.cameraShakeContributions.values())for(const t of e.values())this.accumulateCameraShakeEntry(t)}accumulateCameraShakeEntry(e){const t=d(e.request,e.elapsedTime,this.scratchCameraShakeSample,e.seedOverride);if(t)for(let e=0;e<3;e++)this.accumulatedCameraShakeSample.position[e]+=t.position[e],this.accumulatedCameraShakeSample.rotation[e]+=t.rotation[e]}applyCameraShakeSample(e){y.copy(e.quaternion),x.set(this.accumulatedCameraShakeSample.position[0]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.position[1]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.position[2]*this._cameraShakeIntensity),x.applyQuaternion(y),e.position.add(x),P.set(this.accumulatedCameraShakeSample.rotation[0]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.rotation[1]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.rotation[2]*this._cameraShakeIntensity),b.setFromEuler(P),e.quaternion.copy(y).multiply(b),e.updateMatrixWorld(!0)}setMuted(e){this._muted=e,this.applyAudioGain(),this.mutedChanged.next(e)}getMuted(){return this._muted}set masterVolume(e){this._masterVolume=Math.min(Math.max(e,0),1),this.applyAudioGain()}get masterVolume(){return this._masterVolume}set cameraShakeIntensity(e){this._cameraShakeIntensity=Math.min(Math.max(e,0),1),this.refreshCameraPresentation()}get cameraShakeIntensity(){return this._cameraShakeIntensity}applyAudioGain(){this.audioListener.gain.gain.setValueAtTime(this._muted?0:this._masterVolume,this.audioListener.context.currentTime)}setOutlined(e){this.outlined.length=0;const t=this.outlined;for(let a=0;a<e.length;a++)t[a]=e[a];this.view.setSelectedObjects(t),this.view.setEnableOutlines(e.length>0)}getOutlined(){return this.outlined}addOutlined(e){this.outlined.includes(e)||(this.outlined.push(e),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(!0))}removeOutlined(e){const t=this.outlined.indexOf(e);-1!==t&&(this.outlined.splice(t,1),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(this.outlined.length>0))}setOutlineColor(e){this.view.outlinePass?.visibleEdgeColor.copy(e)}getOutlineColor(){return this.view.outlinePass?.visibleEdgeColor}setOutlineThickness(e){this.view.outlinePass.edgeThickness=e}getOutlineThickness(){return this.view.outlinePass.edgeThickness}get htmlElement(){return this.view.container}getViewportSize(e=v){return this.view.getClientSize(e)}get paused(){return this.view.paused}set paused(e){e!=this.paused&&(e?this.pauseRendering():this.unpauseRendering())}pauseRendering(){this.view.paused=!0,this.pausedChanged.next(this.view.paused),this.scheduler.pause()}unpauseRendering(){this.view.paused=!1,this.pausedChanged.next(this.view.paused),this.scheduler.resume()}setInterval(e,t,a){return this.scheduler.setInterval(e,t,a)}clearInterval(e){this.scheduler.clearInterval(e)}dispose(e=!0){e&&this.view.running&&this.view.stop(),this.scheduler.dispose(),this.cameraOverrides.length=0,this.gameplayCameraShakes.length=0,this.cameraShakeContributions.clear(),this.audioListener.disposePoseUpdates(),this.audioListener.removeFromParent(),this.tick.complete(),this.lateTick.complete(),this.paused=!0}createTimer(e){return this.scheduler.createTimer(e)}getScreenPosition(e,t=C,a=this.getViewportSize()){const i=this.getCamera();return g.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),i instanceof m.PerspectiveCamera&&(S.setFromProjectionMatrix(g),!S.containsPoint(e))?null:(t.copy(e),t.project(i),t.x=(t.x+1)/2*a.x,t.y=(1-t.y)/2*a.y,t)}};p=e([a(),t("design:paramtypes",[s])],p);export{p as ViewController};const g=new m.Matrix4,C=new m.Vector3,v=new m.Vector2,S=new m.Frustum,f=new m.Vector3,w=new m.Vector3,k=new m.Quaternion,y=new m.Quaternion,x=new m.Vector3,P=new m.Euler(0,0,0,"XYZ"),b=new m.Quaternion;/*
|
|
1
|
+
import{__decorate as e,__metadata as t}from"tslib";import{Service as a}from"typedi";import{Camera as i}from"three";import{FrameAudioListener as r}from"../../utils/three/frame-audio-listener.js";import{RenderingView as s}from"../../rendering.js";import{BehaviorSubject as n,Subject as h,takeUntil as o}from"rxjs";import*as m from"three";import{GameTimeScheduler as l}from"./game-time-scheduler.js";import{createCameraShakeSample as u,resetCameraShakeSample as c,sampleCameraShake as d}from"./camera-shake.js";export{defaultPostProcessEffectStage,postProcessEffectStages}from"../../rendering/post-process-effect.js";let p=class{constructor(e){this.view=e,this.tick=new h,this.lateTick=new h,this.audioListener=new r,this.pausedChanged=new n(!1),this.mutedChanged=new n(!1),this._muted=!1,this._masterVolume=1,this._cameraShakeIntensity=1,this._timeScale=1,this._hitStopRemaining=0,this.scheduler=new l,this.cameraOverrideId=0,this.cameraOverrides=[],this.cameraShakeId=0,this.gameplayCameraShakes=[],this.cameraShakeContributions=new Map,this.presentationCamera=null,this.accumulatedCameraShakeSample=u(),this.scratchCameraShakeSample=u(),this._updateFrameIndex=0,this.outlined=[],this.baseCamera=e.camera,this.sourceCamera=e.camera,e.onLoop(e=>{this.handleFrame(e)}),e.camera.add(this.audioListener),window.hology_view=this}get activeBackend(){return this.view.activeBackend}get requestedBackend(){return this.view.requestedBackend}get vfxBackendPreference(){return this.view.vfxBackendPreference}get webgpuVfxInstancesPerTemplate(){return this.view.webgpuVfxInstancesPerTemplate}get webgpuVfxTemplateMemoryBudgetBytes(){return this.view.webgpuVfxTemplateMemoryBudgetBytes}get webgpuVfxWorldMemoryBudgetBytes(){return this.view.webgpuVfxWorldMemoryBudgetBytes}get webgpuVfxColdTemplateSeconds(){return this.view.webgpuVfxColdTemplateSeconds}get webGpuDevice(){return this.view.webGpuDevice}get experimentalWebGpuDevice(){return this.webGpuDevice}registerWebGpuRenderGraphExtension(e){return this.view.registerWebGpuRenderGraphExtension(e)}registerExperimentalWebGpuRenderGraphExtension(e){return this.registerWebGpuRenderGraphExtension(e)}get updateFrameIndex(){return this._updateFrameIndex}handleFrame(e){this._updateFrameIndex++;let t=this._timeScale,a=0;this._hitStopRemaining>0?(this._hitStopRemaining-=1e3*e,this._hitStopRemaining<=0&&(this._hitStopRemaining=0),t=0):a=e*this._timeScale,this.advanceGameplayCameraShakes(a),this.tick.next(a),this.scheduler.update(1e3*a),this.lateTick.next(a),this.view.simulationTimeScale=t,this.refreshCameraPresentation()}set timeScale(e){this._timeScale=Math.max(0,e)}get timeScale(){return this._timeScale}get time(){return performance.now()/1e3}applyHitStop(e){this._hitStopRemaining=Math.max(this._hitStopRemaining,e)}set fpsCap(e){this.view.fpsCap=e}get fpsCap(){return this.view.fpsCap}set showStats(e){this.view.showStats=e}get showStats(){return this.view.showStats}set statsStyle(e){this.view.statsStyle=e}get statsStyle(){return this.view.statsStyle}setProfilingEnabled(e){this.view.setProfilingEnabled(e)}getLastFrameProfile(){return this.view.getLastFrameProfile()}setLightVolume(e){this.view.lightVolume=e}getLightVolume(){return this.view.lightVolume}addPostProcessVolume(e){this.view.addPostProcessVolume(e)}removePostProcessVolume(e){this.view.removePostProcessVolume(e)}addPostProcessEffect(e,t){return this.view.addPostProcessEffect(e,t)}onUpdate(e){return null==e?this.tick:this.tick.pipe(o(e.disposed))}onLateUpdate(e){return null==e?this.lateTick:this.lateTick.pipe(o(e.disposed))}setCamera(e){const t=e instanceof i?e:e.camera.instance;this.baseCamera=t,0===this.cameraOverrides.length&&(this.sourceCamera=t,this.refreshCameraPresentation())}getCamera(){return this.view.camera}getSourceCamera(){return this.sourceCamera}getBaseCamera(){return this.baseCamera}applyCameraShake(e){const t=function(e){return{duration:Math.max(0,e.duration??0),attack:e.attack??0,decay:e.decay??0,frequency:e.frequency??24,positionAmplitude:e.positionAmplitude?[...e.positionAmplitude]:[0,0,0],rotationAmplitude:e.rotationAmplitude?[...e.rotationAmplitude]:[0,0,0],seed:e.seed}}(e);if(t.duration<=0)return{release:()=>{}};const a={id:++this.cameraShakeId,request:t,elapsedTime:0,seedOverride:t.seed};this.gameplayCameraShakes.push(a),this.refreshCameraPresentation();let i=!1;return{release:()=>{i||(i=!0,this.releaseGameplayCameraShake(a.id))}}}setCameraShakeContribution(e,t,a,i,r){if(a.duration<=0)return void this.removeCameraShakeContribution(e,t);let s=this.cameraShakeContributions.get(e);s||(s=new Map,this.cameraShakeContributions.set(e,s));const n=s.get(t);n?(n.request=a,n.elapsedTime=Math.max(0,i),n.seedOverride=r):s.set(t,{key:t,request:a,elapsedTime:Math.max(0,i),seedOverride:r}),this.refreshCameraPresentation()}removeCameraShakeContribution(e,t){const a=this.cameraShakeContributions.get(e);a?.delete(t)&&(0===a.size&&this.cameraShakeContributions.delete(e),this.refreshCameraPresentation())}clearCameraShakeContributionsForOwner(e){this.cameraShakeContributions.delete(e)&&this.refreshCameraPresentation()}pushCameraOverride(e,t,a=0){const i={id:++this.cameraOverrideId,camera:e,owner:t,priority:a};this.cameraOverrides.push(i),this.applyTopCameraOverride();let r=!1;return{release:()=>{r||(r=!0,this.releaseCameraOverrideEntry(i))}}}releaseCameraOverridesForOwner(e){const t=this.cameraOverrides.filter(t=>t.owner!==e);t.length!==this.cameraOverrides.length&&(this.cameraOverrides=t,this.applyTopCameraOverride())}releaseCameraOverrideEntry(e){const t=this.cameraOverrides.indexOf(e);-1!==t&&(this.cameraOverrides.splice(t,1),this.applyTopCameraOverride())}applyTopCameraOverride(){const e=this.getTopCameraOverride();this.sourceCamera=e?.camera??this.baseCamera,this.refreshCameraPresentation()}getTopCameraOverride(){let e;for(const t of this.cameraOverrides)(!e||t.priority>e.priority||t.priority===e.priority&&t.id>e.id)&&(e=t);return e}applyRenderedCamera(e){this.view.camera!==e&&this.view.setCamera(e),e.add(this.audioListener)}releaseGameplayCameraShake(e){const t=this.gameplayCameraShakes.findIndex(t=>t.id===e);-1!==t&&(this.gameplayCameraShakes.splice(t,1),this.refreshCameraPresentation())}advanceGameplayCameraShakes(e){if(!(e<=0||0===this.gameplayCameraShakes.length))for(let t=this.gameplayCameraShakes.length-1;t>=0;t--){const a=this.gameplayCameraShakes[t];a.elapsedTime+=e,a.elapsedTime>a.request.duration&&this.gameplayCameraShakes.splice(t,1)}}refreshCameraPresentation(){if(!this.hasActiveCameraShake())return void this.applyRenderedCamera(this.sourceCamera);const e=this.ensurePresentationCamera();this.copyCameraState(this.sourceCamera,e),this.accumulateCameraShakeSamples(),this.applyCameraShakeSample(e),this.applyRenderedCamera(e)}hasActiveCameraShake(){if(this.gameplayCameraShakes.length>0)return!0;for(const e of this.cameraShakeContributions.values())if(e.size>0)return!0;return!1}ensurePresentationCamera(){return this.presentationCamera||(this.presentationCamera=new m.PerspectiveCamera,this.presentationCamera.name="View Controller Presentation Camera"),this.presentationCamera}copyCameraState(e,t){e.updateWorldMatrix(!0,!1),t.position.copy(e.getWorldPosition(f)),t.quaternion.copy(e.getWorldQuaternion(k)),t.scale.copy(e.getWorldScale(w)),t.layers.mask=e.layers.mask,e instanceof m.PerspectiveCamera?(t.fov=e.fov,t.near=e.near,t.far=e.far,t.aspect=e.aspect,t.zoom=e.zoom,t.focus=e.focus,t.filmGauge=e.filmGauge,t.filmOffset=e.filmOffset,t.view=null==e.view?null:{enabled:e.view.enabled,fullWidth:e.view.fullWidth,fullHeight:e.view.fullHeight,offsetX:e.view.offsetX,offsetY:e.view.offsetY,width:e.view.width,height:e.view.height},t.updateProjectionMatrix()):(t.projectionMatrix.copy(e.projectionMatrix),t.projectionMatrixInverse.copy(e.projectionMatrixInverse))}accumulateCameraShakeSamples(){c(this.accumulatedCameraShakeSample);for(let e=0;e<this.gameplayCameraShakes.length;e++)this.accumulateCameraShakeEntry(this.gameplayCameraShakes[e]);for(const e of this.cameraShakeContributions.values())for(const t of e.values())this.accumulateCameraShakeEntry(t)}accumulateCameraShakeEntry(e){const t=d(e.request,e.elapsedTime,this.scratchCameraShakeSample,e.seedOverride);if(t)for(let e=0;e<3;e++)this.accumulatedCameraShakeSample.position[e]+=t.position[e],this.accumulatedCameraShakeSample.rotation[e]+=t.rotation[e]}applyCameraShakeSample(e){y.copy(e.quaternion),x.set(this.accumulatedCameraShakeSample.position[0]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.position[1]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.position[2]*this._cameraShakeIntensity),x.applyQuaternion(y),e.position.add(x),P.set(this.accumulatedCameraShakeSample.rotation[0]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.rotation[1]*this._cameraShakeIntensity,this.accumulatedCameraShakeSample.rotation[2]*this._cameraShakeIntensity),b.setFromEuler(P),e.quaternion.copy(y).multiply(b),e.updateMatrixWorld(!0)}setMuted(e){this._muted=e,this.applyAudioGain(),this.mutedChanged.next(e)}getMuted(){return this._muted}set masterVolume(e){this._masterVolume=Math.min(Math.max(e,0),1),this.applyAudioGain()}get masterVolume(){return this._masterVolume}set cameraShakeIntensity(e){this._cameraShakeIntensity=Math.min(Math.max(e,0),1),this.refreshCameraPresentation()}get cameraShakeIntensity(){return this._cameraShakeIntensity}applyAudioGain(){this.audioListener.gain.gain.setValueAtTime(this._muted?0:this._masterVolume,this.audioListener.context.currentTime)}setOutlined(e){this.outlined.length=0;const t=this.outlined;for(let a=0;a<e.length;a++)t[a]=e[a];this.view.setSelectedObjects(t),this.view.setEnableOutlines(e.length>0)}getOutlined(){return this.outlined}addOutlined(e){this.outlined.includes(e)||(this.outlined.push(e),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(!0))}removeOutlined(e){const t=this.outlined.indexOf(e);-1!==t&&(this.outlined.splice(t,1),this.view.setSelectedObjects(this.outlined),this.view.setEnableOutlines(this.outlined.length>0))}setOutlineColor(e){this.view.outlinePass?.visibleEdgeColor.copy(e)}getOutlineColor(){return this.view.outlinePass?.visibleEdgeColor}setOutlineThickness(e){this.view.outlinePass.edgeThickness=e}getOutlineThickness(){return this.view.outlinePass.edgeThickness}get htmlElement(){return this.view.container}getViewportSize(e=v){return this.view.getClientSize(e)}get paused(){return this.view.paused}set paused(e){e!=this.paused&&(e?this.pauseRendering():this.unpauseRendering())}pauseRendering(){this.view.paused=!0,this.pausedChanged.next(this.view.paused),this.scheduler.pause()}unpauseRendering(){this.view.paused=!1,this.pausedChanged.next(this.view.paused),this.scheduler.resume()}setInterval(e,t,a){return this.scheduler.setInterval(e,t,a)}clearInterval(e){this.scheduler.clearInterval(e)}dispose(e=!0){e&&this.view.running&&this.view.stop(),this.scheduler.dispose(),this.cameraOverrides.length=0,this.gameplayCameraShakes.length=0,this.cameraShakeContributions.clear(),this.audioListener.disposePoseUpdates(),this.audioListener.removeFromParent(),this.tick.complete(),this.lateTick.complete(),this.paused=!0}createTimer(e){return this.scheduler.createTimer(e)}getScreenPosition(e,t=C,a=this.getViewportSize()){const i=this.getCamera();return g.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),i instanceof m.PerspectiveCamera&&(S.setFromProjectionMatrix(g),!S.containsPoint(e))?null:(t.copy(e),t.project(i),t.x=(t.x+1)/2*a.x,t.y=(1-t.y)/2*a.y,t)}};p=e([a(),t("design:paramtypes",[s])],p);export{p as ViewController};const g=new m.Matrix4,C=new m.Vector3,v=new m.Vector2,S=new m.Frustum,f=new m.Vector3,w=new m.Vector3,k=new m.Quaternion,y=new m.Quaternion,x=new m.Vector3,P=new m.Euler(0,0,0,"XYZ"),b=new m.Quaternion;/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -67,6 +67,11 @@ export declare class World {
|
|
|
67
67
|
* It sets isLocallyControlled to true
|
|
68
68
|
*/
|
|
69
69
|
spawnLocalPlayerController<T extends BasePlayerController>(type: Constructable<T>, position?: Vector3, rotation?: Euler): Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Spawn an actor synchronously when its resources are already loaded.
|
|
72
|
+
* Persistent spawns require spawnActor().
|
|
73
|
+
*/
|
|
74
|
+
spawnActorSync<T extends BaseActor>(type: Constructable<T>, position?: Vector3, rotation?: Euler, options?: ActorSpawnOptions): T;
|
|
70
75
|
addActor(actor: BaseActor, position?: Vector3, rotation?: Euler, lifetime?: ActorLifetime, deferBeginPlay?: boolean): void;
|
|
71
76
|
private assertPersistentSpawn;
|
|
72
77
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"three";import{compileNodeWebGpuFullscreen as a,compileNodeShaderMaterialForWebGpu as t,NodeShaderMaterial as n,webGpuRendererBindings as i,webGpuTiledRendererBindings as s,textureSampler2d as o,float as r,length as l,max as u,rgba as p,isWgslCompiler as m,isWgslFragmentCompiler as c,sqrt as f,normalize as h,transformed as d,uniformFloat as M,uniforms as v,vec4 as y,Vec3Node as g,toonMaterial as V}from"three-shader-graph";import{StandardShader as w}from"../shader/builtin/standard-shader.js";import{LambertShader as I}from"../shader/builtin/lambert-shader.js";import{ToonShader as S}from"../shader/builtin/toon-shader.js";import{UnlitShader as x}from"../shader/builtin/unlit-shader.js";import{SpriteShader as T}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as E}from"../shader-nodes/time.js";import{depthUniformName as C,farUniformName as b,nearUniformName as U,resolutionUniformName as A,sceneNormalUniformName as N}from"../shader-nodes/depth.js";import{sceneMapUniformName as W,transmissionMapUniformName as k}from"../shader-nodes/scene-sample.js";const R={...i,uniformExpressions:{...i.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[E]:{type:"float",expression:"rendererElapsedTime()"},[U]:{type:"float",expression:"rendererCameraNear()"},[b]:{type:"float",expression:"rendererCameraFar()"},[A]:{type:"vec2",expression:"rendererViewportSize()"}},graphTextures:{[k]:{resource:"physicalTransmissionSnapshot",dimension:"2d",sampleType:"float",sampler:"filtering",requiresLatePass:!0}},sceneTextures:{[W]:{semantic:"sceneColor",sampleType:"float"},[C]:{semantic:"sceneDepth",sampleType:"depth"}},attributes:{material:{shaderLocation:6,format:"float32x4",defaultValue:[0,0,0,0]},material2:{shaderLocation:7,format:"float32x4",defaultValue:[0,0,0,0]},hole:{shaderLocation:8,format:"float32",defaultValue:[0]},offset:{shaderLocation:9,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},velocity:{shaderLocation:10,format:"float32x4",stepMode:"instance",defaultValue:[0,0,0,0]},size:{shaderLocation:11,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},rotation:{shaderLocation:12,format:"float32",stepMode:"instance",defaultValue:[0]},particleData:{shaderLocation:13,format:"float32x3",stepMode:"instance",defaultValue:[1,1,0]},particleColor:{shaderLocation:14,format:"float32x4",stepMode:"instance",defaultValue:[1,1,1,1]}}};class L extends g{constructor(e){super(),this.fallback=e}compile(e){if(!m(e))return{out:e.get(this.fallback)};if(c(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const a=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${a} = input.position;\n#endif`,out:a}}}class D extends g{constructor(e){super(),this.fallback=e}compile(e){if(!m(e))return{out:e.get(this.fallback)};if(c(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const a=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${a} = input.normal;\n#endif`,out:a}}}export function setMaterialUniformValuesAutoUpdate(e,a){e.uniformValuesAutoUpdate=a}export function markMaterialUniformValuesNeedUpdate(e){const a=e;"uniformValuesNeedsUpdate"in a?a.uniformValuesNeedsUpdate=!0:a.uniformValuesAutoVersion=(a.uniformValuesAutoVersion??0)+1}function F(e){return!1!==e.uniformValuesAutoUpdate}function O(e){return e.uniformValuesAutoVersion??0}export function withThreeDefaultVertexAttributeValues(e){return e.map(e=>"uv1"===e.name&&null==e.defaultValue?{...e,defaultValue:[0,0]}:e)}const P=new WeakMap,j=new WeakMap;export function createNodeMaterialSignature(e){const a=j.get(e);if(null!=a)return a;const t=JSON.stringify({version:e.version,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,alphaTest:e.alphaTest,alphaToCoverage:e.alphaToCoverage,blending:e.blending,colorWrite:e.colorWrite,depthFunc:e.depthFunc,depthTest:e.depthTest,depthWrite:e.depthWrite,polygonOffset:e.polygonOffset,polygonOffsetFactor:e.polygonOffsetFactor,polygonOffsetUnits:e.polygonOffsetUnits,premultipliedAlpha:e.premultipliedAlpha,side:e.side,stencilWrite:e.stencilWrite,transparent:e.transparent,wireframe:e.wireframe});return j.set(e,t),t}export class NodeMaterialWebGpuResolver{constructor(e,a,t){this.webGpu=e,this.mrtResolver=a,this.environmentTextureResolver=t,this.cache=new WeakMap,this.failedSignatures=new WeakMap,this.mappedMaterialsCache=new WeakMap,this.mappedMaterialsSignatures=new WeakMap,this.observedNodeMaterials=new Map,this.outlineMaterials=new WeakMap,this.outlineUniformVersions=new WeakMap,this.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const a=e?.texture??null,t=e?.intensity??0;if(this.worldEnvironmentTexture!==a||this.worldEnvironmentIntensity!==t){if(this.worldEnvironmentTexture!==a)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=t,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=a,this.worldEnvironmentIntensity=t}}resolve(e,a=void 0){let i,o=!1;if(e instanceof n)i=e,this.observeNodeMaterial(i);else{const a=this.getOrCreateMappedNodeMaterial(e);if(null==a)return;i=a,o=!0}if("outline"===a){if(null==i.outputAlbedo)return;o&&J(e,i),i.userData.outlineParameters=e.userData?.outlineParameters,i=this.getOrCreateOutlineMaterial(i),o=!1}i.visible=e.visible,o&&(i.userData.receiveDecals=e.userData.receiveDecals);const r=a??"default",l=this.cache.get(i),u=l?.get(r);if(o&&null!=u&&u.sourceVersion===e.version&&u.worldEnvironmentRevision===this.worldEnvironmentRevision){const a=F(e),t=O(e);return u.material.uniformValuesAutoUpdate=a,this.syncInheritedWorldEnvironmentSource(i,u),a||u.sourceUniformValuesAutoVersion!==t?(J(e,i),u.compiled.syncLiveUniforms(u.material.uniforms),z(i,u.material.uniforms),B(i,u.material),u.sourceUniformValuesAutoVersion=t,a||(u.material.uniformValuesNeedsUpdate=!0),u.material):u.material}if(!o&&null!=u&&u.sourceVersion===e.version&&u.worldEnvironmentRevision===this.worldEnvironmentRevision&&_(i,u.compiled))return this.syncInheritedWorldEnvironmentSource(i,u),$(i,u),u.material;o&&J(e,i);const p=this.prepareWorldEnvironment(i),m=this.getNodeMaterialSignature(i,p);if(u?.signature===m&&_(i,u.compiled))return o?(u.material.uniformValuesAutoUpdate=F(e),u.compiled.syncLiveUniforms(u.material.uniforms),z(i,u.material.uniforms),B(i,u.material),u.sourceUniformValuesAutoVersion=O(e),u.material.uniformValuesAutoUpdate||(u.material.uniformValuesNeedsUpdate=!0)):$(i,u,!0),u.sourceVersion=e.version,u.worldEnvironmentRevision=this.worldEnvironmentRevision,u.material;try{const n=this.mrtResolver?.(i,a),c=t(i,"opaque"===a?{...R,arrays:s.arrays}:R,n),f=new this.webGpu.WGSLShaderMaterial({vertexShader:c.vertexShader,fragmentShader:c.fragmentShader,depthVertexShader:c.depthVertexShader,depthFragmentShader:c.depthFragmentShader,pointShadowVertexShader:c.pointShadowVertexShader,pointShadowFragmentShader:c.pointShadowFragmentShader,uniforms:c.uniforms,textures:c.textures,sceneTextures:c.sceneTextures,graphTextures:c.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(c.vertexAttributes),uniformValuesAutoUpdate:o?F(e):i.uniformValuesAutoUpdate,transparent:c.renderState?.transparent,alphaTest:c.renderState?.alphaTest,depthTest:c.renderState?.depthTest,depthWrite:c.renderState?.depthWrite,side:c.renderState?.side,wireframe:i.wireframe});f.name=e.name||i.name||e.uuid,f.userData.pipelineOrigin={assetId:e.userData.assetId??i.userData.assetId,assetName:e.userData.assetName??i.userData.assetName,sourceUuid:e.uuid,sourceName:e.name,sourceType:e.type,sourceVersion:e.version},f.uniformValuesAutoUpdate=o?F(e):i.uniformValuesAutoUpdate,function(e,a){if(null==e)return;Object.assign(a,e)}(c.renderState,f),null!=u&&(u.material.dispose(),this.cacheValues.delete(u));const h={signature:m,compiled:c,material:f,inheritsWorldEnvironment:p,sourceVersion:e.version,sourceUniformValuesAutoVersion:o?O(e):i.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},d=l??new Map;return d.set(r,h),this.cache.set(i,d),this.cacheValues.add(h),z(i,f.uniforms),B(i,f),f}catch(e){let a=this.failedSignatures.get(i);if(null==a&&(a=new Map,this.failedSignatures.set(i,a)),a.get(r)!==m){a.set(r,m);const t=e instanceof Error?e.message:String(e),n=i.name||i.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${n}": ${t}`,{material:i,error:e})}return}}getOrCreateOutlineMaterial(a){let t=this.outlineMaterials.get(a);if(null==t){const i=a.nodeMaterialDefinition,s=a.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const o=M("outlineThickness",.003),m=M("outlineDarkening",.65),c=M("outlineAlpha",1),g=new L(d.position.xyz),w=new D(d.normal),I=i.transform?.multiplyVec(y(g,1))??y(g,1),S=v.modelViewMatrix.multiplyVec(I),x=h(v.normalMatrix.multiplyVec(w)),T=f(u(l(S.xyz),r(1e-4))).multiply(.5),E=S.xyz.add(x.multiplyScalar(o.multiply(T))),C=v.projectionMatrix.multiplyVec(S),b=v.projectionMatrix.multiplyVec(y(E,1)),U=(i.position??C).add(b.subtract(C)),A=p(V({color:s.rgb.multiplyScalar(r(1).subtract(m))}),a.outputOpacity.multiply(c));t=new n({color:A,position:U,opacity:a.outputOpacity,discard:i.discard,alphaTest:a.alphaTest,transparent:!0,fog:!1,outputEncoding:i.outputEncoding,uniforms:i.uniforms,uniformNodes:i.uniformNodes}),t.side=e.BackSide,t.depthTest=!0,t.depthWrite=!0,this.outlineMaterials.set(a,t),this.outlineUniformVersions.delete(a)}const i=a.userData?.outlineParameters,s=i?.thickness??.003,o=e.MathUtils.clamp(i?.darkening??.65,0,1),m=e.MathUtils.clamp(i?.alpha??a.opacity,0,1),c=t.uniforms.outlineThickness.value!==s||t.uniforms.outlineDarkening.value!==o||t.uniforms.outlineAlpha.value!==m;t.uniforms.outlineThickness.value=s,t.uniforms.outlineDarkening.value=o,t.uniforms.outlineAlpha.value=m,t.userData.outlineSource=a,t.uniformValuesAutoUpdate=a.uniformValuesAutoUpdate;let g=this.outlineUniformVersions.get(a);const w=a.uniformValuesAutoUpdate||null==g||g.version!==a.uniformValuesAutoVersion||g.uniforms!==a.uniforms;if(w){for(const e in a.uniforms)null!=t.uniforms[e]&&(t.uniforms[e].value=a.uniforms[e].value);g?(g.version=a.uniformValuesAutoVersion,g.uniforms=a.uniforms):(g={version:a.uniformValuesAutoVersion,uniforms:a.uniforms},this.outlineUniformVersions.set(a,g))}return a.uniformValuesAutoUpdate||!c&&!w||(t.uniformValuesNeedsUpdate=!0),t}compileFullscreen(e){const t=a({color:e.outputColor,wgslBindings:{...R,uniformExpressions:{},graphTextures:{...R.graphTextures,[N]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),n=t.syncLiveUniforms;return{...t,syncLiveUniforms(a){n(a),z(e,a)}}}getOrCreateMappedNodeMaterial(a){const t=function(a){const t=[a.vertexColors,a.transparent,a.alphaTest,a.side,a.depthTest,a.depthWrite,a.wireframe??!1];if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){if(t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.roughnessMap?a.roughnessMap.uuid:null,a.metalnessMap?a.metalnessMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null),a instanceof e.MeshPhysicalMaterial){t.push(a.clearcoat>0,a.iridescence>0,a.transmission>0,a.sheen>0,a.anisotropy>0,1.5!==a.ior,1!==a.specularIntensity,1!==a.specularColor.r||1!==a.specularColor.g||1!==a.specularColor.b);for(const e of H)t.push(a[e]?.uuid??null)}}else a instanceof e.MeshLambertMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.MeshToonMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.gradientMap?a.gradientMap.uuid:null):a instanceof e.MeshBasicMaterial?t.push(a.map?a.map.uuid:null,a.aoMap?a.aoMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.MeshPhongMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.SpriteMaterial&&t.push(a.map?a.map.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.sizeAttenuation);return t.join(",")}(a),n=this.mappedMaterialsCache.get(a),i=this.mappedMaterialsSignatures.get(a);if(null!=n&&i===t)return n;if(null!=n){n.dispose();const e=this.cache.get(n);if(null!=e){for(const a of e.values())a.material.dispose(),this.cacheValues.delete(a);this.cache.delete(n)}}const s=function(a){if(a instanceof e.SpriteMaterial){const e=new T;e.color=a.color,e.opacity=a.opacity,e.rotation=a.rotation,e.screenSpaceSize=a.sizeAttenuation?0:1,e.alphaTest=a.alphaTest,a.map&&(e.map=a.map),a.alphaMap&&(e.alphaMap=a.alphaMap);const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t}if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){const t=new w;if(t.color=a.color,t.opacity=a.opacity,t.roughness=a.roughness,t.metalness=a.metalness,t.vertexColor=a.vertexColors,a.map&&(t.map=o(a.map)),a.normalMap&&(t.normalMap=o(a.normalMap),t.normalScale=a.normalScale),a.roughnessMap&&(t.roughnessMap=o(a.roughnessMap)),a.metalnessMap&&(t.metalnessMap=o(a.metalnessMap)),a.aoMap&&(t.aoMap=o(a.aoMap),t.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(t.emissiveMap=o(a.emissiveMap)),a.lightMap&&(t.lightMap=o(a.lightMap),t.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(t.alphaMap=o(a.alphaMap)),t.emissive=a.emissive,t.emissiveIntensity=a.emissiveIntensity,t.envMap=a.envMap,t.envMapIntensity=a.envMapIntensity,t.alphaTest=a.alphaTest,a instanceof e.MeshPhysicalMaterial){for(const e of K)t[e]=a[e];for(const e of q)t[e]=a[e];for(const e of H)a[e]&&(t[e]=o(a[e]));t.clearcoatNormalScale=a.clearcoatNormalScale,t.iridescenceThicknessRange=new e.Vector2(...a.iridescenceThicknessRange),t.anisotropyRotation=a.anisotropyRotation}const n=t.build();return n.transparent=a.transparent,n.side=a.side,n.depthTest=a.depthTest,n.depthWrite=a.depthWrite,n.wireframe=a.wireframe,n}if(a instanceof e.MeshLambertMaterial){const e=new I;e.color=a.color,e.opacity=a.opacity,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.envMap=a.envMap,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}if(a instanceof e.MeshToonMaterial){const e=new S;e.color=a.color,e.opacity=a.opacity,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}if(a instanceof e.MeshBasicMaterial||a instanceof e.LineBasicMaterial){const t=new x;t.color=a.color,t.opacity=a.opacity,t.vertexColor=a.vertexColors,a instanceof e.MeshBasicMaterial&&(a.map&&(t.map=o(a.map)),a.aoMap&&(t.aoMap=o(a.aoMap),t.aoMapIntensity=a.aoMapIntensity),a.lightMap&&(t.lightMap=o(a.lightMap),t.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(t.alphaMap=o(a.alphaMap)),t.envMap=a.envMap),t.alphaTest=a.alphaTest;const n=t.build();return n.transparent=a.transparent,n.side=a.side,n.depthTest=a.depthTest,n.depthWrite=a.depthWrite,n.wireframe=a instanceof e.MeshBasicMaterial&&a.wireframe,n}if(a instanceof e.MeshPhongMaterial){const e=new w;e.color=a.color,e.opacity=a.opacity,e.roughness=Math.max(0,1-a.shininess/100),e.metalness=0,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.envMap=a.envMap,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}return null}(a);return null==s?null:(s.wireframe=a.wireframe??!1,this.mappedMaterialsCache.set(a,s),this.mappedMaterialsSignatures.set(a,t),a.addEventListener("dispose",()=>{const e=this.mappedMaterialsCache.get(a);if(null!=e){e.dispose(),this.mappedMaterialsCache.delete(a),this.mappedMaterialsSignatures.delete(a);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}}}),s)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,a]of this.observedNodeMaterials)e.removeEventListener("dispose",a);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,a){a.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,a){const t=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return a?`${t}|worldEnvironment:${this.worldEnvironmentRevision}`:t}prepareWorldEnvironment(a){var t,n,i,s,o,r;if(null!=a.envMap){const s=this.environmentTextureResolver?.(a.envMap)??a.envMap;return(t=a.uniforms).envMap??(t.envMap={value:s}),a.uniforms.envMap.value=s,(n=a.uniforms).envMapIntensity??(n.envMapIntensity={value:1}),(i=a.uniforms).envMapRotation??(i.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.delete(a),!1}return null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(a)&&(delete a.uniforms.envMap,delete a.uniforms.envMapIntensity,delete a.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(a)),!1):((s=a.uniforms).envMap??(s.envMap={value:this.worldEnvironment.texture}),a.uniforms.envMap.value=this.worldEnvironment.texture,(o=a.uniforms).envMapIntensity??(o.envMapIntensity={value:this.worldEnvironment.intensity}),a.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(r=a.uniforms).envMapRotation??(r.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.add(a),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const a=()=>{e.removeEventListener("dispose",a),this.observedNodeMaterials.delete(e);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const n=this.outlineMaterials.get(e);if(null!=n){const a=this.cache.get(n);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(n)}this.failedSignatures.delete(n),j.delete(n),n.dispose(),this.outlineMaterials.delete(e),this.outlineUniformVersions.delete(e)}this.failedSignatures.delete(e),j.delete(e)};this.observedNodeMaterials.set(e,a),e.addEventListener("dispose",a)}}function $(e,a,t=!1){const n=a.material;n.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(t||e.uniformValuesAutoUpdate||a.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(a.compiled.syncLiveUniforms(n.uniforms),z(e,n.uniforms),B(e,n),a.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,n.uniformValuesAutoUpdate||(n.uniformValuesNeedsUpdate=!0))}function z(e,a){let t=P.get(a);if(null==t){t=[];for(const e in a){const n=a[e],i=n.value,s=!0===i?.isVector2?2:!0===i?.isVector3?3:!0===i?.isVector4?4:!0===i?.isColor?5:0;t.push({name:e,target:n,copyKind:s})}P.set(a,t)}const n=e.uniforms;for(let e=0;e<t.length;e++){const a=t[e],i=n[a.name];if(null==i)continue;const s=i.value,o=a.target.value;if(s!==o){if(0!==a.copyKind){const e=s,t=o;if((2===a.copyKind?!0===e?.isVector2:3===a.copyKind?!0===e?.isVector3:4===a.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof t?.copy){t.copy(s);continue}}a.target.value=s}}}function B(a,t){const n=a.uniforms.envMapIntensity,i=t.uniforms.envMapIntensity;null!=n&&null!=i&&(i.value=n.value);const s=a.uniforms.envMapRotation?.value,o=t.uniforms.envMapRotation?.value;s instanceof e.Matrix3&&o instanceof e.Matrix3&&o.copy(s)}function _(e,a){for(const t in a.textures){const n=a.textures[t],i=e.uniforms[t]?.value;if(G(i)&&i!==n)return!1}return!0}function G(e){return!0===e?.isTexture}const K=["ior","specularIntensity","clearcoat","clearcoatRoughness","iridescence","iridescenceIOR","transmission","thickness","attenuationDistance","dispersion","sheen","sheenRoughness","anisotropy"],q=["specularColor","attenuationColor","sheenColor"],H=["specularIntensityMap","specularColorMap","clearcoatMap","clearcoatRoughnessMap","clearcoatNormalMap","iridescenceMap","iridescenceThicknessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","anisotropyMap"];function J(a,t){if(a instanceof e.SpriteMaterial){const n=t;t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),n.rotation=a.rotation,n.screenSpaceSize=a.sizeAttenuation?0:1}else if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){if(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=a.roughness),t.uniforms.metalness&&(t.uniforms.metalness.value=a.metalness),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity),t.uniforms.envMapIntensity&&(t.uniforms.envMapIntensity.value=a.envMapIntensity),a instanceof e.MeshPhysicalMaterial){for(const e of K)t.uniforms[e]&&(t.uniforms[e].value=a[e]);for(const n of q){const i=t.uniforms[n]?.value;i instanceof e.Vector3&&i.setFromColor(a[n])}const n=t.uniforms.clearcoatNormalScale?.value;n instanceof e.Vector2&&n.copy(a.clearcoatNormalScale),t.uniforms.iridescenceThicknessMin&&(t.uniforms.iridescenceThicknessMin.value=a.iridescenceThicknessRange[0]),t.uniforms.iridescenceThicknessMax&&(t.uniforms.iridescenceThicknessMax.value=a.iridescenceThicknessRange[1]);const i=t.uniforms.anisotropyDirection?.value;i instanceof e.Vector2&&i.set(Math.cos(a.anisotropyRotation),Math.sin(a.anisotropyRotation))}}else a instanceof e.MeshLambertMaterial||a instanceof e.MeshToonMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity)):a instanceof e.MeshBasicMaterial||a instanceof e.LineBasicMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),a instanceof e.MeshBasicMaterial&&(t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity))):a instanceof e.MeshPhongMaterial&&(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=Math.max(0,1-a.shininess/100)),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity))}/*
|
|
1
|
+
import{skyPosition as e}from"../scene/sky.js";import*as a from"three";import{compileNodeWebGpuFullscreen as t,compileNodeShaderMaterialForWebGpu as n,NodeShaderMaterial as i,deriveNodeShaderMaterial as s,webGpuRendererBindings as o,webGpuTiledRendererBindings as r,textureSampler2d as l,float as u,length as p,max as m,rgba as c,isWgslCompiler as f,isWgslFragmentCompiler as h,sqrt as d,normalize as M,transformed as v,uniformFloat as y,uniforms as g,vec4 as V,Vec3Node as w,toonMaterial as I}from"three-shader-graph";import{StandardShader as S}from"../shader/builtin/standard-shader.js";import{LambertShader as x}from"../shader/builtin/lambert-shader.js";import{ToonShader as T}from"../shader/builtin/toon-shader.js";import{UnlitShader as E}from"../shader/builtin/unlit-shader.js";import{SpriteShader as C}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as b}from"../shader-nodes/time.js";import{depthUniformName as U,farUniformName as A,nearUniformName as N,resolutionUniformName as k,sceneNormalUniformName as W}from"../shader-nodes/depth.js";import{sceneMapUniformName as R,transmissionMapUniformName as L}from"../shader-nodes/scene-sample.js";const D={...o,uniformExpressions:{...o.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[b]:{type:"float",expression:"rendererElapsedTime()"},[N]:{type:"float",expression:"rendererCameraNear()"},[A]:{type:"float",expression:"rendererCameraFar()"},[k]:{type:"vec2",expression:"rendererViewportSize()"}},graphTextures:{[L]:{resource:"physicalTransmissionSnapshot",dimension:"2d",sampleType:"float",sampler:"filtering",requiresLatePass:!0}},sceneTextures:{[R]:{semantic:"sceneColor",sampleType:"float"},[U]:{semantic:"sceneDepth",sampleType:"depth"}},attributes:{material:{shaderLocation:6,format:"float32x4",defaultValue:[0,0,0,0]},material2:{shaderLocation:7,format:"float32x4",defaultValue:[0,0,0,0]},hole:{shaderLocation:8,format:"float32",defaultValue:[0]},offset:{shaderLocation:9,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},velocity:{shaderLocation:10,format:"float32x4",stepMode:"instance",defaultValue:[0,0,0,0]},size:{shaderLocation:11,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},rotation:{shaderLocation:12,format:"float32",stepMode:"instance",defaultValue:[0]},particleData:{shaderLocation:13,format:"float32x3",stepMode:"instance",defaultValue:[1,1,0]},particleColor:{shaderLocation:14,format:"float32x4",stepMode:"instance",defaultValue:[1,1,1,1]}}};class F extends w{constructor(e){super(),this.fallback=e}compile(e){if(!f(e))return{out:e.get(this.fallback)};if(h(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const a=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${a} = input.position;\n#endif`,out:a}}}class O extends w{constructor(e){super(),this.fallback=e}compile(e){if(!f(e))return{out:e.get(this.fallback)};if(h(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const a=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${a} = input.normal;\n#endif`,out:a}}}export function setMaterialUniformValuesAutoUpdate(e,a){e.uniformValuesAutoUpdate=a}export function markMaterialUniformValuesNeedUpdate(e){const a=e;"uniformValuesNeedsUpdate"in a?a.uniformValuesNeedsUpdate=!0:a.uniformValuesAutoVersion=(a.uniformValuesAutoVersion??0)+1}function P(e){return!1!==e.uniformValuesAutoUpdate}function j(e){return e.uniformValuesAutoVersion??0}export function withThreeDefaultVertexAttributeValues(e){return e.map(e=>"uv1"===e.name&&null==e.defaultValue?{...e,defaultValue:[0,0]}:e)}const $=new WeakMap,z=new WeakMap;export function createNodeMaterialSignature(e){const a=z.get(e);if(null!=a)return a;const t=JSON.stringify({version:e.version,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,alphaTest:e.alphaTest,alphaToCoverage:e.alphaToCoverage,blending:e.blending,colorWrite:e.colorWrite,depthFunc:e.depthFunc,depthTest:e.depthTest,depthWrite:e.depthWrite,polygonOffset:e.polygonOffset,polygonOffsetFactor:e.polygonOffsetFactor,polygonOffsetUnits:e.polygonOffsetUnits,premultipliedAlpha:e.premultipliedAlpha,side:e.side,stencilWrite:e.stencilWrite,transparent:e.transparent,wireframe:e.wireframe});return z.set(e,t),t}export class NodeMaterialWebGpuResolver{constructor(e,a,t){this.webGpu=e,this.mrtResolver=a,this.environmentTextureResolver=t,this.cache=new WeakMap,this.failedSignatures=new WeakMap,this.mappedMaterialsCache=new WeakMap,this.mappedMaterialsSignatures=new WeakMap,this.observedNodeMaterials=new Map,this.outlineMaterials=new WeakMap,this.outlineUniformVersions=new WeakMap,this.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const a=e?.texture??null,t=e?.intensity??0;if(this.worldEnvironmentTexture!==a||this.worldEnvironmentIntensity!==t){if(this.worldEnvironmentTexture!==a)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=t,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=a,this.worldEnvironmentIntensity=t}}resolve(a,t=void 0){let o,l=!1;if(a instanceof i)o=a,this.observeNodeMaterial(o);else{const e=this.getOrCreateMappedNodeMaterial(a);if(null==e)return;o=e,l=!0}if("outline"===t){if(null==o.outputAlbedo)return;l&&X(a,o),o.userData.outlineParameters=a.userData?.outlineParameters,o=this.getOrCreateOutlineMaterial(o),l=!1}o.visible=a.visible,l&&(o.userData.receiveDecals=a.userData.receiveDecals);const u=t??"default",p=this.cache.get(o),m=p?.get(u);if(l&&null!=m&&m.sourceVersion===a.version&&m.worldEnvironmentRevision===this.worldEnvironmentRevision){const e=P(a),t=j(a);return m.material.uniformValuesAutoUpdate=e,this.syncInheritedWorldEnvironmentSource(o,m),e||m.sourceUniformValuesAutoVersion!==t?(X(a,o),m.compiled.syncLiveUniforms(m.material.uniforms),_(o,m.material.uniforms),G(o,m.material),m.sourceUniformValuesAutoVersion=t,e||(m.material.uniformValuesNeedsUpdate=!0),m.material):m.material}if(!l&&null!=m&&m.sourceVersion===a.version&&m.worldEnvironmentRevision===this.worldEnvironmentRevision&&K(o,m.compiled))return this.syncInheritedWorldEnvironmentSource(o,m),B(o,m),m.material;l&&X(a,o);const c=this.prepareWorldEnvironment(o),f=this.getNodeMaterialSignature(o,c);if(m?.signature===f&&K(o,m.compiled))return l?(m.material.uniformValuesAutoUpdate=P(a),m.compiled.syncLiveUniforms(m.material.uniforms),_(o,m.material.uniforms),G(o,m.material),m.sourceUniformValuesAutoVersion=j(a),m.material.uniformValuesAutoUpdate||(m.material.uniformValuesNeedsUpdate=!0)):B(o,m,!0),m.sourceVersion=a.version,m.worldEnvironmentRevision=this.worldEnvironmentRevision,m.material;try{const i=this.mrtResolver?.(o,t),h=!0===a.userData.isSky?s(o,{position:e,fog:o.fog}):o,d=n(h,"opaque"===t?{...D,arrays:r.arrays}:D,i),M=new this.webGpu.WGSLShaderMaterial({vertexShader:d.vertexShader,fragmentShader:d.fragmentShader,depthVertexShader:d.depthVertexShader,depthFragmentShader:d.depthFragmentShader,pointShadowVertexShader:d.pointShadowVertexShader,pointShadowFragmentShader:d.pointShadowFragmentShader,uniforms:d.uniforms,textures:d.textures,sceneTextures:d.sceneTextures,graphTextures:d.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(d.vertexAttributes),uniformValuesAutoUpdate:l?P(a):o.uniformValuesAutoUpdate,transparent:d.renderState?.transparent,alphaTest:d.renderState?.alphaTest,depthTest:d.renderState?.depthTest,depthWrite:d.renderState?.depthWrite,side:d.renderState?.side,wireframe:o.wireframe});M.name=a.name||o.name||a.uuid,M.userData.pipelineOrigin={assetId:a.userData.assetId??o.userData.assetId,assetName:a.userData.assetName??o.userData.assetName,sourceUuid:a.uuid,sourceName:a.name,sourceType:a.type,sourceVersion:a.version},M.uniformValuesAutoUpdate=l?P(a):o.uniformValuesAutoUpdate,function(e,a){if(null==e)return;Object.assign(a,e)}(d.renderState,M),null!=m&&(m.material.dispose(),this.cacheValues.delete(m));const v={signature:f,compiled:d,material:M,inheritsWorldEnvironment:c,sourceVersion:a.version,sourceUniformValuesAutoVersion:l?j(a):o.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},y=p??new Map;return y.set(u,v),this.cache.set(o,y),this.cacheValues.add(v),_(o,M.uniforms),G(o,M),M}catch(e){let a=this.failedSignatures.get(o);if(null==a&&(a=new Map,this.failedSignatures.set(o,a)),a.get(u)!==f){a.set(u,f);const t=e instanceof Error?e.message:String(e),n=o.name||o.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${n}": ${t}`,{material:o,error:e})}return}}getOrCreateOutlineMaterial(e){let t=this.outlineMaterials.get(e);if(null==t){const n=e.nodeMaterialDefinition,s=e.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const o=y("outlineThickness",.003),r=y("outlineDarkening",.65),l=y("outlineAlpha",1),f=new F(v.position.xyz),h=new O(v.normal),w=n.transform?.multiplyVec(V(f,1))??V(f,1),S=g.modelViewMatrix.multiplyVec(w),x=M(g.normalMatrix.multiplyVec(h)),T=d(m(p(S.xyz),u(1e-4))).multiply(.5),E=S.xyz.add(x.multiplyScalar(o.multiply(T))),C=g.projectionMatrix.multiplyVec(S),b=g.projectionMatrix.multiplyVec(V(E,1)),U=(n.position??C).add(b.subtract(C)),A=c(I({color:s.rgb.multiplyScalar(u(1).subtract(r))}),e.outputOpacity.multiply(l));t=new i({color:A,position:U,opacity:e.outputOpacity,discard:n.discard,alphaTest:e.alphaTest,transparent:!0,fog:!1,outputEncoding:n.outputEncoding,uniforms:n.uniforms,uniformNodes:n.uniformNodes}),t.side=a.BackSide,t.depthTest=!0,t.depthWrite=!0,this.outlineMaterials.set(e,t),this.outlineUniformVersions.delete(e)}const n=e.userData?.outlineParameters,s=n?.thickness??.003,o=a.MathUtils.clamp(n?.darkening??.65,0,1),r=a.MathUtils.clamp(n?.alpha??e.opacity,0,1),l=t.uniforms.outlineThickness.value!==s||t.uniforms.outlineDarkening.value!==o||t.uniforms.outlineAlpha.value!==r;t.uniforms.outlineThickness.value=s,t.uniforms.outlineDarkening.value=o,t.uniforms.outlineAlpha.value=r,t.userData.outlineSource=e,t.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate;let f=this.outlineUniformVersions.get(e);const h=e.uniformValuesAutoUpdate||null==f||f.version!==e.uniformValuesAutoVersion||f.uniforms!==e.uniforms;if(h){for(const a in e.uniforms)null!=t.uniforms[a]&&(t.uniforms[a].value=e.uniforms[a].value);f?(f.version=e.uniformValuesAutoVersion,f.uniforms=e.uniforms):(f={version:e.uniformValuesAutoVersion,uniforms:e.uniforms},this.outlineUniformVersions.set(e,f))}return e.uniformValuesAutoUpdate||!l&&!h||(t.uniformValuesNeedsUpdate=!0),t}compileFullscreen(e){const a=t({color:e.outputColor,wgslBindings:{...D,uniformExpressions:{},graphTextures:{...D.graphTextures,[W]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),n=a.syncLiveUniforms;return{...a,syncLiveUniforms(a){n(a),_(e,a)}}}getOrCreateMappedNodeMaterial(e){const t=function(e){const t=[e.vertexColors,e.transparent,e.alphaTest,e.side,e.depthTest,e.depthWrite,e.wireframe??!1];if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){if(t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.roughnessMap?e.roughnessMap.uuid:null,e.metalnessMap?e.metalnessMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null),e instanceof a.MeshPhysicalMaterial){t.push(e.clearcoat>0,e.iridescence>0,e.transmission>0,e.sheen>0,e.anisotropy>0,1.5!==e.ior,1!==e.specularIntensity,1!==e.specularColor.r||1!==e.specularColor.g||1!==e.specularColor.b);for(const a of Q)t.push(e[a]?.uuid??null)}}else e instanceof a.MeshLambertMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.MeshToonMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.gradientMap?e.gradientMap.uuid:null):e instanceof a.MeshBasicMaterial?t.push(e.map?e.map.uuid:null,e.aoMap?e.aoMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.MeshPhongMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.SpriteMaterial&&t.push(e.map?e.map.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.sizeAttenuation);return t.join(",")}(e),n=this.mappedMaterialsCache.get(e),i=this.mappedMaterialsSignatures.get(e);if(null!=n&&i===t)return n;if(null!=n){n.dispose();const e=this.cache.get(n);if(null!=e){for(const a of e.values())a.material.dispose(),this.cacheValues.delete(a);this.cache.delete(n)}}const s=function(e){if(e instanceof a.SpriteMaterial){const a=new C;a.color=e.color,a.opacity=e.opacity,a.rotation=e.rotation,a.screenSpaceSize=e.sizeAttenuation?0:1,a.alphaTest=e.alphaTest,e.map&&(a.map=e.map),e.alphaMap&&(a.alphaMap=e.alphaMap);const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t}if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){const t=new S;if(t.color=e.color,t.opacity=e.opacity,t.roughness=e.roughness,t.metalness=e.metalness,t.vertexColor=e.vertexColors,e.map&&(t.map=l(e.map)),e.normalMap&&(t.normalMap=l(e.normalMap),t.normalScale=e.normalScale),e.roughnessMap&&(t.roughnessMap=l(e.roughnessMap)),e.metalnessMap&&(t.metalnessMap=l(e.metalnessMap)),e.aoMap&&(t.aoMap=l(e.aoMap),t.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(t.emissiveMap=l(e.emissiveMap)),e.lightMap&&(t.lightMap=l(e.lightMap),t.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(t.alphaMap=l(e.alphaMap)),t.emissive=e.emissive,t.emissiveIntensity=e.emissiveIntensity,t.envMap=e.envMap,t.envMapIntensity=e.envMapIntensity,t.alphaTest=e.alphaTest,e instanceof a.MeshPhysicalMaterial){for(const a of H)t[a]=e[a];for(const a of J)t[a]=e[a];for(const a of Q)e[a]&&(t[a]=l(e[a]));t.clearcoatNormalScale=e.clearcoatNormalScale,t.iridescenceThicknessRange=new a.Vector2(...e.iridescenceThicknessRange),t.anisotropyRotation=e.anisotropyRotation}const n=t.build();return n.transparent=e.transparent,n.side=e.side,n.depthTest=e.depthTest,n.depthWrite=e.depthWrite,n.wireframe=e.wireframe,n}if(e instanceof a.MeshLambertMaterial){const a=new x;a.color=e.color,a.opacity=e.opacity,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.envMap=e.envMap,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}if(e instanceof a.MeshToonMaterial){const a=new T;a.color=e.color,a.opacity=e.opacity,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}if(e instanceof a.MeshBasicMaterial||e instanceof a.LineBasicMaterial){const t=new E;t.color=e.color,t.opacity=e.opacity,t.vertexColor=e.vertexColors,e instanceof a.MeshBasicMaterial&&(e.map&&(t.map=l(e.map)),e.aoMap&&(t.aoMap=l(e.aoMap),t.aoMapIntensity=e.aoMapIntensity),e.lightMap&&(t.lightMap=l(e.lightMap),t.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(t.alphaMap=l(e.alphaMap)),t.envMap=e.envMap),t.alphaTest=e.alphaTest;const n=t.build();return n.transparent=e.transparent,n.side=e.side,n.depthTest=e.depthTest,n.depthWrite=e.depthWrite,n.wireframe=e instanceof a.MeshBasicMaterial&&e.wireframe,n}if(e instanceof a.MeshPhongMaterial){const a=new S;a.color=e.color,a.opacity=e.opacity,a.roughness=Math.max(0,1-e.shininess/100),a.metalness=0,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.envMap=e.envMap,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}return null}(e);return null==s?null:(s.wireframe=e.wireframe??!1,this.mappedMaterialsCache.set(e,s),this.mappedMaterialsSignatures.set(e,t),e.addEventListener("dispose",()=>{const a=this.mappedMaterialsCache.get(e);if(null!=a){a.dispose(),this.mappedMaterialsCache.delete(e),this.mappedMaterialsSignatures.delete(e);const t=this.cache.get(a);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(a)}}}),s)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,a]of this.observedNodeMaterials)e.removeEventListener("dispose",a);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,a){a.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,a){const t=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return a?`${t}|worldEnvironment:${this.worldEnvironmentRevision}`:t}prepareWorldEnvironment(e){var t,n,i,s,o,r;if(null!=e.envMap){const s=this.environmentTextureResolver?.(e.envMap)??e.envMap;return(t=e.uniforms).envMap??(t.envMap={value:s}),e.uniforms.envMap.value=s,(n=e.uniforms).envMapIntensity??(n.envMapIntensity={value:1}),(i=e.uniforms).envMapRotation??(i.envMapRotation={value:new a.Matrix3}),this.worldEnvironmentMaterials.delete(e),!1}return null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(e)&&(delete e.uniforms.envMap,delete e.uniforms.envMapIntensity,delete e.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(e)),!1):((s=e.uniforms).envMap??(s.envMap={value:this.worldEnvironment.texture}),e.uniforms.envMap.value=this.worldEnvironment.texture,(o=e.uniforms).envMapIntensity??(o.envMapIntensity={value:this.worldEnvironment.intensity}),e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(r=e.uniforms).envMapRotation??(r.envMapRotation={value:new a.Matrix3}),this.worldEnvironmentMaterials.add(e),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const a=()=>{e.removeEventListener("dispose",a),this.observedNodeMaterials.delete(e);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const n=this.outlineMaterials.get(e);if(null!=n){const a=this.cache.get(n);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(n)}this.failedSignatures.delete(n),z.delete(n),n.dispose(),this.outlineMaterials.delete(e),this.outlineUniformVersions.delete(e)}this.failedSignatures.delete(e),z.delete(e)};this.observedNodeMaterials.set(e,a),e.addEventListener("dispose",a)}}function B(e,a,t=!1){const n=a.material;n.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(t||e.uniformValuesAutoUpdate||a.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(a.compiled.syncLiveUniforms(n.uniforms),_(e,n.uniforms),G(e,n),a.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,n.uniformValuesAutoUpdate||(n.uniformValuesNeedsUpdate=!0))}function _(e,a){let t=$.get(a);if(null==t){t=[];for(const e in a){const n=a[e],i=n.value,s=!0===i?.isVector2?2:!0===i?.isVector3?3:!0===i?.isVector4?4:!0===i?.isColor?5:0;t.push({name:e,target:n,copyKind:s})}$.set(a,t)}const n=e.uniforms;for(let e=0;e<t.length;e++){const a=t[e],i=n[a.name];if(null==i)continue;const s=i.value,o=a.target.value;if(s!==o){if(0!==a.copyKind){const e=s,t=o;if((2===a.copyKind?!0===e?.isVector2:3===a.copyKind?!0===e?.isVector3:4===a.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof t?.copy){t.copy(s);continue}}a.target.value=s}}}function G(e,t){const n=e.uniforms.envMapIntensity,i=t.uniforms.envMapIntensity;null!=n&&null!=i&&(i.value=n.value);const s=e.uniforms.envMapRotation?.value,o=t.uniforms.envMapRotation?.value;s instanceof a.Matrix3&&o instanceof a.Matrix3&&o.copy(s)}function K(e,a){for(const t in a.textures){const n=a.textures[t],i=e.uniforms[t]?.value;if(q(i)&&i!==n)return!1}return!0}function q(e){return!0===e?.isTexture}const H=["ior","specularIntensity","clearcoat","clearcoatRoughness","iridescence","iridescenceIOR","transmission","thickness","attenuationDistance","dispersion","sheen","sheenRoughness","anisotropy"],J=["specularColor","attenuationColor","sheenColor"],Q=["specularIntensityMap","specularColorMap","clearcoatMap","clearcoatRoughnessMap","clearcoatNormalMap","iridescenceMap","iridescenceThicknessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","anisotropyMap"];function X(e,t){if(e instanceof a.SpriteMaterial){const n=t;t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),n.rotation=e.rotation,n.screenSpaceSize=e.sizeAttenuation?0:1}else if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){if(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=e.roughness),t.uniforms.metalness&&(t.uniforms.metalness.value=e.metalness),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity),t.uniforms.envMapIntensity&&(t.uniforms.envMapIntensity.value=e.envMapIntensity),e instanceof a.MeshPhysicalMaterial){for(const a of H)t.uniforms[a]&&(t.uniforms[a].value=e[a]);for(const n of J){const i=t.uniforms[n]?.value;i instanceof a.Vector3&&i.setFromColor(e[n])}const n=t.uniforms.clearcoatNormalScale?.value;n instanceof a.Vector2&&n.copy(e.clearcoatNormalScale),t.uniforms.iridescenceThicknessMin&&(t.uniforms.iridescenceThicknessMin.value=e.iridescenceThicknessRange[0]),t.uniforms.iridescenceThicknessMax&&(t.uniforms.iridescenceThicknessMax.value=e.iridescenceThicknessRange[1]);const i=t.uniforms.anisotropyDirection?.value;i instanceof a.Vector2&&i.set(Math.cos(e.anisotropyRotation),Math.sin(e.anisotropyRotation))}}else e instanceof a.MeshLambertMaterial||e instanceof a.MeshToonMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity)):e instanceof a.MeshBasicMaterial||e instanceof a.LineBasicMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),e instanceof a.MeshBasicMaterial&&(t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity))):e instanceof a.MeshPhongMaterial&&(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=Math.max(0,1-e.shininess/100)),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity))}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -4,8 +4,8 @@ import type { WorldEnvironmentState } from './environment.js';
|
|
|
4
4
|
import type { RenderingBackendDriver } from './rendering-backend.js';
|
|
5
5
|
import type { PostProcessEffectStage } from './post-process-effect.js';
|
|
6
6
|
import type { DlssQualityMode } from './upscaling-pass.js';
|
|
7
|
-
import type { BloomOptions, ColorGradingOptions, DepthOfFieldOptions, FXAAOptions, FrameGraphBuilder, GTAOOptions, GTAOQuality, OutlineOptions, OutlineInstanceSelection, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, SSROptions, RendererFrameProfile, SMAAOptions, TemporalAAOptions, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
8
|
-
export type { RendererFrameProfile, GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
7
|
+
import type { BloomOptions, ColorGradingOptions, DepthOfFieldOptions, FXAAOptions, FrameGraphBuilder, GTAOOptions, GTAOQuality, OutlineOptions, OutlineInstanceSelection, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, SSROptions, RendererFrameProfile, RendererSceneCapture, SMAAOptions, TemporalAAOptions, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
8
|
+
export type { RendererFrameProfile, RendererSceneCapture, RendererSceneCaptureOptions, RendererSceneCapturePostProcessContext, GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
9
9
|
type SupportedCamera = THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
10
10
|
export type AntiAliasingMode = 'off' | 'fxaa' | 'smaa' | 'taa';
|
|
11
11
|
export type ExperimentalWebGpuRenderGraphExtension = ((graph: FrameGraphBuilder, color: string) => void) & {
|
|
@@ -133,6 +133,7 @@ export declare class ExperimentalWebGpuBackend implements RenderingBackendDriver
|
|
|
133
133
|
initTexture(texture: THREE.Texture): void;
|
|
134
134
|
setPostProcessEffects(effects: readonly ExperimentalWebGpuPostProcessEffect[]): void;
|
|
135
135
|
getDevice(): GPUDevice | null;
|
|
136
|
+
createSceneCapture(canvas: HTMLCanvasElement | null, width?: number, height?: number): RendererSceneCapture;
|
|
136
137
|
setRenderGraphExtensions(extensions: Iterable<ExperimentalWebGpuRenderGraphExtension>): void;
|
|
137
138
|
setPresentationExtensions(extensions: Iterable<WebGpuPresentationExtension>): void;
|
|
138
139
|
setEnableOutlines(enabled: boolean): void;
|
|
@@ -156,6 +157,7 @@ export declare class ExperimentalWebGpuBackend implements RenderingBackendDriver
|
|
|
156
157
|
resetViewHistory(): void;
|
|
157
158
|
compile(scene: THREE.Scene, camera: SupportedCamera): Promise<void>;
|
|
158
159
|
createStaticDrawSet(root: THREE.Object3D, label: string, allowUnsortedLateDraws?: boolean, onUnsupported?: 'throw' | 'skip'): ExperimentalWebGpuStaticDrawSet | null;
|
|
160
|
+
registerStaticSpatialObject(root: THREE.Object3D): import('@hology/webgpu-renderer').StaticSpatialObject;
|
|
159
161
|
render(scene: THREE.Scene, camera: SupportedCamera, timeSeconds: number): void;
|
|
160
162
|
setMotionBlurOptions(options: MotionBlurOptions): void;
|
|
161
163
|
setGTAOOptions(options: GTAOOptions): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"three";import{NodeMaterialWebGpuResolver as t}from"./node-material-webgpu-resolver.js";import{configureWebGpuRuntimeBindings as i}from"./webgpu-runtime-bridge.js";import{float as n,varyingTransformed as r,vec4 as a}from"three-shader-graph";import{NodeShaderMaterial as o}from"../shader-nodes/index.js";import{sceneMapUniformName as s}from"../shader-nodes/scene-sample.js";import{depthUniformName as l}from"../shader-nodes/depth.js";import{MATERIAL_FLAG_ALPHA_TEST as d,MATERIAL_FLAG_RECEIVE_DECALS as c}from"../shader-nodes/material-flags.js";import{createMotionVectorOutput as h}from"./motion-vector-node.js";export class ExperimentalWebGpuBackend{constructor(e,t,i,n,r,a,o,s,l,d,c,h,u,p,m,g,f,v,S,b,P,x){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=r,this.fxaa=a,this.smaa=o,this.gtao=s,this.ssr=l,this.taa=d,this.motionBlur=c,this.volumetricFog=h,this.colorGrading=u,this.depthOfField=p,this.outline=m,this.postProcessEffects=g,this.renderGraphExtensions=f,this.presentationExtensions=v,this.antiAliasingState=S,this.directionalShadowState=b,this.nativeDlss=P,this.kind="webgpu",this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,this.secondaryMotionPrepared=!1,this.canvas=x}static async probeAvailability(){if("undefined"==typeof navigator||!("gpu"in navigator))return{available:!1,reason:"The runtime does not expose navigator.gpu."};try{const e=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});return null==e?{available:!1,reason:"No WebGPU adapter is available."}:{available:!0,adapter:e}}catch(e){return{available:!1,reason:`Requesting a WebGPU adapter failed: ${e instanceof Error?e.message:String(e)}`}}}static async create(m={},g){const f=await import("@hology/webgpu-renderer");i({registerPipelineDiagnosticOrigin:f.registerPipelineDiagnosticOrigin,createComputeKernel:(e,t)=>new f.ComputeKernel(e,t),buildParticleLightingShaderHeader:f.buildParticleLightingShaderHeader});const v=document.createElement("canvas");v.dataset.hologyRenderer="webgpu-experimental";const S=new f.WGSLShaderMaterial({vertexShader:u,fragmentShader:p}),b=!1!==m.nativeUpscaling&&"dlss"===m.nativeUpscaling?.method,P=b?(await import("./native-dlss-upscaler.js")).createNativeDlssUpscaler(m.nativeUpscaling?.mode??"quality"):null,x=null!=P;S.side=f.DoubleSide;const w=f,y=null!=m.motionBlur&&!1!==m.motionBlur,D=!1!==m.gtao&&(null==m.gtao||!1!==m.gtao.temporal),M=!1!==m.volumetricFog&&(null==m.volumetricFog||!1!==m.volumetricFog.temporal),E=x?"off":b?"taa":null!=(O=m).antiAliasing?O.antiAliasing:null!=O.taa&&!1!==O.taa?"taa":null!=O.smaa&&!1!==O.smaa?"smaa":null!=O.fxaa&&!1!==O.fxaa?"fxaa":!1===O.taa?"off":"taa";var O;const F=null!=m.antiAliasing,L=y||D||M||(F||"taa"===E)||x;let C=null;const G=new t(w,(e,t)=>"opaque"===t?[e.outputColor.xyz.rgba(n(e.alphaTest>0?d:0).add(!1===e.userData.receiveDecals?0:c)),a((e.outputNormal??r.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??n(1)),...L?[h(e)]:[]]:void 0,e=>C?.getEnvironmentTexture(e)??e),R=new e.MeshStandardMaterial({color:8688803,roughness:1});if(null==G.resolve(R,"opaque"))throw S.dispose(),R.dispose(),new Error("Failed to compile the WebGPU G-buffer fallback material.");const T=!1===m.gtao?null:new f.GTAOEffect({normalSpace:"view",...f.GTAO_PRESETS.high,...m.gtao??{}}),A=!1===m.ssr||null==m.ssr?null:new f.SSREffect({normalSpace:"view",resolutionScale:.5,...m.ssr??{}}),B=!1===m.bloom?null:new f.BloomEffect({threshold:1,strength:.9,radius:.2,...m.bloom??{}}),U=F||!1!==m.fxaa&&"fxaa"===E?new f.FXAAEffect(!1===m.fxaa?{}:m.fxaa):null,W=F||!1!==m.smaa&&"smaa"===E?new f.SMAAEffect(!1===m.smaa?{}:m.smaa):null,k=x||F||!1!==m.taa&&"taa"===E?new f.TemporalAAEffect({renderScale:1,...!1===m.taa?{}:m.taa}):null,V={mode:E},I=!1===m.motionBlur||null==m.motionBlur?null:new f.MotionBlurEffect(m.motionBlur),N=m.volumetricFog||void 0,j=!1===m.volumetricFog?null:new f.VolumetricFogEffect(void 0,{...f.VOLUMETRIC_FOG_PRESETS.high,maxDistance:64,spatialJitter:!0,scatteringIntensity:Math.PI,...N,temporal:!1!==N?.temporal&&{...f.VOLUMETRIC_FOG_PRESETS.high.temporal,...N?.temporal},blur:!1!==N?.blur&&{...!1===f.VOLUMETRIC_FOG_PRESETS.high.blur?{}:f.VOLUMETRIC_FOG_PRESETS.high.blur,depthAwareUpsample:!0,...N?.blur}}),H=!1===m.colorGrading?null:new f.ColorGradingEffect({enabled:!1,...m.colorGrading??{}}),$=!1===m.depthOfField?null:new f.DepthOfFieldEffect({enabled:!1,...m.depthOfField??{}}),_=!1===m.outline?null:new f.OutlineEffect({enabled:!1,...m.outline??{}}),q=[],z=new WeakMap,J=new Set,K=[],Z=[],Q=(e,t,i)=>{let n=i;const r=q.filter(e=>e.enabled&&e.stage===t).sort((e,t)=>e.priority-t.priority||e.id-t.id);for(const t of r){if(!(t.material instanceof o)){const e=`${t.id}:material`;J.has(e)||(J.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: only NodeShaderMaterial effects are supported.`));continue}try{let i=z.get(t.material);null!=i&&i.version===t.material.version||(i={version:t.material.version,shader:G.compileFullscreen(t.material),diagnosticOrigin:{key:"post-process:"+String(t.material.userData.assetId??(t.material.name||t.material.uuid)),material:{name:t.material.name,uuid:t.material.uuid,version:t.material.version,assetId:t.material.userData.assetId,assetName:t.material.userData.assetName}}},z.set(t.material,i));const r=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,diagnosticOrigin:i.diagnosticOrigin,shader:i.shader,inputOverrides:{[s]:n},outputs:r}),n=r}catch(e){const i=`${t.id}:compile:${t.material.version}`;J.has(i)||(J.add(i),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: ${e instanceof Error?e.message:String(e)}`,e))}}return n},X={enabled:!0},Y=new f.WebGpuRenderer({canvas:v,fallbackMaterial:S,materialResolver:(e,t)=>G.resolve(e,t),invokeObjectRenderCallbacks:!1,hiZOcclusionCulling:!0,renderGraphProfiling:!1,sampleCount:1,multiDrawIndirect:!1,nativePostSubmit:P?.postSubmit,presentationOverlay:e=>{for(const t of Z)t(e)}});Y.setRenderScale("taa"===E?k?.renderScale??1:1),Y.setRenderGraphBuilder((e,t)=>{const i=new f.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba8unorm"}),r=L?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of K)"beforeScene"===e.stage&&e(i,i.sceneColor);X.enabled&&i.addDirectionalShadowPass(),i.addPointShadowPass(),i.addSpotShadowPass(),i.addDepthPrepass(),i.addHiZPasses(),i.addVisibilityPass(),i.addMaterialPass({name:"OpaqueGBufferPass",outputs:null==r?[i.sceneColor,n]:[i.sceneColor,n,r],drawStage:"opaque",loadDepth:!0}),i.addHiZHistoryPass("OpaqueGBufferPass");let a=i.sceneColor;if(T?.enabled){const e=T.addPasses(i,{depth:i.mainDepth,normal:n,velocity:r??void 0});a=T.addCompositePass(i,a,e)}null!=A&&(a=A.addPasses(i,{sceneColor:a,depth:i.mainDepth,normalRoughness:n}));const o=new Set(K.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(a,{sceneColor:o.has("sceneColorSnapshot"),sceneDepth:o.has("sceneDepthSnapshot")||q.some(e=>e.enabled&&null!=e.material.uniforms[l])}),a=Q(i,"beforeFog",a),i.addLatePass(a);for(const e of K)null!=e.stage&&"afterScene"!==e.stage||e(i,a);null!=j&&(a=j.addPasses(i,{sceneColor:a,depth:i.mainDepth,velocity:r??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=I&&null!=r&&(a=I.addPass(i,a,r,i.mainDepth)),null!=B&&(a=B.addPass(i,a)),a=Q(i,"beforeOutline",a),null!=_&&(a=_.addPass(i,a)),a=Q(i,"beforeDepthOfField",a),null!=$&&(a=$.addPass(i,a,i.mainDepth)),a=Q(i,"beforeColorAdjustment",a),null!=H&&(a=H.addPass(i,a)),a=Q(i,"beforeAntiAliasing",a);let s="taa"===V.mode&&null!=k?k.addPass(i,a,i.mainDepth,r??void 0):a;"smaa"===V.mode&&null!=W?s=W.addPass(i,s):"fxaa"===V.mode&&null!=U&&(s=U.addPass(i,s)),s=Q(i,"beforeOutput",s);for(const e of K)"beforePresent"===e.stage&&e(i,s);!0===P?.enabled&&null!=r?P.addInputPass(i,s,r):i.present(s)});try{return await Y.initialize(g),C=new ExperimentalWebGpuBackend(Y,S,G,R,B,U,W,T,A,k,I,j,H,$,_,q,K,Z,V,X,P,v),C}catch(e){throw Y.destroy(),S.dispose(),G.dispose(),R.dispose(),T?.dispose(),W?.dispose(),I?.dispose(),j?.dispose(),_?.dispose(),e}}static supportsCamera(t){return t instanceof e.PerspectiveCamera||t instanceof e.OrthographicCamera}setSize(e,t,i,n=1){const r=this.canvas.width,a=this.canvas.height;let o=Math.min(1,Math.max(.25,n));if(!0===this.nativeDlss?.enabled){const n=Math.max(1,Math.floor(e*i)),r=Math.max(1,Math.floor(t*i));o=this.nativeDlss.getRenderScale(n,r)}const s=o!==this.renderScale;this.renderScale=o,this.renderer.setRenderScale(o),this.taa?.setRenderScale(o),this.renderer.setSize(e,t,i),(s||this.canvas.width!==r||this.canvas.height!==a)&&this.resetViewHistory()}initTexture(e){this.renderer.initTexture(e)}setPostProcessEffects(e){this.postProcessEffects.splice(0,this.postProcessEffects.length,...e);for(const t of e){if("beforeLut"!==t.stage)continue;const e=`${t.id}:${t.stage}`;this.warnedUnsupportedPostProcessStages.has(e)||(this.warnedUnsupportedPostProcessStages.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: stage "${t.stage}" has no native WebGPU anchor.`))}}getDevice(){return this.renderer.getDevice()}setRenderGraphExtensions(e){this.renderGraphExtensions.length=0;for(const t of e)this.renderGraphExtensions.push(t)}setPresentationExtensions(e){this.presentationExtensions.length=0;for(const t of e)this.presentationExtensions.push(t)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=e)}setTiledLightingEnabled(e){this.renderer.setTiledLightingEnabled(e)}setDynamicBatchingEnabled(e){this.renderer.setDynamicBatchingEnabled(e)}setSelectedObjects(e){this.outline?.setSelectedObjects(e)}setSelectedObjectInstances(e){this.outline?.setSelectedInstances(e)}setCascadedShadowRanges(e,t=[]){this.renderer.setCascadedShadowRanges(e,t),this.volumetricFog?.setCascadedDirectionalLights(t)}setDirectionalShadowUpdateOptions(e){this.renderer.setDirectionalShadowUpdateOptions(e)}invalidateDirectionalShadows(){this.renderer.invalidateDirectionalShadows()}setDirectionalShadowOptions(e,t){this.directionalShadowState.enabled=e,this.renderer.setDirectionalShadowsEnabled(e),this.renderer.setDirectionalShadowMapSize(t)}setWorldEnvironment(e){if(null==e)return void this.nodeMaterialResolver.setWorldEnvironment(null);const t=this.getEnvironmentTexture(e.source);this.nodeMaterialResolver.setWorldEnvironment({texture:t,intensity:e.intensity})}getEnvironmentTexture(t){if(t.mapping===e.CubeUVReflectionMapping)return t;let i=this.pmremResults.get(t);return null==i&&(this.pmremGenerator??(this.pmremGenerator=this.renderer.createPMREMGenerator()),i=this.pmremGenerator.fromEquirectangular(t),this.pmremResults.set(t,i),this.ownedPmremResults.add(i)),i.texture}resetViewHistory(){this.renderer.resetViewHistory(),this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.nativeDlss?.reset()}async compile(e,t){if(!this.secondaryMotionPrepared){let t=!1;e.traverse(e=>{const i=e.userData.secondaryMotion?.regions;Array.isArray(i)&&i.some(e=>e.enabled)&&(t=!0)});const i=this.renderer.getDevice();if(t&&i){const{prepareSecondaryMotionRuntime:e}=await import("../secondary-motion/runtime.js");e(i),this.secondaryMotionPrepared=!0}}await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1,n="skip"){this.renderer.setHiZOcclusionCullingEnabled(!0);const r=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:n,allowUnsortedLateDraws:i});return 0===r.drawCount?(r.dispose(),null):r}render(e,t,i){const n="taa"===this.antiAliasingState.mode?this.taa:null;this.volumetricFog?.setScene(e),this.renderer.setMotionVectorProjection(t.projectionMatrix),this.motionBlur?.prepareCamera(t,this.canvas.width,this.canvas.height,i),this.motionBlur?.requiresRendererHistoryReset()&&(this.renderer.resetViewHistory(),this.gtao?.reset(),this.volumetricFog?.reset()),n?.prepareCamera(t,this.canvas.width,this.canvas.height),this.nativeDlss?.prepareFrame(t);const r=!0===this.nativeDlss?.enabled?this.nativeDlss.jitter:null;this.motionBlur?.setJitterUv(n?.currentJitterUv.x??(null==r?0:r.x/Math.max(1,this.canvas.width*this.renderScale)),n?.currentJitterUv.y??(null==r?0:-r.y/Math.max(1,this.canvas.height*this.renderScale))),null!=r&&this.renderer.setProjectionJitter(r.x,r.y);let a=!1;try{this.renderer.render(e,t,i),a=!0}finally{null!=r&&this.renderer.clearProjectionJitter(),n?.finishCamera(t),a&&this.motionBlur?.commitCamera(),a&&this.nativeDlss?.finishFrame(t)}}setMotionBlurOptions(e){null!=this.motionBlur&&Object.assign(this.motionBlur.options,e)}setGTAOOptions(e){this.gtao?.setOptions(e)}setAntiAliasingMode(e){e!==this.antiAliasingState.mode&&("taa"===e&&null==this.taa||"smaa"===e&&null==this.smaa||"fxaa"===e&&null==this.fxaa?console.warn(`[Hology WebGPU experiment] Anti-aliasing mode "${e}" was not initialized. Set webgpuPostProcessing.antiAliasing in the initial rendering configuration to enable runtime switching.`):(this.antiAliasingState.mode=e,this.resetTemporalHistory()))}setGTAOQuality(e){this.gtao?.applyPreset(e)}setVolumetricFogOptions(e){this.volumetricFog?.setOptions(e)}setVolumetricFogQuality(e){this.volumetricFog?.applyPreset(e)}pushMotionBlurOverride(e){return this.motionBlur?.pushOverride(e)??null}invalidateObjectMotion(e){this.renderer.invalidateObjectMotion(e)}getLastFrameProfile(){return this.renderer.getLastFrameProfile()}setPostProcessState(e){null!=this.colorGrading&&(Object.assign(this.colorGrading.options,e??{enabled:!1}),this.colorGrading.options.enabled=!0===e?.enabled),null!=this.depthOfField&&(this.depthOfField.options.enabled=null!=e?.depthFocus||null!=e?.depthAperture||null!=e?.depthMaxBlur,this.depthOfField.options.focus=e?.depthFocus,this.depthOfField.options.aperture=e?.depthAperture,this.depthOfField.options.maxBlur=e?.depthMaxBlur)}setProfilingEnabled(e){this.renderer.setRenderGraphProfilingEnabled(e)}resetTemporalHistory(){this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.renderer.resetViewHistory(),this.nativeDlss?.reset()}inspect(e,t){return inspectWebGpuScene(e,t,this.nodeMaterialResolver)}destroy(){this.nativeDlss?.dispose(),this.nodeMaterialResolver.dispose(),this.gBufferFallbackSource.dispose(),this.gtao?.dispose(),this.smaa?.dispose(),this.motionBlur?.dispose(),this.volumetricFog?.dispose();for(const e of this.ownedPmremResults)e.dispose();this.ownedPmremResults.clear(),this.renderer.destroy(),this.fallbackMaterial.dispose()}}export function inspectWebGpuScene(e,t,i){const n={meshes:0,skinnedMeshes:0,instancedMeshes:0,batchedMeshes:0,sprites:0,points:0,lines:0,missingPositionGeometry:0,transparentMaterials:0,shaderMaterialsReplaced:0,materialsReplaced:0,unsupportedCamera:ExperimentalWebGpuBackend.supportsCamera(t)?0:1};return e.traverse(e=>{if(e.isSprite)return void n.sprites++;if(e.isPoints)return void n.points++;if(e.isLine)return void n.lines++;if(!e.isMesh)return;const t=e;t.isBatchedMesh?n.batchedMeshes++:t.isInstancedMesh?n.instancedMeshes++:t.isSkinnedMesh?n.skinnedMeshes++:n.meshes++,null==t.geometry?.getAttribute("position")&&n.missingPositionGeometry++;const r=Array.isArray(t.material)?t.material:[t.material];for(const e of r){if(null==e)continue;e.transparent&&n.transparentMaterials++;const t=!0===e.isWGSLShaderMaterial||!0===e.isLineMaterial,r=!t&&!0===i?.canResolve(e);t||r||(n.materialsReplaced++,e.isShaderMaterial&&n.shaderMaterialsReplaced++)}}),n}export function formatWebGpuSceneCapabilitySummary(e){return`[Hology WebGPU experiment] ${JSON.stringify(e)}`}const u="\nstruct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) uv: vec2<f32>,\n @location(3) color: vec4<f32>,\n#ifdef USE_SKINNING\n @location(4) skinIndex: vec4<u32>,\n @location(5) skinWeight: vec4<f32>,\n#endif\n @builtin(instance_index) instanceIndex: u32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\n@vertex\nfn vsMain(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n#ifdef USE_SKINNING\n let localPosition = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight);\n let localNormal = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let localPosition = input.position;\n let localNormal = input.normal;\n#endif\n let world = rendererWorldPosition(localPosition, input.instanceIndex);\n output.position = rendererClipPosition(localPosition, input.instanceIndex);\n output.worldPosition = world.xyz;\n output.worldNormal = rendererWorldNormal(localNormal, input.instanceIndex);\n output.color = input.color * rendererObjectColor(input.instanceIndex);\n return output;\n}\n",p="\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\nfn distanceAttenuation(distanceToLight: f32, cutoffDistance: f32, decayExponent: f32) -> f32 {\n var distanceFalloff = 1.0 / max(pow(distanceToLight, decayExponent), 0.01);\n if (cutoffDistance > 0.0) {\n let ratio = distanceToLight / cutoffDistance;\n let cutoff = clamp(1.0 - ratio * ratio * ratio * ratio, 0.0, 1.0);\n distanceFalloff *= cutoff * cutoff;\n }\n return distanceFalloff;\n}\n\n@fragment\nfn fsMain(input: VertexOutput) -> @location(0) vec4<f32> {\n let normal = normalize(input.worldNormal);\n let normalTint = normal * 0.5 + vec3<f32>(0.5);\n let base = mix(vec3<f32>(0.52, 0.58, 0.64), normalTint, 0.22) * input.color.rgb;\n var lighting = rendererIndirectDiffuse(normal) + vec3<f32>(0.08);\n var directionalLighting = vec3<f32>(0.0);\n let directionalCount = rendererDirectionalLightCount();\n\n for (var index: u32 = 0u; index < directionalCount; index = index + 1u) {\n let lightDirection = rendererDirectionalLightDirectionForLight(index);\n let shadow = rendererSampleDirectionalShadowForLightWithNormal(index, input.worldPosition, normal);\n directionalLighting += rendererDirectionalLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * shadow;\n }\n if (directionalCount > 0u) {\n lighting += directionalLighting / f32(directionalCount);\n }\n\n for (var index: u32 = 0u; index < rendererPointLightCount(); index = index + 1u) {\n let lightVector = rendererPointLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let shadow = rendererSamplePointShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererPointLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * distanceAttenuation(distanceToLight, rendererPointLightRangeForLight(index), rendererPointLightDecayForLight(index)) * shadow;\n }\n\n for (var index: u32 = 0u; index < rendererSpotLightCount(); index = index + 1u) {\n let lightVector = rendererSpotLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let angleCos = dot(-lightDirection, rendererSpotLightDirectionForLight(index));\n let cone = smoothstep(rendererSpotLightConeCosForLight(index), rendererSpotLightPenumbraCosForLight(index), angleCos);\n let shadow = rendererSampleSpotShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererSpotLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * cone * distanceAttenuation(distanceToLight, rendererSpotLightRangeForLight(index), rendererSpotLightDecayForLight(index)) * shadow;\n }\n\n return vec4<f32>(base * max(lighting, vec3<f32>(0.08)), input.color.a);\n}\n";/*
|
|
1
|
+
import*as e from"three";import{NodeMaterialWebGpuResolver as t}from"./node-material-webgpu-resolver.js";import{configureWebGpuRuntimeBindings as i}from"./webgpu-runtime-bridge.js";import{float as n,varyingTransformed as r,vec4 as a}from"three-shader-graph";import{NodeShaderMaterial as o}from"../shader-nodes/index.js";import{sceneMapUniformName as s}from"../shader-nodes/scene-sample.js";import{depthUniformName as l}from"../shader-nodes/depth.js";import{MATERIAL_FLAG_ALPHA_TEST as d,MATERIAL_FLAG_RECEIVE_DECALS as c}from"../shader-nodes/material-flags.js";import{createMotionVectorOutput as h}from"./motion-vector-node.js";export class ExperimentalWebGpuBackend{constructor(e,t,i,n,r,a,o,s,l,d,c,h,u,p,m,g,f,v,S,b,P,x){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=r,this.fxaa=a,this.smaa=o,this.gtao=s,this.ssr=l,this.taa=d,this.motionBlur=c,this.volumetricFog=h,this.colorGrading=u,this.depthOfField=p,this.outline=m,this.postProcessEffects=g,this.renderGraphExtensions=f,this.presentationExtensions=v,this.antiAliasingState=S,this.directionalShadowState=b,this.nativeDlss=P,this.kind="webgpu",this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,this.secondaryMotionPrepared=!1,this.canvas=x}static async probeAvailability(){if("undefined"==typeof navigator||!("gpu"in navigator))return{available:!1,reason:"The runtime does not expose navigator.gpu."};try{const e=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});return null==e?{available:!1,reason:"No WebGPU adapter is available."}:{available:!0,adapter:e}}catch(e){return{available:!1,reason:`Requesting a WebGPU adapter failed: ${e instanceof Error?e.message:String(e)}`}}}static async create(m={},g){const f=await import("@hology/webgpu-renderer");i({registerPipelineDiagnosticOrigin:f.registerPipelineDiagnosticOrigin,createComputeKernel:(e,t)=>new f.ComputeKernel(e,t),buildParticleLightingShaderHeader:f.buildParticleLightingShaderHeader});const v=document.createElement("canvas");v.dataset.hologyRenderer="webgpu-experimental";const S=new f.WGSLShaderMaterial({vertexShader:u,fragmentShader:p}),b=!1!==m.nativeUpscaling&&"dlss"===m.nativeUpscaling?.method,P=b?(await import("./native-dlss-upscaler.js")).createNativeDlssUpscaler(m.nativeUpscaling?.mode??"quality"):null,x=null!=P;S.side=f.DoubleSide;const w=f,y=null!=m.motionBlur&&!1!==m.motionBlur,D=!1!==m.gtao&&(null==m.gtao||!1!==m.gtao.temporal),M=!1!==m.volumetricFog&&(null==m.volumetricFog||!1!==m.volumetricFog.temporal),O=x?"off":b?"taa":null!=(E=m).antiAliasing?E.antiAliasing:null!=E.taa&&!1!==E.taa?"taa":null!=E.smaa&&!1!==E.smaa?"smaa":null!=E.fxaa&&!1!==E.fxaa?"fxaa":!1===E.taa?"off":"taa";var E;const F=null!=m.antiAliasing,C=y||D||M||(F||"taa"===O)||x;let L=null;const G=new t(w,(e,t)=>"opaque"===t?[e.outputColor.xyz.rgba(n(e.alphaTest>0?d:0).add(!1===e.userData.receiveDecals?0:c)),a((e.outputNormal??r.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??n(1)),...C?[h(e)]:[]]:void 0,e=>L?.getEnvironmentTexture(e)??e),R=new e.MeshStandardMaterial({color:8688803,roughness:1});if(null==G.resolve(R,"opaque"))throw S.dispose(),R.dispose(),new Error("Failed to compile the WebGPU G-buffer fallback material.");const T=!1===m.gtao?null:new f.GTAOEffect({normalSpace:"view",...f.GTAO_PRESETS.high,...m.gtao??{}}),A=!1===m.ssr||null==m.ssr?null:new f.SSREffect({normalSpace:"view",resolutionScale:.5,...m.ssr??{}}),B=!1===m.bloom?null:new f.BloomEffect({threshold:1,strength:.9,radius:.2,...m.bloom??{}}),U=F||!1!==m.fxaa&&"fxaa"===O?new f.FXAAEffect(!1===m.fxaa?{}:m.fxaa):null,W=F||!1!==m.smaa&&"smaa"===O?new f.SMAAEffect(!1===m.smaa?{}:m.smaa):null,k=x||F||!1!==m.taa&&"taa"===O?new f.TemporalAAEffect({renderScale:1,...!1===m.taa?{}:m.taa}):null,V={mode:O},I=!1===m.motionBlur||null==m.motionBlur?null:new f.MotionBlurEffect(m.motionBlur),j=m.volumetricFog||void 0,N=!1===m.volumetricFog?null:new f.VolumetricFogEffect(void 0,{...f.VOLUMETRIC_FOG_PRESETS.high,maxDistance:64,spatialJitter:!0,scatteringIntensity:Math.PI,...j,temporal:!1!==j?.temporal&&{...f.VOLUMETRIC_FOG_PRESETS.high.temporal,...j?.temporal},blur:!1!==j?.blur&&{...!1===f.VOLUMETRIC_FOG_PRESETS.high.blur?{}:f.VOLUMETRIC_FOG_PRESETS.high.blur,depthAwareUpsample:!0,...j?.blur}}),H=!1===m.colorGrading?null:new f.ColorGradingEffect({enabled:!1,...m.colorGrading??{}}),$=!1===m.depthOfField?null:new f.DepthOfFieldEffect({enabled:!1,...m.depthOfField??{}}),_=!1===m.outline?null:new f.OutlineEffect({enabled:!1,...m.outline??{}}),q=[],z=new WeakMap,J=new Set,K=[],Z=[],Q=(e,t,i)=>{let n=i;const r=q.filter(e=>e.enabled&&e.stage===t).sort((e,t)=>e.priority-t.priority||e.id-t.id);for(const t of r){if(!(t.material instanceof o)){const e=`${t.id}:material`;J.has(e)||(J.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: only NodeShaderMaterial effects are supported.`));continue}try{let i=z.get(t.material);null!=i&&i.version===t.material.version||(i={version:t.material.version,shader:G.compileFullscreen(t.material),diagnosticOrigin:{key:"post-process:"+String(t.material.userData.assetId??(t.material.name||t.material.uuid)),material:{name:t.material.name,uuid:t.material.uuid,version:t.material.version,assetId:t.material.userData.assetId,assetName:t.material.userData.assetName}}},z.set(t.material,i));const r=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,diagnosticOrigin:i.diagnosticOrigin,shader:i.shader,inputOverrides:{[s]:n},outputs:r}),n=r}catch(e){const i=`${t.id}:compile:${t.material.version}`;J.has(i)||(J.add(i),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: ${e instanceof Error?e.message:String(e)}`,e))}}return n},X={enabled:!0},Y=new f.WebGpuRenderer({canvas:v,fallbackMaterial:S,materialResolver:(e,t)=>G.resolve(e,t),invokeObjectRenderCallbacks:!1,hiZOcclusionCulling:!0,renderGraphProfiling:!1,sampleCount:1,multiDrawIndirect:!1,nativePostSubmit:P?.postSubmit,presentationOverlay:e=>{for(const t of Z)t(e)}});Y.setRenderScale("taa"===O?k?.renderScale??1:1),Y.setRenderGraphBuilder((e,t)=>{const i=new f.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba8unorm"}),r=C?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of K)"beforeScene"===e.stage&&e(i,i.sceneColor);X.enabled&&i.addDirectionalShadowPass(),i.addPointShadowPass(),i.addSpotShadowPass(),i.addDepthPrepass(),i.addHiZPasses(),i.addVisibilityPass(),i.addMaterialPass({name:"OpaqueGBufferPass",outputs:null==r?[i.sceneColor,n]:[i.sceneColor,n,r],drawStage:"opaque",loadDepth:!0}),i.addHiZHistoryPass("OpaqueGBufferPass");let a=i.sceneColor;if(T?.enabled){const e=T.addPasses(i,{depth:i.mainDepth,normal:n,velocity:r??void 0});a=T.addCompositePass(i,a,e)}null!=A&&(a=A.addPasses(i,{sceneColor:a,depth:i.mainDepth,normalRoughness:n}));const o=new Set(K.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(a,{sceneColor:o.has("sceneColorSnapshot"),sceneDepth:o.has("sceneDepthSnapshot")||q.some(e=>e.enabled&&null!=e.material.uniforms[l])}),i.addLatePass(a);for(const e of K)null!=e.stage&&"afterScene"!==e.stage||e(i,a);a=Q(i,"beforeFog",a),null!=N&&(a=N.addPasses(i,{sceneColor:a,depth:i.mainDepth,velocity:r??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=I&&null!=r&&(a=I.addPass(i,a,r,i.mainDepth)),null!=B&&(a=B.addPass(i,a)),a=Q(i,"beforeOutline",a),null!=_&&(a=_.addPass(i,a)),a=Q(i,"beforeDepthOfField",a),null!=$&&(a=$.addPass(i,a,i.mainDepth)),a=Q(i,"beforeColorAdjustment",a),null!=H&&(a=H.addPass(i,a)),a=Q(i,"beforeAntiAliasing",a);let s="taa"===V.mode&&null!=k?k.addPass(i,a,i.mainDepth,r??void 0):a;"smaa"===V.mode&&null!=W?s=W.addPass(i,s):"fxaa"===V.mode&&null!=U&&(s=U.addPass(i,s)),s=Q(i,"beforeOutput",s);for(const e of K)"beforePresent"===e.stage&&e(i,s);!0===P?.enabled&&null!=r?P.addInputPass(i,s,r):i.present(s)});try{return await Y.initialize(g),L=new ExperimentalWebGpuBackend(Y,S,G,R,B,U,W,T,A,k,I,N,H,$,_,q,K,Z,V,X,P,v),L}catch(e){throw Y.destroy(),S.dispose(),G.dispose(),R.dispose(),T?.dispose(),W?.dispose(),I?.dispose(),N?.dispose(),_?.dispose(),e}}static supportsCamera(t){return t instanceof e.PerspectiveCamera||t instanceof e.OrthographicCamera}setSize(e,t,i,n=1){const r=this.canvas.width,a=this.canvas.height;let o=Math.min(1,Math.max(.25,n));if(!0===this.nativeDlss?.enabled){const n=Math.max(1,Math.floor(e*i)),r=Math.max(1,Math.floor(t*i));o=this.nativeDlss.getRenderScale(n,r)}const s=o!==this.renderScale;this.renderScale=o,this.renderer.setRenderScale(o),this.taa?.setRenderScale(o),this.renderer.setSize(e,t,i),(s||this.canvas.width!==r||this.canvas.height!==a)&&this.resetViewHistory()}initTexture(e){this.renderer.initTexture(e)}setPostProcessEffects(e){this.postProcessEffects.splice(0,this.postProcessEffects.length,...e);for(const t of e){if("beforeLut"!==t.stage)continue;const e=`${t.id}:${t.stage}`;this.warnedUnsupportedPostProcessStages.has(e)||(this.warnedUnsupportedPostProcessStages.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: stage "${t.stage}" has no native WebGPU anchor.`))}}getDevice(){return this.renderer.getDevice()}createSceneCapture(e,t,i){return this.renderer.createSceneCapture(e,t,i)}setRenderGraphExtensions(e){this.renderGraphExtensions.length=0;for(const t of e)this.renderGraphExtensions.push(t)}setPresentationExtensions(e){this.presentationExtensions.length=0;for(const t of e)this.presentationExtensions.push(t)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=e)}setTiledLightingEnabled(e){this.renderer.setTiledLightingEnabled(e)}setDynamicBatchingEnabled(e){this.renderer.setDynamicBatchingEnabled(e)}setSelectedObjects(e){this.outline?.setSelectedObjects(e)}setSelectedObjectInstances(e){this.outline?.setSelectedInstances(e)}setCascadedShadowRanges(e,t=[]){this.renderer.setCascadedShadowRanges(e,t),this.volumetricFog?.setCascadedDirectionalLights(t)}setDirectionalShadowUpdateOptions(e){this.renderer.setDirectionalShadowUpdateOptions(e)}invalidateDirectionalShadows(){this.renderer.invalidateDirectionalShadows()}setDirectionalShadowOptions(e,t){this.directionalShadowState.enabled=e,this.renderer.setDirectionalShadowsEnabled(e),this.renderer.setDirectionalShadowMapSize(t)}setWorldEnvironment(e){if(null==e)return void this.nodeMaterialResolver.setWorldEnvironment(null);const t=this.getEnvironmentTexture(e.source);this.nodeMaterialResolver.setWorldEnvironment({texture:t,intensity:e.intensity})}getEnvironmentTexture(t){if(t.mapping===e.CubeUVReflectionMapping)return t;let i=this.pmremResults.get(t);return null==i&&(this.pmremGenerator??(this.pmremGenerator=this.renderer.createPMREMGenerator()),i=this.pmremGenerator.fromEquirectangular(t),this.pmremResults.set(t,i),this.ownedPmremResults.add(i)),i.texture}resetViewHistory(){this.renderer.resetViewHistory(),this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.nativeDlss?.reset()}async compile(e,t){if(!this.secondaryMotionPrepared){let t=!1;e.traverse(e=>{const i=e.userData.secondaryMotion?.regions;Array.isArray(i)&&i.some(e=>e.enabled)&&(t=!0)});const i=this.renderer.getDevice();if(t&&i){const{prepareSecondaryMotionRuntime:e}=await import("../secondary-motion/runtime.js");e(i),this.secondaryMotionPrepared=!0}}await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1,n="skip"){this.renderer.setHiZOcclusionCullingEnabled(!0);const r=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:n,allowUnsortedLateDraws:i});return 0===r.drawCount?(r.dispose(),null):r}registerStaticSpatialObject(e){return this.renderer.registerStaticSpatialObject(e)}render(e,t,i){const n="taa"===this.antiAliasingState.mode?this.taa:null;this.volumetricFog?.setScene(e),this.renderer.setMotionVectorProjection(t.projectionMatrix),this.motionBlur?.prepareCamera(t,this.canvas.width,this.canvas.height,i),this.motionBlur?.requiresRendererHistoryReset()&&(this.renderer.resetViewHistory(),this.gtao?.reset(),this.volumetricFog?.reset()),n?.prepareCamera(t,this.canvas.width,this.canvas.height),this.nativeDlss?.prepareFrame(t);const r=!0===this.nativeDlss?.enabled?this.nativeDlss.jitter:null;this.motionBlur?.setJitterUv(n?.currentJitterUv.x??(null==r?0:r.x/Math.max(1,this.canvas.width*this.renderScale)),n?.currentJitterUv.y??(null==r?0:-r.y/Math.max(1,this.canvas.height*this.renderScale))),null!=r&&this.renderer.setProjectionJitter(r.x,r.y);let a=!1;try{this.renderer.render(e,t,i),a=!0}finally{null!=r&&this.renderer.clearProjectionJitter(),n?.finishCamera(t),a&&this.motionBlur?.commitCamera(),a&&this.nativeDlss?.finishFrame(t)}}setMotionBlurOptions(e){null!=this.motionBlur&&Object.assign(this.motionBlur.options,e)}setGTAOOptions(e){this.gtao?.setOptions(e)}setAntiAliasingMode(e){e!==this.antiAliasingState.mode&&("taa"===e&&null==this.taa||"smaa"===e&&null==this.smaa||"fxaa"===e&&null==this.fxaa?console.warn(`[Hology WebGPU experiment] Anti-aliasing mode "${e}" was not initialized. Set webgpuPostProcessing.antiAliasing in the initial rendering configuration to enable runtime switching.`):(this.antiAliasingState.mode=e,this.resetTemporalHistory()))}setGTAOQuality(e){this.gtao?.applyPreset(e)}setVolumetricFogOptions(e){this.volumetricFog?.setOptions(e)}setVolumetricFogQuality(e){this.volumetricFog?.applyPreset(e)}pushMotionBlurOverride(e){return this.motionBlur?.pushOverride(e)??null}invalidateObjectMotion(e){this.renderer.invalidateObjectMotion(e)}getLastFrameProfile(){return this.renderer.getLastFrameProfile()}setPostProcessState(e){null!=this.colorGrading&&(Object.assign(this.colorGrading.options,e??{enabled:!1}),this.colorGrading.options.enabled=!0===e?.enabled),null!=this.depthOfField&&(this.depthOfField.options.enabled=null!=e?.depthFocus||null!=e?.depthAperture||null!=e?.depthMaxBlur,this.depthOfField.options.focus=e?.depthFocus,this.depthOfField.options.aperture=e?.depthAperture,this.depthOfField.options.maxBlur=e?.depthMaxBlur)}setProfilingEnabled(e){this.renderer.setRenderGraphProfilingEnabled(e)}resetTemporalHistory(){this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.renderer.resetViewHistory(),this.nativeDlss?.reset()}inspect(e,t){return inspectWebGpuScene(e,t,this.nodeMaterialResolver)}destroy(){this.nativeDlss?.dispose(),this.nodeMaterialResolver.dispose(),this.gBufferFallbackSource.dispose(),this.gtao?.dispose(),this.smaa?.dispose(),this.motionBlur?.dispose(),this.volumetricFog?.dispose();for(const e of this.ownedPmremResults)e.dispose();this.ownedPmremResults.clear(),this.renderer.destroy(),this.fallbackMaterial.dispose()}}export function inspectWebGpuScene(e,t,i){const n={meshes:0,skinnedMeshes:0,instancedMeshes:0,batchedMeshes:0,sprites:0,points:0,lines:0,missingPositionGeometry:0,transparentMaterials:0,shaderMaterialsReplaced:0,materialsReplaced:0,unsupportedCamera:ExperimentalWebGpuBackend.supportsCamera(t)?0:1};return e.traverse(e=>{if(e.isSprite)return void n.sprites++;if(e.isPoints)return void n.points++;if(e.isLine)return void n.lines++;if(!e.isMesh)return;const t=e;t.isBatchedMesh?n.batchedMeshes++:t.isInstancedMesh?n.instancedMeshes++:t.isSkinnedMesh?n.skinnedMeshes++:n.meshes++,null==t.geometry?.getAttribute("position")&&n.missingPositionGeometry++;const r=Array.isArray(t.material)?t.material:[t.material];for(const e of r){if(null==e)continue;e.transparent&&n.transparentMaterials++;const t=!0===e.isWGSLShaderMaterial||!0===e.isLineMaterial,r=!t&&!0===i?.canResolve(e);t||r||(n.materialsReplaced++,e.isShaderMaterial&&n.shaderMaterialsReplaced++)}}),n}export function formatWebGpuSceneCapabilitySummary(e){return`[Hology WebGPU experiment] ${JSON.stringify(e)}`}const u="\nstruct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) uv: vec2<f32>,\n @location(3) color: vec4<f32>,\n#ifdef USE_SKINNING\n @location(4) skinIndex: vec4<u32>,\n @location(5) skinWeight: vec4<f32>,\n#endif\n @builtin(instance_index) instanceIndex: u32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\n@vertex\nfn vsMain(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n#ifdef USE_SKINNING\n let localPosition = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight);\n let localNormal = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let localPosition = input.position;\n let localNormal = input.normal;\n#endif\n let world = rendererWorldPosition(localPosition, input.instanceIndex);\n output.position = rendererClipPosition(localPosition, input.instanceIndex);\n output.worldPosition = world.xyz;\n output.worldNormal = rendererWorldNormal(localNormal, input.instanceIndex);\n output.color = input.color * rendererObjectColor(input.instanceIndex);\n return output;\n}\n",p="\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\nfn distanceAttenuation(distanceToLight: f32, cutoffDistance: f32, decayExponent: f32) -> f32 {\n var distanceFalloff = 1.0 / max(pow(distanceToLight, decayExponent), 0.01);\n if (cutoffDistance > 0.0) {\n let ratio = distanceToLight / cutoffDistance;\n let cutoff = clamp(1.0 - ratio * ratio * ratio * ratio, 0.0, 1.0);\n distanceFalloff *= cutoff * cutoff;\n }\n return distanceFalloff;\n}\n\n@fragment\nfn fsMain(input: VertexOutput) -> @location(0) vec4<f32> {\n let normal = normalize(input.worldNormal);\n let normalTint = normal * 0.5 + vec3<f32>(0.5);\n let base = mix(vec3<f32>(0.52, 0.58, 0.64), normalTint, 0.22) * input.color.rgb;\n var lighting = rendererIndirectDiffuse(normal) + vec3<f32>(0.08);\n var directionalLighting = vec3<f32>(0.0);\n let directionalCount = rendererDirectionalLightCount();\n\n for (var index: u32 = 0u; index < directionalCount; index = index + 1u) {\n let lightDirection = rendererDirectionalLightDirectionForLight(index);\n let shadow = rendererSampleDirectionalShadowForLightWithNormal(index, input.worldPosition, normal);\n directionalLighting += rendererDirectionalLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * shadow;\n }\n if (directionalCount > 0u) {\n lighting += directionalLighting / f32(directionalCount);\n }\n\n for (var index: u32 = 0u; index < rendererPointLightCount(); index = index + 1u) {\n let lightVector = rendererPointLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let shadow = rendererSamplePointShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererPointLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * distanceAttenuation(distanceToLight, rendererPointLightRangeForLight(index), rendererPointLightDecayForLight(index)) * shadow;\n }\n\n for (var index: u32 = 0u; index < rendererSpotLightCount(); index = index + 1u) {\n let lightVector = rendererSpotLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let angleCos = dot(-lightDirection, rendererSpotLightDirectionForLight(index));\n let cone = smoothstep(rendererSpotLightConeCosForLight(index), rendererSpotLightPenumbraCosForLight(index), angleCos);\n let shadow = rendererSampleSpotShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererSpotLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * cone * distanceAttenuation(distanceToLight, rendererSpotLightRangeForLight(index), rendererSpotLightDecayForLight(index)) * shadow;\n }\n\n return vec4<f32>(base * max(lighting, vec3<f32>(0.08)), input.color.a);\n}\n";/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|