@hology/core 0.0.250 → 0.0.252

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/effects/sequence/sequence-data.d.ts +2 -0
  2. package/dist/effects/sequence/sequence-data.js +1 -1
  3. package/dist/effects/sequence/sequence-definitions.js +1 -1
  4. package/dist/effects/sequence/sequence-player.d.ts +4 -0
  5. package/dist/effects/sequence/sequence-player.js +1 -1
  6. package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
  7. package/dist/effects/vfx/gpu-vfx-world-service.js +1 -1
  8. package/dist/gameplay/actors/actor.js +1 -1
  9. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  10. package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
  11. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +1 -1
  12. package/dist/gameplay/initiate.d.ts +4 -0
  13. package/dist/gameplay/initiate.js +1 -1
  14. package/dist/gameplay/services/render.d.ts +11 -3
  15. package/dist/gameplay/services/render.js +1 -1
  16. package/dist/rendering/native-dlss-upscaler.d.ts +104 -0
  17. package/dist/rendering/native-dlss-upscaler.js +4 -0
  18. package/dist/rendering/node-material-webgpu-resolver.d.ts +2 -1
  19. package/dist/rendering/node-material-webgpu-resolver.js +1 -1
  20. package/dist/rendering/post-process-effect.d.ts +1 -1
  21. package/dist/rendering/post-process-effect.js +1 -1
  22. package/dist/rendering/rendering-backend.d.ts +9 -0
  23. package/dist/rendering/rendering-backend.js +4 -0
  24. package/dist/rendering/upscaling-pass.d.ts +9 -1
  25. package/dist/rendering/upscaling-pass.js +1 -1
  26. package/dist/rendering/webgl-backend.d.ts +32 -0
  27. package/dist/rendering/webgl-backend.js +4 -0
  28. package/dist/rendering/webgpu-experimental-backend.d.ts +19 -2
  29. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  30. package/dist/rendering/webgpu-runtime-bridge.d.ts +22 -0
  31. package/dist/rendering/webgpu-runtime-bridge.js +4 -0
  32. package/dist/rendering.d.ts +45 -16
  33. package/dist/rendering.js +1 -1
  34. package/dist/scene/asset-resource-loader.d.ts +5 -0
  35. package/dist/scene/asset-resource-loader.js +1 -1
  36. package/dist/scene/materializer.js +1 -1
  37. package/dist/scene/materials/water.js +1 -1
  38. package/dist/scene/runtime-bundled-backend-service.d.ts +7 -0
  39. package/dist/scene/runtime-bundled-backend-service.js +1 -1
  40. package/dist/scene/storage/packed-json.js +1 -1
  41. package/dist/secondary-motion/runtime.d.ts +1 -1
  42. package/dist/secondary-motion/runtime.js +1 -1
  43. package/dist/test/actor-attachment.test.d.ts +2 -0
  44. package/dist/test/actor-attachment.test.js +4 -0
  45. package/dist/test/gpu-sprite-compiler.test.js +1 -1
  46. package/dist/test/native-dlss-upscaler.test.d.ts +2 -0
  47. package/dist/test/native-dlss-upscaler.test.js +4 -0
  48. package/dist/test/node-material-webgpu-resolver.test.js +1 -1
  49. package/dist/test/webgpu-experimental-backend.test.js +1 -1
  50. package/dist/utils/uuid.js +1 -1
  51. package/package.json +1 -1
  52. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,104 @@
1
+ import * as THREE from 'three';
2
+ import type { FrameGraphBuilder } from '@hology/webgpu-renderer';
3
+ import type { DlssQualityMode } from './upscaling-pass.js';
4
+ export interface NativeUpscalingCapability {
5
+ readonly apiVersion: number;
6
+ readonly backend: string;
7
+ readonly compiled: boolean;
8
+ readonly available: boolean;
9
+ readonly reason: string;
10
+ }
11
+ interface NativeUpscalingHost {
12
+ getCapabilities(): NativeUpscalingCapability;
13
+ getOptimalSettings(options: {
14
+ outputWidth: number;
15
+ outputHeight: number;
16
+ mode: DlssQualityMode;
17
+ }): {
18
+ renderWidth: number;
19
+ renderHeight: number;
20
+ };
21
+ createSession(options: {
22
+ renderWidth: number;
23
+ renderHeight: number;
24
+ outputWidth: number;
25
+ outputHeight: number;
26
+ mode: DlssQualityMode;
27
+ }): NativeUpscalingSession;
28
+ }
29
+ interface NativeUpscalingSession {
30
+ readonly color: GPUTexture;
31
+ readonly depth: GPUTexture;
32
+ readonly motionVectors: GPUTexture;
33
+ readonly output: GPUTexture;
34
+ evaluate(options: NativeDlssFrame): void;
35
+ }
36
+ interface NativeDlssFrame {
37
+ cameraViewToClip: Float32Array;
38
+ clipToCameraView: Float32Array;
39
+ clipToPreviousClip: Float32Array;
40
+ previousClipToClip: Float32Array;
41
+ cameraPosition: Float32Array;
42
+ cameraUp: Float32Array;
43
+ cameraRight: Float32Array;
44
+ cameraForward: Float32Array;
45
+ jitterX: number;
46
+ jitterY: number;
47
+ nearPlane: number;
48
+ farPlane: number;
49
+ verticalFov: number;
50
+ aspectRatio: number;
51
+ reset: boolean;
52
+ orthographic: boolean;
53
+ }
54
+ export interface NativePostSubmitContext {
55
+ readonly device: GPUDevice;
56
+ present(sourceView: GPUTextureView): void;
57
+ }
58
+ export declare class NativeDlssUpscaler {
59
+ private readonly host;
60
+ private readonly mode;
61
+ private session;
62
+ private sessionSize;
63
+ private pipeline;
64
+ private bindGroup;
65
+ private colorView;
66
+ private depthView;
67
+ private motionView;
68
+ private outputView;
69
+ private inputColorView;
70
+ private inputDepthView;
71
+ private inputMotionView;
72
+ private fallbackView;
73
+ private presentFallbackOnce;
74
+ private failed;
75
+ private resetPending;
76
+ private historyValid;
77
+ private frameIndex;
78
+ private readonly previousViewProjection;
79
+ private readonly currentViewProjection;
80
+ private readonly currentViewProjectionInverse;
81
+ private readonly projection;
82
+ private readonly projectionInverse;
83
+ private readonly clipToPreviousClip;
84
+ private readonly previousClipToClip;
85
+ readonly jitter: THREE.Vector2;
86
+ private readonly cameraPosition;
87
+ private readonly cameraUp;
88
+ private readonly cameraRight;
89
+ private readonly cameraForward;
90
+ private readonly frame;
91
+ constructor(host: NativeUpscalingHost, mode: DlssQualityMode);
92
+ get enabled(): boolean;
93
+ getRenderScale(outputWidth: number, outputHeight: number): number;
94
+ addInputPass(graph: FrameGraphBuilder, color: string, motionVectors: string): void;
95
+ postSubmit: ({ present }: NativePostSubmitContext) => void;
96
+ prepareFrame(camera: THREE.PerspectiveCamera | THREE.OrthographicCamera): void;
97
+ finishFrame(camera: THREE.PerspectiveCamera | THREE.OrthographicCamera): void;
98
+ reset(): void;
99
+ dispose(): void;
100
+ private disable;
101
+ }
102
+ export declare function createNativeDlssUpscaler(mode: DlssQualityMode): NativeDlssUpscaler | null;
103
+ export {};
104
+ //# sourceMappingURL=native-dlss-upscaler.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as i from"three";const t=(new i.Matrix4).set(1,0,0,0,0,1,0,0,0,0,.5,.5,0,0,0,1);function e(i,t){const e=i.elements;t[0]=e[0],t[1]=e[4],t[2]=e[8],t[3]=e[12],t[4]=e[1],t[5]=e[5],t[6]=e[9],t[7]=e[13],t[8]=e[2],t[9]=e[6],t[10]=e[10],t[11]=e[14],t[12]=e[3],t[13]=e[7],t[14]=e[11],t[15]=e[15]}function r(i,t){t[0]=i.x,t[1]=i.y,t[2]=i.z}function s(i,t){let e=0,r=1/t;for(;i>0;)e+=r*(i%t),i=Math.floor(i/t),r/=t;return e}export class NativeDlssUpscaler{constructor(t,e){this.host=t,this.mode=e,this.session=null,this.sessionSize="",this.pipeline=null,this.bindGroup=null,this.colorView=null,this.depthView=null,this.motionView=null,this.outputView=null,this.inputColorView=null,this.inputDepthView=null,this.inputMotionView=null,this.fallbackView=null,this.presentFallbackOnce=!1,this.failed=!1,this.resetPending=!0,this.historyValid=!1,this.frameIndex=0,this.previousViewProjection=new i.Matrix4,this.currentViewProjection=new i.Matrix4,this.currentViewProjectionInverse=new i.Matrix4,this.projection=new i.Matrix4,this.projectionInverse=new i.Matrix4,this.clipToPreviousClip=new i.Matrix4,this.previousClipToClip=new i.Matrix4,this.jitter=new i.Vector2,this.cameraPosition=new i.Vector3,this.cameraUp=new i.Vector3,this.cameraRight=new i.Vector3,this.cameraForward=new i.Vector3,this.frame={cameraViewToClip:new Float32Array(16),clipToCameraView:new Float32Array(16),clipToPreviousClip:new Float32Array(16),previousClipToClip:new Float32Array(16),cameraPosition:new Float32Array(3),cameraUp:new Float32Array([0,1,0]),cameraRight:new Float32Array([1,0,0]),cameraForward:new Float32Array([0,0,-1]),jitterX:0,jitterY:0,nearPlane:.1,farPlane:1e3,verticalFov:1,aspectRatio:1,reset:!0,orthographic:!1},this.postSubmit=({present:i})=>{if(this.presentFallbackOnce)return this.presentFallbackOnce=!1,void(null!=this.fallbackView&&i(this.fallbackView));if(!this.failed&&null!=this.session&&null!=this.outputView)try{this.frame.reset=this.resetPending,this.session.evaluate(this.frame),this.resetPending=!1,i(this.outputView)}catch(t){this.disable(t),null!=this.fallbackView&&(this.presentFallbackOnce=!1,i(this.fallbackView))}}}get enabled(){return!this.failed}getRenderScale(i,t){if(this.failed)return 1;try{const e=this.host.getOptimalSettings({outputWidth:i,outputHeight:t,mode:this.mode});return Math.min(e.renderWidth/i,e.renderHeight/t)}catch(i){return this.disable(i),1}}addInputPass(i,t,e){i.addPass({name:"NativeDlssInputs",inputs:{color:t,depth:i.mainDepth,motion:e},execute:i=>{const r=i.getColorView(t),s=i.depthView,n=i.getColorView(e);if(this.fallbackView=r,!this.failed)try{const t=`${i.width}x${i.height}:${i.presentationWidth}x${i.presentationHeight}`;null!=this.session&&this.sessionSize===t||(this.session=this.host.createSession({renderWidth:i.width,renderHeight:i.height,outputWidth:i.presentationWidth,outputHeight:i.presentationHeight,mode:this.mode}),this.sessionSize=t,this.colorView=this.session.color.createView(),this.depthView=this.session.depth.createView(),this.motionView=this.session.motionVectors.createView(),this.outputView=this.session.output.createView(),this.pipeline??(this.pipeline=function(i){const t=i.createShaderModule({label:"native-dlss-inputs-shader",code:"\n struct VertexOutput { @builtin(position) position: vec4<f32> };\n @vertex fn vertexMain(@builtin(vertex_index) index: u32) -> VertexOutput {\n var positions = array<vec2<f32>, 3>(vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));\n var output: VertexOutput;\n output.position = vec4(positions[index], 0.0, 1.0);\n return output;\n }\n @group(0) @binding(0) var inputColor: texture_2d<f32>;\n @group(0) @binding(1) var inputDepth: texture_depth_2d;\n @group(0) @binding(2) var inputMotion: texture_2d<f32>;\n struct FragmentOutput {\n @location(0) color: vec4<f32>,\n @location(1) depth: f32,\n @location(2) motion: vec2<f32>,\n };\n @fragment fn fragmentMain(@builtin(position) position: vec4<f32>) -> FragmentOutput {\n let pixel = vec2<i32>(position.xy);\n var output: FragmentOutput;\n output.color = textureLoad(inputColor, pixel, 0);\n output.depth = textureLoad(inputDepth, pixel, 0);\n output.motion = textureLoad(inputMotion, pixel, 0).xy;\n return output;\n }\n "});return i.createRenderPipeline({label:"native-dlss-inputs-pipeline",layout:"auto",vertex:{module:t,entryPoint:"vertexMain"},fragment:{module:t,entryPoint:"fragmentMain",targets:[{format:"rgba16float"},{format:"r32float"},{format:"rg16float"}]},primitive:{topology:"triangle-list"}})}(i.device)),this.bindGroup=null,this.reset()),null!=this.bindGroup&&this.inputColorView===r&&this.inputDepthView===s&&this.inputMotionView===n||(this.bindGroup=i.device.createBindGroup({label:"native-dlss-inputs-bind-group",layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:r},{binding:1,resource:s},{binding:2,resource:n}]}),this.inputColorView=r,this.inputDepthView=s,this.inputMotionView=n);const e=i.encoder.beginRenderPass({colorAttachments:[{view:this.colorView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"},{view:this.depthView,clearValue:{r:1,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"},{view:this.motionView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(3),e.end()}catch(i){this.disable(i)}}})}prepareFrame(n){if(this.failed)return;this.projection.multiplyMatrices(t,n.projectionMatrix),this.projectionInverse.copy(this.projection).invert();const o=this.currentViewProjection.multiplyMatrices(this.projection,n.matrixWorldInverse);this.currentViewProjectionInverse.copy(o).invert(),this.historyValid?(this.clipToPreviousClip.multiplyMatrices(this.previousViewProjection,this.currentViewProjectionInverse),this.previousClipToClip.copy(this.previousViewProjection).invert().premultiply(o)):(this.clipToPreviousClip.identity(),this.previousClipToClip.identity());const a=this.frameIndex%32+1;this.jitter.set(s(a,2)-.5,s(a,3)-.5),this.frameIndex++,e(this.projection,this.frame.cameraViewToClip),e(this.projectionInverse,this.frame.clipToCameraView),e(this.clipToPreviousClip,this.frame.clipToPreviousClip),e(this.previousClipToClip,this.frame.previousClipToClip),this.frame.jitterX=this.jitter.x,this.frame.jitterY=-this.jitter.y,this.cameraPosition.setFromMatrixPosition(n.matrixWorld),this.cameraRight.setFromMatrixColumn(n.matrixWorld,0).normalize(),this.cameraUp.setFromMatrixColumn(n.matrixWorld,1).normalize(),n.getWorldDirection(this.cameraForward),r(this.cameraPosition,this.frame.cameraPosition),r(this.cameraRight,this.frame.cameraRight),r(this.cameraUp,this.frame.cameraUp),r(this.cameraForward,this.frame.cameraForward);const l=n instanceof i.PerspectiveCamera?n:null;this.frame.nearPlane=n.near,this.frame.farPlane=n.far,this.frame.verticalFov=null==l?0:i.MathUtils.degToRad(l.fov),this.frame.aspectRatio=l?.aspect??1,this.frame.reset=this.resetPending||!this.historyValid,this.frame.orthographic=null==l}finishFrame(i){this.failed||(this.previousViewProjection.multiplyMatrices(this.projection,i.matrixWorldInverse),this.historyValid=!0)}reset(){this.resetPending=!0,this.historyValid=!1,this.frameIndex=0}dispose(){this.session=null,this.bindGroup=null,this.inputColorView=this.inputDepthView=this.inputMotionView=null,this.colorView=this.depthView=this.motionView=this.outputView=this.fallbackView=null}disable(i){this.failed||(this.failed=!0,this.presentFallbackOnce=!0,this.jitter.set(0,0),console.warn("[Hology WebGPU] Native DLSS failed; continuing with normal WebGPU presentation.",i))}}export function createNativeDlssUpscaler(i){const t=navigator.gpu.nativeUpscaling,e=t?.getCapabilities();return null==t||1!==e?.apiVersion||!0!==e.available?(console.warn("[Hology WebGPU] Native DLSS-SR is unavailable; using TAA fallback."+(null!=e&&1!==e.apiVersion?` Unsupported native upscaling API version ${e.apiVersion}.`:e?.reason?` ${e.reason}`:"")),null):(console.info("[Hology WebGPU] Native DLSS-SR is active."),new NativeDlssUpscaler(t,i))}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -56,6 +56,7 @@ type MRTOutputsResolverFn = (mat: NodeShaderMaterial, drawStage?: NodeMaterialWe
56
56
  export declare class NodeMaterialWebGpuResolver {
57
57
  private readonly webGpu;
58
58
  private readonly mrtResolver?;
59
+ private readonly environmentTextureResolver?;
59
60
  private readonly cache;
60
61
  private readonly failedSignatures;
61
62
  private readonly mappedMaterialsCache;
@@ -67,7 +68,7 @@ export declare class NodeMaterialWebGpuResolver {
67
68
  private worldEnvironmentTexture;
68
69
  private worldEnvironmentIntensity;
69
70
  private worldEnvironmentRevision;
70
- constructor(webGpu: NodeMaterialWebGpuModule, mrtResolver?: MRTOutputsResolverFn);
71
+ constructor(webGpu: NodeMaterialWebGpuModule, mrtResolver?: MRTOutputsResolverFn, environmentTextureResolver?: (texture: THREE.Texture) => THREE.Texture);
71
72
  setWorldEnvironment(environment: ResolvedWorldEnvironment | null): void;
72
73
  resolve(material: THREE.Material, drawStage?: NodeMaterialWebGpuDrawStage): ResolvedWebGpuMaterial | undefined;
73
74
  private getOrCreateOutlineMaterial;
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{compileNodeWebGpuFullscreen as t,compileNodeShaderMaterialForWebGpu as a,NodeShaderMaterial as i,webGpuRendererBindings as n,textureSampler2d as s,float as o,length as r,max as l,rgba as u,isWgslCompiler as p,isWgslFragmentCompiler as m,sqrt as c,normalize as d,transformed as h,uniformFloat as f,uniforms as M,vec4 as v,Vec3Node as y,toonMaterial as g}from"three-shader-graph";import{StandardShader as V}from"../shader/builtin/standard-shader.js";import{LambertShader as w}from"../shader/builtin/lambert-shader.js";import{ToonShader as S}from"../shader/builtin/toon-shader.js";import{UnlitShader as I}from"../shader/builtin/unlit-shader.js";import{SpriteShader as x}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as T}from"../shader-nodes/time.js";import{depthUniformName as E,farUniformName as b,nearUniformName as C,resolutionUniformName as W,sceneNormalUniformName as U}from"../shader-nodes/depth.js";import{sceneMapUniformName as A}from"../shader-nodes/scene-sample.js";const N={...n,uniformExpressions:{...n.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[T]:{type:"float",expression:"rendererElapsedTime()"},[C]:{type:"float",expression:"rendererCameraNear()"},[b]:{type:"float",expression:"rendererCameraFar()"},[W]:{type:"vec2",expression:"rendererViewportSize()"}},sceneTextures:{[A]:{semantic:"sceneColor",sampleType:"float"},[E]:{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 k extends y{constructor(e){super(),this.fallback=e}compile(e){if(!p(e))return{out:e.get(this.fallback)};if(m(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const t=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${t} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${t} = input.position;\n#endif`,out:t}}}class L extends y{constructor(e){super(),this.fallback=e}compile(e){if(!p(e))return{out:e.get(this.fallback)};if(m(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const t=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${t} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${t} = input.normal;\n#endif`,out:t}}}export function setMaterialUniformValuesAutoUpdate(e,t){e.uniformValuesAutoUpdate=t}export function markMaterialUniformValuesNeedUpdate(e){const t=e;"uniformValuesNeedsUpdate"in t?t.uniformValuesNeedsUpdate=!0:t.uniformValuesAutoVersion=(t.uniformValuesAutoVersion??0)+1}function R(e){return!1!==e.uniformValuesAutoUpdate}function F(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 D=new WeakMap,O=new WeakMap;export function createNodeMaterialSignature(e){const t=O.get(e);if(null!=t)return t;const a=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 O.set(e,a),a}export class NodeMaterialWebGpuResolver{constructor(e,t){this.webGpu=e,this.mrtResolver=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.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const t=e?.texture??null,a=e?.intensity??0;if(this.worldEnvironmentTexture!==t||this.worldEnvironmentIntensity!==a){if(this.worldEnvironmentTexture!==t)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=a,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=t,this.worldEnvironmentIntensity=a}}resolve(e,t=void 0){let n,s=!1;if(e instanceof i)n=e,this.observeNodeMaterial(n);else{const t=this.getOrCreateMappedNodeMaterial(e);if(null==t)return;n=t,s=!0}if("outline"===t){if(null==n.outputAlbedo)return;s&&_(e,n),n.userData.outlineParameters=e.userData?.outlineParameters,n=this.getOrCreateOutlineMaterial(n),s=!1}n.visible=e.visible,s&&(n.userData.receiveDecals=e.userData.receiveDecals);const o=t??"default",r=this.cache.get(n),l=r?.get(o);if(s&&null!=l&&l.sourceVersion===e.version&&l.worldEnvironmentRevision===this.worldEnvironmentRevision){const t=R(e),a=F(e);return l.material.uniformValuesAutoUpdate=t,this.syncInheritedWorldEnvironmentSource(n,l),t||l.sourceUniformValuesAutoVersion!==a?(_(e,n),l.compiled.syncLiveUniforms(l.material.uniforms),P(n,l.material.uniforms),$(n,l.material),l.sourceUniformValuesAutoVersion=a,t||(l.material.uniformValuesNeedsUpdate=!0),l.material):l.material}if(!s&&null!=l&&l.sourceVersion===e.version&&l.worldEnvironmentRevision===this.worldEnvironmentRevision&&z(n,l.compiled))return this.syncInheritedWorldEnvironmentSource(n,l),j(n,l),l.material;s&&_(e,n);const u=this.prepareWorldEnvironment(n),p=this.getNodeMaterialSignature(n,u);if(l?.signature===p&&z(n,l.compiled))return s?(l.material.uniformValuesAutoUpdate=R(e),l.compiled.syncLiveUniforms(l.material.uniforms),P(n,l.material.uniforms),$(n,l.material),l.sourceUniformValuesAutoVersion=F(e),l.material.uniformValuesAutoUpdate||(l.material.uniformValuesNeedsUpdate=!0)):j(n,l,!0),l.sourceVersion=e.version,l.worldEnvironmentRevision=this.worldEnvironmentRevision,l.material;try{const i=this.mrtResolver?.(n,t),m=a(n,N,i),c=new this.webGpu.WGSLShaderMaterial({vertexShader:m.vertexShader,fragmentShader:m.fragmentShader,depthVertexShader:m.depthVertexShader,depthFragmentShader:m.depthFragmentShader,pointShadowVertexShader:m.pointShadowVertexShader,pointShadowFragmentShader:m.pointShadowFragmentShader,uniforms:m.uniforms,textures:m.textures,sceneTextures:m.sceneTextures,graphTextures:m.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(m.vertexAttributes),uniformValuesAutoUpdate:s?R(e):n.uniformValuesAutoUpdate,transparent:m.renderState?.transparent,alphaTest:m.renderState?.alphaTest,depthTest:m.renderState?.depthTest,depthWrite:m.renderState?.depthWrite,side:m.renderState?.side,wireframe:n.wireframe});c.uniformValuesAutoUpdate=s?R(e):n.uniformValuesAutoUpdate,function(e,t){if(null==e)return;Object.assign(t,e)}(m.renderState,c),null!=l&&(l.material.dispose(),this.cacheValues.delete(l));const d={signature:p,compiled:m,material:c,inheritsWorldEnvironment:u,sourceVersion:e.version,sourceUniformValuesAutoVersion:s?F(e):n.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},h=r??new Map;return h.set(o,d),this.cache.set(n,h),this.cacheValues.add(d),P(n,c.uniforms),$(n,c),c}catch(e){let t=this.failedSignatures.get(n);if(null==t&&(t=new Map,this.failedSignatures.set(n,t)),t.get(o)!==p){t.set(o,p);const a=e instanceof Error?e.message:String(e),i=n.name||n.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${i}": ${a}`,{material:n,error:e})}return}}getOrCreateOutlineMaterial(t){let a=this.outlineMaterials.get(t);if(null==a){const n=t.nodeMaterialDefinition,s=t.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const p=f("outlineThickness",.003),m=f("outlineDarkening",.65),y=f("outlineAlpha",1),V=new k(h.position.xyz),w=new L(h.normal),S=n.transform?.multiplyVec(v(V,1))??v(V,1),I=M.modelViewMatrix.multiplyVec(S),x=d(M.normalMatrix.multiplyVec(w)),T=c(l(r(I.xyz),o(1e-4))).multiply(.5),E=I.xyz.add(x.multiplyScalar(p.multiply(T))),b=M.projectionMatrix.multiplyVec(I),C=M.projectionMatrix.multiplyVec(v(E,1)),W=(n.position??b).add(C.subtract(b)),U=u(g({color:s.rgb.multiplyScalar(o(1).subtract(m))}),t.outputOpacity.multiply(y));a=new i({color:U,position:W,opacity:t.outputOpacity,discard:n.discard,alphaTest:t.alphaTest,transparent:!0,fog:!1,outputEncoding:n.outputEncoding,uniforms:n.uniforms,uniformNodes:n.uniformNodes}),a.side=e.BackSide,a.depthTest=!0,a.depthWrite=!0,this.outlineMaterials.set(t,a)}const n=t.userData?.outlineParameters;a.uniforms.outlineThickness.value=n?.thickness??.003,a.uniforms.outlineDarkening.value=e.MathUtils.clamp(n?.darkening??.65,0,1),a.uniforms.outlineAlpha.value=e.MathUtils.clamp(n?.alpha??t.opacity,0,1),a.userData.outlineSource=t;for(const e in t.uniforms)null!=a.uniforms[e]&&(a.uniforms[e].value=t.uniforms[e].value);return a}compileFullscreen(e){const a=t({color:e.outputColor,wgslBindings:{...N,uniformExpressions:{},graphTextures:{...N.graphTextures,[U]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),i=a.syncLiveUniforms;return{...a,syncLiveUniforms(t){i(t),P(e,t)}}}getOrCreateMappedNodeMaterial(t){const a=function(t){const a=[t.vertexColors,t.transparent,t.alphaTest,t.side,t.depthTest,t.depthWrite,t.wireframe??!1];t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.roughnessMap?t.roughnessMap.uuid:null,t.metalnessMap?t.metalnessMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshLambertMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshToonMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.gradientMap?t.gradientMap.uuid:null):t instanceof e.MeshBasicMaterial?a.push(t.map?t.map.uuid:null,t.aoMap?t.aoMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshPhongMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.SpriteMaterial&&a.push(t.map?t.map.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.sizeAttenuation);return a.join(",")}(t),i=this.mappedMaterialsCache.get(t),n=this.mappedMaterialsSignatures.get(t);if(null!=i&&n===a)return i;if(null!=i){i.dispose();const e=this.cache.get(i);if(null!=e){for(const t of e.values())t.material.dispose(),this.cacheValues.delete(t);this.cache.delete(i)}}const o=function(t){if(t instanceof e.SpriteMaterial){const e=new x;e.color=t.color,e.opacity=t.opacity,e.rotation=t.rotation,e.screenSpaceSize=t.sizeAttenuation?0:1,e.alphaTest=t.alphaTest,t.map&&(e.map=t.map),t.alphaMap&&(e.alphaMap=t.alphaMap);const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a}if(t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial){const e=new V;e.color=t.color,e.opacity=t.opacity,e.roughness=t.roughness,e.metalness=t.metalness,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.roughnessMap&&(e.roughnessMap=s(t.roughnessMap)),t.metalnessMap&&(e.metalnessMap=s(t.metalnessMap)),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.envMapIntensity=t.envMapIntensity,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshLambertMaterial){const e=new w;e.color=t.color,e.opacity=t.opacity,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshToonMaterial){const e=new S;e.color=t.color,e.opacity=t.opacity,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshBasicMaterial||t instanceof e.LineBasicMaterial){const a=new I;a.color=t.color,a.opacity=t.opacity,a.vertexColor=t.vertexColors,t instanceof e.MeshBasicMaterial&&(t.map&&(a.map=s(t.map)),t.aoMap&&(a.aoMap=s(t.aoMap),a.aoMapIntensity=t.aoMapIntensity),t.lightMap&&(a.lightMap=s(t.lightMap),a.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(a.alphaMap=s(t.alphaMap)),a.envMap=t.envMap),a.alphaTest=t.alphaTest;const i=a.build();return i.transparent=t.transparent,i.side=t.side,i.depthTest=t.depthTest,i.depthWrite=t.depthWrite,i.wireframe=t instanceof e.MeshBasicMaterial&&t.wireframe,i}if(t instanceof e.MeshPhongMaterial){const e=new V;e.color=t.color,e.opacity=t.opacity,e.roughness=Math.max(0,1-t.shininess/100),e.metalness=0,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}return null}(t);return null==o?null:(o.wireframe=t.wireframe??!1,this.mappedMaterialsCache.set(t,o),this.mappedMaterialsSignatures.set(t,a),t.addEventListener("dispose",()=>{const e=this.mappedMaterialsCache.get(t);if(null!=e){e.dispose(),this.mappedMaterialsCache.delete(t),this.mappedMaterialsSignatures.delete(t);const a=this.cache.get(e);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}}}),o)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,t]of this.observedNodeMaterials)e.removeEventListener("dispose",t);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,t){t.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,t){const a=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return t?`${a}|worldEnvironment:${this.worldEnvironmentRevision}`:a}prepareWorldEnvironment(t){var a,i,n;return null!=t.envMap?(this.worldEnvironmentMaterials.has(t)&&(t.uniforms.envMap={value:t.envMap},t.uniforms.envMapIntensity={value:1},t.uniforms.envMapRotation={value:new e.Matrix3},this.worldEnvironmentMaterials.delete(t)),!1):null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(t)&&(delete t.uniforms.envMap,delete t.uniforms.envMapIntensity,delete t.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(t)),!1):((a=t.uniforms).envMap??(a.envMap={value:this.worldEnvironment.texture}),t.uniforms.envMap.value=this.worldEnvironment.texture,(i=t.uniforms).envMapIntensity??(i.envMapIntensity={value:this.worldEnvironment.intensity}),t.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(n=t.uniforms).envMapRotation??(n.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.add(t),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const t=()=>{e.removeEventListener("dispose",t),this.observedNodeMaterials.delete(e);const a=this.cache.get(e);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const i=this.outlineMaterials.get(e);if(null!=i){const t=this.cache.get(i);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(i)}this.failedSignatures.delete(i),O.delete(i),i.dispose(),this.outlineMaterials.delete(e)}this.failedSignatures.delete(e),O.delete(e)};this.observedNodeMaterials.set(e,t),e.addEventListener("dispose",t)}}function j(e,t,a=!1){const i=t.material;i.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(a||e.uniformValuesAutoUpdate||t.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(t.compiled.syncLiveUniforms(i.uniforms),P(e,i.uniforms),$(e,i),t.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,i.uniformValuesAutoUpdate||(i.uniformValuesNeedsUpdate=!0))}function P(e,t){let a=D.get(t);if(null==a){a=[];for(const e in t){const i=t[e],n=i.value,s=!0===n?.isVector2?2:!0===n?.isVector3?3:!0===n?.isVector4?4:!0===n?.isColor?5:0;a.push({name:e,target:i,copyKind:s})}D.set(t,a)}const i=e.uniforms;for(let e=0;e<a.length;e++){const t=a[e],n=i[t.name];if(null==n)continue;const s=n.value,o=t.target.value;if(s!==o){if(0!==t.copyKind){const e=s,a=o;if((2===t.copyKind?!0===e?.isVector2:3===t.copyKind?!0===e?.isVector3:4===t.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof a?.copy){a.copy(s);continue}}t.target.value=s}}}function $(t,a){const i=t.uniforms.envMapIntensity,n=a.uniforms.envMapIntensity;null!=i&&null!=n&&(n.value=i.value);const s=t.uniforms.envMapRotation?.value,o=a.uniforms.envMapRotation?.value;s instanceof e.Matrix3&&o instanceof e.Matrix3&&o.copy(s)}function z(e,t){for(const a in t.textures){const i=t.textures[a],n=e.uniforms[a]?.value;if(B(n)&&n!==i)return!1}return!0}function B(e){return!0===e?.isTexture}function _(t,a){if(t instanceof e.SpriteMaterial){const i=a;a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),i.rotation=t.rotation,i.screenSpaceSize=t.sizeAttenuation?0:1}else t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.roughness&&(a.uniforms.roughness.value=t.roughness),a.uniforms.metalness&&(a.uniforms.metalness.value=t.metalness),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity),a.uniforms.envMapIntensity&&(a.uniforms.envMapIntensity.value=t.envMapIntensity)):t instanceof e.MeshLambertMaterial||t instanceof e.MeshToonMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity)):t instanceof e.MeshBasicMaterial||t instanceof e.LineBasicMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),t instanceof e.MeshBasicMaterial&&(a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity))):t instanceof e.MeshPhongMaterial&&(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.roughness&&(a.uniforms.roughness.value=Math.max(0,1-t.shininess/100)),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity))}/*
1
+ import*as e from"three";import{compileNodeWebGpuFullscreen as t,compileNodeShaderMaterialForWebGpu as a,NodeShaderMaterial as n,webGpuRendererBindings as i,textureSampler2d as s,float as o,length as r,max as l,rgba as u,isWgslCompiler as p,isWgslFragmentCompiler as m,sqrt as c,normalize as h,transformed as d,uniformFloat as f,uniforms as M,vec4 as v,Vec3Node as y,toonMaterial as g}from"three-shader-graph";import{StandardShader as V}from"../shader/builtin/standard-shader.js";import{LambertShader as w}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 I}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as T}from"../shader-nodes/time.js";import{depthUniformName as E,farUniformName as b,nearUniformName as C,resolutionUniformName as W,sceneNormalUniformName as U}from"../shader-nodes/depth.js";import{sceneMapUniformName as A}from"../shader-nodes/scene-sample.js";const N={...i,uniformExpressions:{...i.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[T]:{type:"float",expression:"rendererElapsedTime()"},[C]:{type:"float",expression:"rendererCameraNear()"},[b]:{type:"float",expression:"rendererCameraFar()"},[W]:{type:"vec2",expression:"rendererViewportSize()"}},sceneTextures:{[A]:{semantic:"sceneColor",sampleType:"float"},[E]:{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 k extends y{constructor(e){super(),this.fallback=e}compile(e){if(!p(e))return{out:e.get(this.fallback)};if(m(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const t=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${t} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${t} = input.position;\n#endif`,out:t}}}class L extends y{constructor(e){super(),this.fallback=e}compile(e){if(!p(e))return{out:e.get(this.fallback)};if(m(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const t=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${t} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${t} = input.normal;\n#endif`,out:t}}}export function setMaterialUniformValuesAutoUpdate(e,t){e.uniformValuesAutoUpdate=t}export function markMaterialUniformValuesNeedUpdate(e){const t=e;"uniformValuesNeedsUpdate"in t?t.uniformValuesNeedsUpdate=!0:t.uniformValuesAutoVersion=(t.uniformValuesAutoVersion??0)+1}function R(e){return!1!==e.uniformValuesAutoUpdate}function F(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 D=new WeakMap,O=new WeakMap;export function createNodeMaterialSignature(e){const t=O.get(e);if(null!=t)return t;const a=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 O.set(e,a),a}export class NodeMaterialWebGpuResolver{constructor(e,t,a){this.webGpu=e,this.mrtResolver=t,this.environmentTextureResolver=a,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.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const t=e?.texture??null,a=e?.intensity??0;if(this.worldEnvironmentTexture!==t||this.worldEnvironmentIntensity!==a){if(this.worldEnvironmentTexture!==t)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=a,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=t,this.worldEnvironmentIntensity=a}}resolve(e,t=void 0){let i,s=!1;if(e instanceof n)i=e,this.observeNodeMaterial(i);else{const t=this.getOrCreateMappedNodeMaterial(e);if(null==t)return;i=t,s=!0}if("outline"===t){if(null==i.outputAlbedo)return;s&&_(e,i),i.userData.outlineParameters=e.userData?.outlineParameters,i=this.getOrCreateOutlineMaterial(i),s=!1}i.visible=e.visible,s&&(i.userData.receiveDecals=e.userData.receiveDecals);const o=t??"default",r=this.cache.get(i),l=r?.get(o);if(s&&null!=l&&l.sourceVersion===e.version&&l.worldEnvironmentRevision===this.worldEnvironmentRevision){const t=R(e),a=F(e);return l.material.uniformValuesAutoUpdate=t,this.syncInheritedWorldEnvironmentSource(i,l),t||l.sourceUniformValuesAutoVersion!==a?(_(e,i),l.compiled.syncLiveUniforms(l.material.uniforms),P(i,l.material.uniforms),$(i,l.material),l.sourceUniformValuesAutoVersion=a,t||(l.material.uniformValuesNeedsUpdate=!0),l.material):l.material}if(!s&&null!=l&&l.sourceVersion===e.version&&l.worldEnvironmentRevision===this.worldEnvironmentRevision&&z(i,l.compiled))return this.syncInheritedWorldEnvironmentSource(i,l),j(i,l),l.material;s&&_(e,i);const u=this.prepareWorldEnvironment(i),p=this.getNodeMaterialSignature(i,u);if(l?.signature===p&&z(i,l.compiled))return s?(l.material.uniformValuesAutoUpdate=R(e),l.compiled.syncLiveUniforms(l.material.uniforms),P(i,l.material.uniforms),$(i,l.material),l.sourceUniformValuesAutoVersion=F(e),l.material.uniformValuesAutoUpdate||(l.material.uniformValuesNeedsUpdate=!0)):j(i,l,!0),l.sourceVersion=e.version,l.worldEnvironmentRevision=this.worldEnvironmentRevision,l.material;try{const n=this.mrtResolver?.(i,t),m=a(i,N,n),c=new this.webGpu.WGSLShaderMaterial({vertexShader:m.vertexShader,fragmentShader:m.fragmentShader,depthVertexShader:m.depthVertexShader,depthFragmentShader:m.depthFragmentShader,pointShadowVertexShader:m.pointShadowVertexShader,pointShadowFragmentShader:m.pointShadowFragmentShader,uniforms:m.uniforms,textures:m.textures,sceneTextures:m.sceneTextures,graphTextures:m.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(m.vertexAttributes),uniformValuesAutoUpdate:s?R(e):i.uniformValuesAutoUpdate,transparent:m.renderState?.transparent,alphaTest:m.renderState?.alphaTest,depthTest:m.renderState?.depthTest,depthWrite:m.renderState?.depthWrite,side:m.renderState?.side,wireframe:i.wireframe});c.uniformValuesAutoUpdate=s?R(e):i.uniformValuesAutoUpdate,function(e,t){if(null==e)return;Object.assign(t,e)}(m.renderState,c),null!=l&&(l.material.dispose(),this.cacheValues.delete(l));const h={signature:p,compiled:m,material:c,inheritsWorldEnvironment:u,sourceVersion:e.version,sourceUniformValuesAutoVersion:s?F(e):i.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},d=r??new Map;return d.set(o,h),this.cache.set(i,d),this.cacheValues.add(h),P(i,c.uniforms),$(i,c),c}catch(e){let t=this.failedSignatures.get(i);if(null==t&&(t=new Map,this.failedSignatures.set(i,t)),t.get(o)!==p){t.set(o,p);const a=e instanceof Error?e.message:String(e),n=i.name||i.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${n}": ${a}`,{material:i,error:e})}return}}getOrCreateOutlineMaterial(t){let a=this.outlineMaterials.get(t);if(null==a){const i=t.nodeMaterialDefinition,s=t.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const p=f("outlineThickness",.003),m=f("outlineDarkening",.65),y=f("outlineAlpha",1),V=new k(d.position.xyz),w=new L(d.normal),S=i.transform?.multiplyVec(v(V,1))??v(V,1),x=M.modelViewMatrix.multiplyVec(S),I=h(M.normalMatrix.multiplyVec(w)),T=c(l(r(x.xyz),o(1e-4))).multiply(.5),E=x.xyz.add(I.multiplyScalar(p.multiply(T))),b=M.projectionMatrix.multiplyVec(x),C=M.projectionMatrix.multiplyVec(v(E,1)),W=(i.position??b).add(C.subtract(b)),U=u(g({color:s.rgb.multiplyScalar(o(1).subtract(m))}),t.outputOpacity.multiply(y));a=new n({color:U,position:W,opacity:t.outputOpacity,discard:i.discard,alphaTest:t.alphaTest,transparent:!0,fog:!1,outputEncoding:i.outputEncoding,uniforms:i.uniforms,uniformNodes:i.uniformNodes}),a.side=e.BackSide,a.depthTest=!0,a.depthWrite=!0,this.outlineMaterials.set(t,a)}const i=t.userData?.outlineParameters;a.uniforms.outlineThickness.value=i?.thickness??.003,a.uniforms.outlineDarkening.value=e.MathUtils.clamp(i?.darkening??.65,0,1),a.uniforms.outlineAlpha.value=e.MathUtils.clamp(i?.alpha??t.opacity,0,1),a.userData.outlineSource=t;for(const e in t.uniforms)null!=a.uniforms[e]&&(a.uniforms[e].value=t.uniforms[e].value);return a}compileFullscreen(e){const a=t({color:e.outputColor,wgslBindings:{...N,uniformExpressions:{},graphTextures:{...N.graphTextures,[U]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),n=a.syncLiveUniforms;return{...a,syncLiveUniforms(t){n(t),P(e,t)}}}getOrCreateMappedNodeMaterial(t){const a=function(t){const a=[t.vertexColors,t.transparent,t.alphaTest,t.side,t.depthTest,t.depthWrite,t.wireframe??!1];t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.roughnessMap?t.roughnessMap.uuid:null,t.metalnessMap?t.metalnessMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshLambertMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshToonMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.gradientMap?t.gradientMap.uuid:null):t instanceof e.MeshBasicMaterial?a.push(t.map?t.map.uuid:null,t.aoMap?t.aoMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.MeshPhongMaterial?a.push(t.map?t.map.uuid:null,t.normalMap?t.normalMap.uuid:null,t.aoMap?t.aoMap.uuid:null,t.emissiveMap?t.emissiveMap.uuid:null,t.lightMap?t.lightMap.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.envMap?t.envMap.uuid:null):t instanceof e.SpriteMaterial&&a.push(t.map?t.map.uuid:null,t.alphaMap?t.alphaMap.uuid:null,t.sizeAttenuation);return a.join(",")}(t),n=this.mappedMaterialsCache.get(t),i=this.mappedMaterialsSignatures.get(t);if(null!=n&&i===a)return n;if(null!=n){n.dispose();const e=this.cache.get(n);if(null!=e){for(const t of e.values())t.material.dispose(),this.cacheValues.delete(t);this.cache.delete(n)}}const o=function(t){if(t instanceof e.SpriteMaterial){const e=new I;e.color=t.color,e.opacity=t.opacity,e.rotation=t.rotation,e.screenSpaceSize=t.sizeAttenuation?0:1,e.alphaTest=t.alphaTest,t.map&&(e.map=t.map),t.alphaMap&&(e.alphaMap=t.alphaMap);const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a}if(t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial){const e=new V;e.color=t.color,e.opacity=t.opacity,e.roughness=t.roughness,e.metalness=t.metalness,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.roughnessMap&&(e.roughnessMap=s(t.roughnessMap)),t.metalnessMap&&(e.metalnessMap=s(t.metalnessMap)),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.envMapIntensity=t.envMapIntensity,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshLambertMaterial){const e=new w;e.color=t.color,e.opacity=t.opacity,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshToonMaterial){const e=new S;e.color=t.color,e.opacity=t.opacity,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}if(t instanceof e.MeshBasicMaterial||t instanceof e.LineBasicMaterial){const a=new x;a.color=t.color,a.opacity=t.opacity,a.vertexColor=t.vertexColors,t instanceof e.MeshBasicMaterial&&(t.map&&(a.map=s(t.map)),t.aoMap&&(a.aoMap=s(t.aoMap),a.aoMapIntensity=t.aoMapIntensity),t.lightMap&&(a.lightMap=s(t.lightMap),a.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(a.alphaMap=s(t.alphaMap)),a.envMap=t.envMap),a.alphaTest=t.alphaTest;const n=a.build();return n.transparent=t.transparent,n.side=t.side,n.depthTest=t.depthTest,n.depthWrite=t.depthWrite,n.wireframe=t instanceof e.MeshBasicMaterial&&t.wireframe,n}if(t instanceof e.MeshPhongMaterial){const e=new V;e.color=t.color,e.opacity=t.opacity,e.roughness=Math.max(0,1-t.shininess/100),e.metalness=0,e.vertexColor=t.vertexColors,t.map&&(e.map=s(t.map)),t.normalMap&&(e.normalMap=s(t.normalMap),e.normalScale=t.normalScale),t.aoMap&&(e.aoMap=s(t.aoMap),e.aoMapIntensity=t.aoMapIntensity),t.emissiveMap&&(e.emissiveMap=s(t.emissiveMap)),t.lightMap&&(e.lightMap=s(t.lightMap),e.lightMapIntensity=t.lightMapIntensity),t.alphaMap&&(e.alphaMap=s(t.alphaMap)),e.emissive=t.emissive,e.emissiveIntensity=t.emissiveIntensity,e.envMap=t.envMap,e.alphaTest=t.alphaTest;const a=e.build();return a.transparent=t.transparent,a.side=t.side,a.depthTest=t.depthTest,a.depthWrite=t.depthWrite,a.wireframe=t.wireframe,a}return null}(t);return null==o?null:(o.wireframe=t.wireframe??!1,this.mappedMaterialsCache.set(t,o),this.mappedMaterialsSignatures.set(t,a),t.addEventListener("dispose",()=>{const e=this.mappedMaterialsCache.get(t);if(null!=e){e.dispose(),this.mappedMaterialsCache.delete(t),this.mappedMaterialsSignatures.delete(t);const a=this.cache.get(e);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}}}),o)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,t]of this.observedNodeMaterials)e.removeEventListener("dispose",t);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,t){t.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,t){const a=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return t?`${a}|worldEnvironment:${this.worldEnvironmentRevision}`:a}prepareWorldEnvironment(t){var a,n,i,s,o,r;if(null!=t.envMap){const s=this.environmentTextureResolver?.(t.envMap)??t.envMap;return(a=t.uniforms).envMap??(a.envMap={value:s}),t.uniforms.envMap.value=s,(n=t.uniforms).envMapIntensity??(n.envMapIntensity={value:1}),(i=t.uniforms).envMapRotation??(i.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.delete(t),!1}return null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(t)&&(delete t.uniforms.envMap,delete t.uniforms.envMapIntensity,delete t.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(t)),!1):((s=t.uniforms).envMap??(s.envMap={value:this.worldEnvironment.texture}),t.uniforms.envMap.value=this.worldEnvironment.texture,(o=t.uniforms).envMapIntensity??(o.envMapIntensity={value:this.worldEnvironment.intensity}),t.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(r=t.uniforms).envMapRotation??(r.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.add(t),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const t=()=>{e.removeEventListener("dispose",t),this.observedNodeMaterials.delete(e);const a=this.cache.get(e);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const n=this.outlineMaterials.get(e);if(null!=n){const t=this.cache.get(n);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(n)}this.failedSignatures.delete(n),O.delete(n),n.dispose(),this.outlineMaterials.delete(e)}this.failedSignatures.delete(e),O.delete(e)};this.observedNodeMaterials.set(e,t),e.addEventListener("dispose",t)}}function j(e,t,a=!1){const n=t.material;n.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(a||e.uniformValuesAutoUpdate||t.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(t.compiled.syncLiveUniforms(n.uniforms),P(e,n.uniforms),$(e,n),t.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,n.uniformValuesAutoUpdate||(n.uniformValuesNeedsUpdate=!0))}function P(e,t){let a=D.get(t);if(null==a){a=[];for(const e in t){const n=t[e],i=n.value,s=!0===i?.isVector2?2:!0===i?.isVector3?3:!0===i?.isVector4?4:!0===i?.isColor?5:0;a.push({name:e,target:n,copyKind:s})}D.set(t,a)}const n=e.uniforms;for(let e=0;e<a.length;e++){const t=a[e],i=n[t.name];if(null==i)continue;const s=i.value,o=t.target.value;if(s!==o){if(0!==t.copyKind){const e=s,a=o;if((2===t.copyKind?!0===e?.isVector2:3===t.copyKind?!0===e?.isVector3:4===t.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof a?.copy){a.copy(s);continue}}t.target.value=s}}}function $(t,a){const n=t.uniforms.envMapIntensity,i=a.uniforms.envMapIntensity;null!=n&&null!=i&&(i.value=n.value);const s=t.uniforms.envMapRotation?.value,o=a.uniforms.envMapRotation?.value;s instanceof e.Matrix3&&o instanceof e.Matrix3&&o.copy(s)}function z(e,t){for(const a in t.textures){const n=t.textures[a],i=e.uniforms[a]?.value;if(B(i)&&i!==n)return!1}return!0}function B(e){return!0===e?.isTexture}function _(t,a){if(t instanceof e.SpriteMaterial){const n=a;a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),n.rotation=t.rotation,n.screenSpaceSize=t.sizeAttenuation?0:1}else t instanceof e.MeshStandardMaterial||t instanceof e.MeshPhysicalMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.roughness&&(a.uniforms.roughness.value=t.roughness),a.uniforms.metalness&&(a.uniforms.metalness.value=t.metalness),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity),a.uniforms.envMapIntensity&&(a.uniforms.envMapIntensity.value=t.envMapIntensity)):t instanceof e.MeshLambertMaterial||t instanceof e.MeshToonMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity)):t instanceof e.MeshBasicMaterial||t instanceof e.LineBasicMaterial?(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),t instanceof e.MeshBasicMaterial&&(a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity))):t instanceof e.MeshPhongMaterial&&(a.uniforms.color&&(a.uniforms.color.value instanceof e.Vector3?a.uniforms.color.value.setFromColor(t.color):a.uniforms.color.value instanceof e.Color&&a.uniforms.color.value.copy(t.color)),a.uniforms.opacity&&(a.uniforms.opacity.value=t.opacity),a.uniforms.roughness&&(a.uniforms.roughness.value=Math.max(0,1-t.shininess/100)),a.uniforms.emissive&&(a.uniforms.emissive.value instanceof e.Vector3?a.uniforms.emissive.value.setFromColor(t.emissive):a.uniforms.emissive.value instanceof e.Color&&a.uniforms.emissive.value.copy(t.emissive)),a.uniforms.emissiveIntensity&&(a.uniforms.emissiveIntensity.value=t.emissiveIntensity),a.uniforms.normalScale&&t.normalScale&&(a.uniforms.normalScale.value=t.normalScale.x),a.uniforms.aoMapIntensity&&(a.uniforms.aoMapIntensity.value=t.aoMapIntensity),a.uniforms.lightMapIntensity&&(a.uniforms.lightMapIntensity.value=t.lightMapIntensity))}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -31,7 +31,7 @@ export declare function sanitizePostProcessEffectPriority(priority: number | und
31
31
  export interface PostProcessEffectEntry {
32
32
  readonly id: number;
33
33
  readonly material: ShaderMaterial;
34
- pass: PostProcessEffectPass;
34
+ pass: PostProcessEffectPass | null;
35
35
  enabled: boolean;
36
36
  priority: number;
37
37
  stage: PostProcessEffectStage;
@@ -1,4 +1,4 @@
1
- import{FullScreenQuad as e,Pass as t}from"three/examples/jsm/Addons.js";import{NodeShaderMaterial as s}from"../shader-nodes/index.js";import{depthUniformName as r,farUniformName as i,nearUniformName as o,resolutionUniformName as n,sceneNormalUniformName as a}from"../shader-nodes/depth.js";import{aoMapUniformName as f,sceneMapUniformName as l}from"../shader-nodes/scene-sample.js";import{elapsedTimeUniformName as u}from"../shader-nodes/time.js";export const postProcessEffectStages=["beforeFog","beforeDepthOfField","beforeColorAdjustment","beforeOutline","beforeAntiAliasing","beforeLut","beforeOutput"];export const defaultPostProcessEffectStage="beforeOutput";export function applyPostProcessEffectUniformState(e,t){null!=e.uniforms[n]&&e.uniforms[n].value.copy(t.resolution),null!=e.uniforms[r]&&(e.uniforms[r].value=t.depthTexture),null!=e.uniforms[a]&&(e.uniforms[a].value=t.normalTexture),null!=e.uniforms[o]&&null!=t.cameraNear&&(e.uniforms[o].value=t.cameraNear),null!=e.uniforms[i]&&null!=t.cameraFar&&(e.uniforms[i].value=t.cameraFar),null!=e.uniforms[u]&&(e.uniforms[u].value=t.simulationTime),null!=e.uniforms[f]&&(e.uniforms[f].value=t.aoTexture),e instanceof s&&null!=e.uniforms[f]&&(t.aoEnabled?(null==e.defines.USE_SSAO_MAP&&(e.needsUpdate=!0),e.defines.USE_SSAO_MAP=""):null!=e.defines.USE_SSAO_MAP&&(delete e.defines.USE_SSAO_MAP,e.needsUpdate=!0))}export function sanitizePostProcessEffectStage(e){return e??"beforeOutput"}export function sanitizePostProcessEffectPriority(e){return null!=e&&Number.isFinite(e)?e:0}export class PostProcessEffectRegistration{constructor(e,t){this.owner=e,this.entry=t,this.disposed=!1}get material(){return this.entry.material}get enabled(){return this.entry.enabled}set enabled(e){this.entry.enabled!==e&&(this.entry.enabled=e,this.entry.pass.enabled=e,this.owner.refreshPostProcessEffectPassOrder())}get priority(){return this.entry.priority}set priority(e){const t=sanitizePostProcessEffectPriority(e);this.entry.priority!==t&&(this.entry.priority=t,this.owner.refreshPostProcessEffectPassOrder())}get stage(){return this.entry.stage}set stage(e){const t=sanitizePostProcessEffectStage(e);this.entry.stage!==t&&(this.entry.stage=t,this.owner.refreshPostProcessEffectPassOrder())}dispose(){this.disposed||(this.disposed=!0,this.owner.removePostProcessEffectEntry(this.entry))}}export class PostProcessEffectPass extends t{constructor(t){super(),this.material=t,this.material.depthWrite=!1,this.material.depthTest=!1,this.material.toneMapped=!1,this.fsQuad=new e(this.material),this.needsSwap=!0,this.clear=!1}updateUniformState(e){applyPostProcessEffectUniformState(this.material,e)}setMaterial(e){this.fsQuad.material=e,this.material=e}render(e,t,s,r,i){if(null!=this.material.uniforms[l]&&(this.material.uniforms[l].value=s.texture),this.renderToScreen)return e.setRenderTarget(null),this.clear&&e.clear(),void this.fsQuad.render(e);e.setRenderTarget(t),this.clear&&e.clear(),this.fsQuad.render(e)}dispose(){this.fsQuad.dispose()}}/*
1
+ import{FullScreenQuad as e,Pass as t}from"three/examples/jsm/Addons.js";import{NodeShaderMaterial as s}from"../shader-nodes/index.js";import{depthUniformName as r,farUniformName as i,nearUniformName as o,resolutionUniformName as n,sceneNormalUniformName as a}from"../shader-nodes/depth.js";import{aoMapUniformName as f,sceneMapUniformName as l}from"../shader-nodes/scene-sample.js";import{elapsedTimeUniformName as u}from"../shader-nodes/time.js";export const postProcessEffectStages=["beforeFog","beforeDepthOfField","beforeColorAdjustment","beforeOutline","beforeAntiAliasing","beforeLut","beforeOutput"];export const defaultPostProcessEffectStage="beforeOutput";export function applyPostProcessEffectUniformState(e,t){null!=e.uniforms[n]&&e.uniforms[n].value.copy(t.resolution),null!=e.uniforms[r]&&(e.uniforms[r].value=t.depthTexture),null!=e.uniforms[a]&&(e.uniforms[a].value=t.normalTexture),null!=e.uniforms[o]&&null!=t.cameraNear&&(e.uniforms[o].value=t.cameraNear),null!=e.uniforms[i]&&null!=t.cameraFar&&(e.uniforms[i].value=t.cameraFar),null!=e.uniforms[u]&&(e.uniforms[u].value=t.simulationTime),null!=e.uniforms[f]&&(e.uniforms[f].value=t.aoTexture),e instanceof s&&null!=e.uniforms[f]&&(t.aoEnabled?(null==e.defines.USE_SSAO_MAP&&(e.needsUpdate=!0),e.defines.USE_SSAO_MAP=""):null!=e.defines.USE_SSAO_MAP&&(delete e.defines.USE_SSAO_MAP,e.needsUpdate=!0))}export function sanitizePostProcessEffectStage(e){return e??"beforeOutput"}export function sanitizePostProcessEffectPriority(e){return null!=e&&Number.isFinite(e)?e:0}export class PostProcessEffectRegistration{constructor(e,t){this.owner=e,this.entry=t,this.disposed=!1}get material(){return this.entry.material}get enabled(){return this.entry.enabled}set enabled(e){this.entry.enabled!==e&&(this.entry.enabled=e,null!=this.entry.pass&&(this.entry.pass.enabled=e),this.owner.refreshPostProcessEffectPassOrder())}get priority(){return this.entry.priority}set priority(e){const t=sanitizePostProcessEffectPriority(e);this.entry.priority!==t&&(this.entry.priority=t,this.owner.refreshPostProcessEffectPassOrder())}get stage(){return this.entry.stage}set stage(e){const t=sanitizePostProcessEffectStage(e);this.entry.stage!==t&&(this.entry.stage=t,this.owner.refreshPostProcessEffectPassOrder())}dispose(){this.disposed||(this.disposed=!0,this.owner.removePostProcessEffectEntry(this.entry))}}export class PostProcessEffectPass extends t{constructor(t){super(),this.material=t,this.material.depthWrite=!1,this.material.depthTest=!1,this.material.toneMapped=!1,this.fsQuad=new e(this.material),this.needsSwap=!0,this.clear=!1}updateUniformState(e){applyPostProcessEffectUniformState(this.material,e)}setMaterial(e){this.fsQuad.material=e,this.material=e}render(e,t,s,r,i){if(null!=this.material.uniforms[l]&&(this.material.uniforms[l].value=s.texture),this.renderToScreen)return e.setRenderTarget(null),this.clear&&e.clear(),void this.fsQuad.render(e);e.setRenderTarget(t),this.clear&&e.clear(),this.fsQuad.render(e)}dispose(){this.fsQuad.dispose()}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,9 @@
1
+ import type { Texture } from 'three';
2
+ /** Backend-neutral operations used by RenderingView and resource materializers. */
3
+ export interface RenderingBackendDriver {
4
+ readonly kind: 'webgl' | 'webgpu';
5
+ readonly canvas: HTMLCanvasElement;
6
+ initTexture(texture: Texture): void;
7
+ getEnvironmentTexture(texture: Texture): Texture;
8
+ }
9
+ //# sourceMappingURL=rendering-backend.d.ts.map
@@ -0,0 +1,4 @@
1
+ export{};/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,6 +1,11 @@
1
1
  import * as THREE from 'three';
2
2
  import { Pass } from 'three/examples/jsm/postprocessing/Pass.js';
3
- export type UpscalingMethod = 'linear' | 'spatial' | 'catmull-rom' | 'temporal';
3
+ export type UpscalingMethod = 'linear' | 'spatial' | 'catmull-rom' | 'temporal' | 'dlss';
4
+ export type DlssQualityMode = 'quality' | 'balanced' | 'performance' | 'ultra-performance';
5
+ export type DlssUpscalingOptions = {
6
+ /** Streamline DLSS performance/quality mode. Defaults to `quality`. */
7
+ mode?: DlssQualityMode;
8
+ };
4
9
  export type TemporalUpscalingOptions = {
5
10
  /**
6
11
  * How strongly history contributes to the current frame. Defaults to 0.88.
@@ -15,6 +20,8 @@ export type UpscalingOptions = {
15
20
  enabled?: boolean;
16
21
  /**
17
22
  * `temporal` jitters the projection and accumulates history using depth reprojection.
23
+ * `dlss` requests native DLSS Super Resolution and falls back to temporal
24
+ * upscaling when the host does not expose a compatible implementation.
18
25
  * `spatial` and `catmull-rom` are single-frame upscalers with sharpening.
19
26
  * `linear` only decouples render and presentation resolutions.
20
27
  */
@@ -24,6 +31,7 @@ export type UpscalingOptions = {
24
31
  */
25
32
  sharpness?: number;
26
33
  temporal?: TemporalUpscalingOptions;
34
+ dlss?: DlssUpscalingOptions;
27
35
  };
28
36
  export type TemporalUpscalingFrameState = {
29
37
  depthTexture: THREE.Texture | null;
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{Pass as t,FullScreenQuad as r}from"three/examples/jsm/postprocessing/Pass.js";export function getUpscalingMethod(e){return e?.method??"spatial"}export function getTemporalUpscalingJitter(e,t,r=1){return t.set((n(e%1024+1,2)-.5)*r,(n(e%1024+1,3)-.5)*r),t}export class UpscaleOutputPass extends t{constructor(t={}){super(),this.options=t,this.uniforms={tDiffuse:{value:null},tDepth:{value:null},tHistory:{value:null},toneMappingExposure:{value:1},inputSize:{value:new e.Vector2(1,1)},sharpness:{value:.2},temporalFeedback:{value:.88},historyValid:{value:0},currentJitterUv:{value:new e.Vector2},currentViewProjectionInverse:{value:new e.Matrix4},previousViewProjection:{value:new e.Matrix4}},this.drawingBufferSize=new e.Vector2,this.historyRead=null,this.historyWrite=null,this.historyValid=!1,this.frameState=null,this._outputColorSpace=null,this._toneMapping=null,this._method=null,this._usesCatmullRom=null,this._usesTemporal=null,this.material=new e.RawShaderMaterial({name:"UpscaleOutputPass",uniforms:this.uniforms,vertexShader:o,fragmentShader:a}),this.fsQuad=new r(this.material)}setFrameState(e){this.frameState=e}resetHistory(){this.historyValid=!1}render(t,r,n){t.getDrawingBufferSize(this.drawingBufferSize);const o=getUpscalingMethod(this.options),a=n.width<this.drawingBufferSize.x-.5||n.height<this.drawingBufferSize.y-.5,s="temporal"===o&&null!=this.frameState&&null!=this.frameState.depthTexture,l=a&&(s||"spatial"===o||"catmull-rom"===o);if(this.uniforms.tDiffuse.value=n.texture,this.uniforms.tDepth.value=this.frameState?.depthTexture??null,this.uniforms.toneMappingExposure.value=t.toneMappingExposure,this.uniforms.inputSize.value.set(n.width,n.height),this.uniforms.sharpness.value=e.MathUtils.clamp(i(this.options.sharpness,.2),0,1),this.uniforms.temporalFeedback.value=e.MathUtils.clamp(i(this.options.temporal?.feedback,.88),0,.97),s?(this.ensureHistoryTargets(this.drawingBufferSize.x,this.drawingBufferSize.y),this.uniforms.tHistory.value=this.historyRead?.texture??null,this.uniforms.historyValid.value=this.historyValid?1:0,this.uniforms.currentJitterUv.value.copy(this.frameState.currentJitterUv),this.uniforms.currentViewProjectionInverse.value.copy(this.frameState.currentViewProjectionInverse),this.uniforms.previousViewProjection.value.copy(this.frameState.previousViewProjection)):(this.uniforms.tHistory.value=null,this.uniforms.historyValid.value=0,this.uniforms.currentJitterUv.value.set(0,0)),this.updateDefines(t,o,l,s),!0===this.renderToScreen?(t.setRenderTarget(null),this.fsQuad.render(t)):(t.setRenderTarget(r),this.clear&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),this.fsQuad.render(t)),s&&null!=this.historyWrite){t.setRenderTarget(this.historyWrite),this.fsQuad.render(t);const e=this.historyRead;this.historyRead=this.historyWrite,this.historyWrite=e,this.historyValid=!0}else s||(this.historyValid=!1)}dispose(){this.material.dispose(),this.fsQuad.dispose(),this.disposeHistoryTargets()}updateDefines(t,r,i,n){this._outputColorSpace===t.outputColorSpace&&this._toneMapping===t.toneMapping&&this._method===r&&this._usesCatmullRom===i&&this._usesTemporal===n||(this._outputColorSpace=t.outputColorSpace,this._toneMapping=t.toneMapping,this._method=r,this._usesCatmullRom=i,this._usesTemporal=n,this.material.defines={},i&&(this.material.defines.CATMULL_ROM_UPSCALE=""),n&&(this.material.defines.TEMPORAL_UPSCALE=""),e.ColorManagement.getTransfer(t.outputColorSpace)===e.SRGBTransfer&&(this.material.defines.SRGB_TRANSFER=""),t.toneMapping===e.LinearToneMapping?this.material.defines.LINEAR_TONE_MAPPING="":t.toneMapping===e.ReinhardToneMapping?this.material.defines.REINHARD_TONE_MAPPING="":t.toneMapping===e.CineonToneMapping?this.material.defines.CINEON_TONE_MAPPING="":t.toneMapping===e.ACESFilmicToneMapping?this.material.defines.ACES_FILMIC_TONE_MAPPING="":t.toneMapping===e.AgXToneMapping?this.material.defines.AGX_TONE_MAPPING="":t.toneMapping===e.NeutralToneMapping&&(this.material.defines.NEUTRAL_TONE_MAPPING=""),this.material.needsUpdate=!0)}ensureHistoryTargets(e,t){const r=Math.max(1,Math.floor(e)),i=Math.max(1,Math.floor(t));null!=this.historyRead&&null!=this.historyWrite&&this.historyRead.width===r&&this.historyRead.height===i||(this.disposeHistoryTargets(),this.historyRead=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyRead"),this.historyWrite=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyWrite"),this.historyValid=!1)}createHistoryTarget(t,r,i){const n=new e.WebGLRenderTarget(t,r,{type:e.HalfFloatType,minFilter:e.LinearFilter,magFilter:e.LinearFilter,format:e.RGBAFormat,depthBuffer:!1,stencilBuffer:!1});return n.texture.name=i,n.texture.generateMipmaps=!1,n}disposeHistoryTargets(){this.historyRead?.dispose(),this.historyWrite?.dispose(),this.historyRead=null,this.historyWrite=null,this.historyValid=!1}}function i(e,t){return null!=e&&Number.isFinite(e)?e:t}function n(e,t){let r=0,i=1/t;for(;e>0;)r+=i*(e%t),e=Math.floor(e/t),i/=t;return r}const o="\n precision highp float;\n\n uniform mat4 modelViewMatrix;\n uniform mat4 projectionMatrix;\n\n attribute vec3 position;\n attribute vec2 uv;\n\n varying vec2 vUv;\n\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n",a="\n precision highp float;\n\n uniform sampler2D tDiffuse;\n uniform sampler2D tDepth;\n uniform sampler2D tHistory;\n uniform vec2 inputSize;\n uniform float sharpness;\n uniform float temporalFeedback;\n uniform float historyValid;\n uniform vec2 currentJitterUv;\n uniform mat4 currentViewProjectionInverse;\n uniform mat4 previousViewProjection;\n\n #include <common>\n #include <tonemapping_pars_fragment>\n #include <colorspace_pars_fragment>\n #include <dithering_pars_fragment>\n\n varying vec2 vUv;\n\n vec4 applyOutputTransform(vec4 color) {\n #ifdef LINEAR_TONE_MAPPING\n color.rgb = LinearToneMapping(color.rgb);\n #elif defined(REINHARD_TONE_MAPPING)\n color.rgb = ReinhardToneMapping(color.rgb);\n #elif defined(CINEON_TONE_MAPPING)\n color.rgb = CineonToneMapping(color.rgb);\n #elif defined(ACES_FILMIC_TONE_MAPPING)\n color.rgb = ACESFilmicToneMapping(color.rgb);\n #elif defined(AGX_TONE_MAPPING)\n color.rgb = AgXToneMapping(color.rgb);\n #elif defined(NEUTRAL_TONE_MAPPING)\n color.rgb = NeutralToneMapping(color.rgb);\n #endif\n\n #ifdef SRGB_TRANSFER\n color = sRGBTransferOETF(color);\n #endif\n\n return color;\n }\n\n vec4 readOutputColor(vec2 uv) {\n return applyOutputTransform(texture2D(tDiffuse, clamp(uv, vec2(0.0), vec2(1.0))));\n }\n\n float cubicWeight(float value) {\n value = abs(value);\n float value2 = value * value;\n float value3 = value2 * value;\n if (value <= 1.0) {\n return 1.5 * value3 - 2.5 * value2 + 1.0;\n }\n if (value < 2.0) {\n return -0.5 * value3 + 2.5 * value2 - 4.0 * value + 2.0;\n }\n return 0.0;\n }\n\n vec4 sampleCatmullRom(vec2 uv) {\n vec2 texelSize = 1.0 / inputSize;\n vec2 pixel = uv * inputSize - 0.5;\n vec2 basePixel = floor(pixel);\n vec2 fraction = pixel - basePixel;\n vec4 color = vec4(0.0);\n float weightSum = 0.0;\n\n for (int y = -1; y <= 2; y++) {\n float wy = cubicWeight(float(y) - fraction.y);\n for (int x = -1; x <= 2; x++) {\n float wx = cubicWeight(float(x) - fraction.x);\n float weight = wx * wy;\n vec2 sampleUv = (basePixel + vec2(float(x), float(y)) + 0.5) * texelSize;\n color += readOutputColor(sampleUv) * weight;\n weightSum += weight;\n }\n }\n\n return color / max(weightSum, 0.00001);\n }\n\n void getNeighborhoodBounds(vec2 uv, out vec3 minColor, out vec3 maxColor, out vec3 blurColor) {\n vec2 texelSize = 1.0 / inputSize;\n vec3 center = readOutputColor(uv).rgb;\n vec3 north = readOutputColor(uv + vec2(0.0, texelSize.y)).rgb;\n vec3 south = readOutputColor(uv - vec2(0.0, texelSize.y)).rgb;\n vec3 east = readOutputColor(uv + vec2(texelSize.x, 0.0)).rgb;\n vec3 west = readOutputColor(uv - vec2(texelSize.x, 0.0)).rgb;\n minColor = min(center, min(min(north, south), min(east, west)));\n maxColor = max(center, max(max(north, south), max(east, west)));\n blurColor = (north + south + east + west) * 0.25;\n }\n\n vec3 applyContrastLimitedSharpen(vec2 uv, vec3 color) {\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(uv, minColor, maxColor, blurColor);\n return clamp(color + (color - blurColor) * sharpness, minColor, maxColor);\n }\n\n vec2 reprojectHistoryUv(vec2 uv, float depth) {\n vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 world = currentViewProjectionInverse * clip;\n world /= max(abs(world.w), 0.00001);\n vec4 previousClip = previousViewProjection * world;\n vec3 previousNdc = previousClip.xyz / max(abs(previousClip.w), 0.00001);\n return previousNdc.xy * 0.5 + 0.5;\n }\n\n vec4 applyTemporal(vec2 currentUv, vec4 currentColor) {\n if (historyValid < 0.5) {\n return currentColor;\n }\n\n float depth = texture2D(tDepth, clamp(currentUv, vec2(0.0), vec2(1.0))).x;\n if (depth <= 0.0 || depth >= 1.0) {\n return currentColor;\n }\n\n vec2 historyUv = reprojectHistoryUv(currentUv, depth);\n if (\n historyUv.x < 0.0 || historyUv.x > 1.0 ||\n historyUv.y < 0.0 || historyUv.y > 1.0\n ) {\n return currentColor;\n }\n\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(currentUv, minColor, maxColor, blurColor);\n vec4 historyColor = texture2D(tHistory, historyUv);\n historyColor.rgb = clamp(historyColor.rgb, minColor, maxColor);\n return mix(currentColor, historyColor, temporalFeedback);\n }\n\n void main() {\n vec2 currentUv = vUv;\n #ifdef TEMPORAL_UPSCALE\n currentUv -= currentJitterUv;\n #endif\n\n #ifdef CATMULL_ROM_UPSCALE\n gl_FragColor = sampleCatmullRom(currentUv);\n gl_FragColor.rgb = applyContrastLimitedSharpen(currentUv, gl_FragColor.rgb);\n #else\n gl_FragColor = readOutputColor(currentUv);\n #endif\n\n #ifdef TEMPORAL_UPSCALE\n gl_FragColor = applyTemporal(currentUv, gl_FragColor);\n #endif\n\n #include <dithering_fragment>\n }\n";/*
1
+ import*as e from"three";import{Pass as t,FullScreenQuad as r}from"three/examples/jsm/postprocessing/Pass.js";export function getUpscalingMethod(e){return e?.method??"spatial"}export function getTemporalUpscalingJitter(e,t,r=1){return t.set((n(e%1024+1,2)-.5)*r,(n(e%1024+1,3)-.5)*r),t}export class UpscaleOutputPass extends t{constructor(t={}){super(),this.options=t,this.uniforms={tDiffuse:{value:null},tDepth:{value:null},tHistory:{value:null},toneMappingExposure:{value:1},inputSize:{value:new e.Vector2(1,1)},sharpness:{value:.2},temporalFeedback:{value:.88},historyValid:{value:0},currentJitterUv:{value:new e.Vector2},currentViewProjectionInverse:{value:new e.Matrix4},previousViewProjection:{value:new e.Matrix4}},this.drawingBufferSize=new e.Vector2,this.historyRead=null,this.historyWrite=null,this.historyValid=!1,this.frameState=null,this._outputColorSpace=null,this._toneMapping=null,this._method=null,this._usesCatmullRom=null,this._usesTemporal=null,this.material=new e.RawShaderMaterial({name:"UpscaleOutputPass",uniforms:this.uniforms,vertexShader:o,fragmentShader:a}),this.fsQuad=new r(this.material)}setFrameState(e){this.frameState=e}resetHistory(){this.historyValid=!1}render(t,r,n){t.getDrawingBufferSize(this.drawingBufferSize);const o=getUpscalingMethod(this.options),a=n.width<this.drawingBufferSize.x-.5||n.height<this.drawingBufferSize.y-.5,s=("temporal"===o||"dlss"===o)&&null!=this.frameState&&null!=this.frameState.depthTexture,l=a&&(s||"spatial"===o||"catmull-rom"===o);if(this.uniforms.tDiffuse.value=n.texture,this.uniforms.tDepth.value=this.frameState?.depthTexture??null,this.uniforms.toneMappingExposure.value=t.toneMappingExposure,this.uniforms.inputSize.value.set(n.width,n.height),this.uniforms.sharpness.value=e.MathUtils.clamp(i(this.options.sharpness,.2),0,1),this.uniforms.temporalFeedback.value=e.MathUtils.clamp(i(this.options.temporal?.feedback,.88),0,.97),s?(this.ensureHistoryTargets(this.drawingBufferSize.x,this.drawingBufferSize.y),this.uniforms.tHistory.value=this.historyRead?.texture??null,this.uniforms.historyValid.value=this.historyValid?1:0,this.uniforms.currentJitterUv.value.copy(this.frameState.currentJitterUv),this.uniforms.currentViewProjectionInverse.value.copy(this.frameState.currentViewProjectionInverse),this.uniforms.previousViewProjection.value.copy(this.frameState.previousViewProjection)):(this.uniforms.tHistory.value=null,this.uniforms.historyValid.value=0,this.uniforms.currentJitterUv.value.set(0,0)),this.updateDefines(t,o,l,s),!0===this.renderToScreen?(t.setRenderTarget(null),this.fsQuad.render(t)):(t.setRenderTarget(r),this.clear&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),this.fsQuad.render(t)),s&&null!=this.historyWrite){t.setRenderTarget(this.historyWrite),this.fsQuad.render(t);const e=this.historyRead;this.historyRead=this.historyWrite,this.historyWrite=e,this.historyValid=!0}else s||(this.historyValid=!1)}dispose(){this.material.dispose(),this.fsQuad.dispose(),this.disposeHistoryTargets()}updateDefines(t,r,i,n){this._outputColorSpace===t.outputColorSpace&&this._toneMapping===t.toneMapping&&this._method===r&&this._usesCatmullRom===i&&this._usesTemporal===n||(this._outputColorSpace=t.outputColorSpace,this._toneMapping=t.toneMapping,this._method=r,this._usesCatmullRom=i,this._usesTemporal=n,this.material.defines={},i&&(this.material.defines.CATMULL_ROM_UPSCALE=""),n&&(this.material.defines.TEMPORAL_UPSCALE=""),e.ColorManagement.getTransfer(t.outputColorSpace)===e.SRGBTransfer&&(this.material.defines.SRGB_TRANSFER=""),t.toneMapping===e.LinearToneMapping?this.material.defines.LINEAR_TONE_MAPPING="":t.toneMapping===e.ReinhardToneMapping?this.material.defines.REINHARD_TONE_MAPPING="":t.toneMapping===e.CineonToneMapping?this.material.defines.CINEON_TONE_MAPPING="":t.toneMapping===e.ACESFilmicToneMapping?this.material.defines.ACES_FILMIC_TONE_MAPPING="":t.toneMapping===e.AgXToneMapping?this.material.defines.AGX_TONE_MAPPING="":t.toneMapping===e.NeutralToneMapping&&(this.material.defines.NEUTRAL_TONE_MAPPING=""),this.material.needsUpdate=!0)}ensureHistoryTargets(e,t){const r=Math.max(1,Math.floor(e)),i=Math.max(1,Math.floor(t));null!=this.historyRead&&null!=this.historyWrite&&this.historyRead.width===r&&this.historyRead.height===i||(this.disposeHistoryTargets(),this.historyRead=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyRead"),this.historyWrite=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyWrite"),this.historyValid=!1)}createHistoryTarget(t,r,i){const n=new e.WebGLRenderTarget(t,r,{type:e.HalfFloatType,minFilter:e.LinearFilter,magFilter:e.LinearFilter,format:e.RGBAFormat,depthBuffer:!1,stencilBuffer:!1});return n.texture.name=i,n.texture.generateMipmaps=!1,n}disposeHistoryTargets(){this.historyRead?.dispose(),this.historyWrite?.dispose(),this.historyRead=null,this.historyWrite=null,this.historyValid=!1}}function i(e,t){return null!=e&&Number.isFinite(e)?e:t}function n(e,t){let r=0,i=1/t;for(;e>0;)r+=i*(e%t),e=Math.floor(e/t),i/=t;return r}const o="\n precision highp float;\n\n uniform mat4 modelViewMatrix;\n uniform mat4 projectionMatrix;\n\n attribute vec3 position;\n attribute vec2 uv;\n\n varying vec2 vUv;\n\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n",a="\n precision highp float;\n\n uniform sampler2D tDiffuse;\n uniform sampler2D tDepth;\n uniform sampler2D tHistory;\n uniform vec2 inputSize;\n uniform float sharpness;\n uniform float temporalFeedback;\n uniform float historyValid;\n uniform vec2 currentJitterUv;\n uniform mat4 currentViewProjectionInverse;\n uniform mat4 previousViewProjection;\n\n #include <common>\n #include <tonemapping_pars_fragment>\n #include <colorspace_pars_fragment>\n #include <dithering_pars_fragment>\n\n varying vec2 vUv;\n\n vec4 applyOutputTransform(vec4 color) {\n #ifdef LINEAR_TONE_MAPPING\n color.rgb = LinearToneMapping(color.rgb);\n #elif defined(REINHARD_TONE_MAPPING)\n color.rgb = ReinhardToneMapping(color.rgb);\n #elif defined(CINEON_TONE_MAPPING)\n color.rgb = CineonToneMapping(color.rgb);\n #elif defined(ACES_FILMIC_TONE_MAPPING)\n color.rgb = ACESFilmicToneMapping(color.rgb);\n #elif defined(AGX_TONE_MAPPING)\n color.rgb = AgXToneMapping(color.rgb);\n #elif defined(NEUTRAL_TONE_MAPPING)\n color.rgb = NeutralToneMapping(color.rgb);\n #endif\n\n #ifdef SRGB_TRANSFER\n color = sRGBTransferOETF(color);\n #endif\n\n return color;\n }\n\n vec4 readOutputColor(vec2 uv) {\n return applyOutputTransform(texture2D(tDiffuse, clamp(uv, vec2(0.0), vec2(1.0))));\n }\n\n float cubicWeight(float value) {\n value = abs(value);\n float value2 = value * value;\n float value3 = value2 * value;\n if (value <= 1.0) {\n return 1.5 * value3 - 2.5 * value2 + 1.0;\n }\n if (value < 2.0) {\n return -0.5 * value3 + 2.5 * value2 - 4.0 * value + 2.0;\n }\n return 0.0;\n }\n\n vec4 sampleCatmullRom(vec2 uv) {\n vec2 texelSize = 1.0 / inputSize;\n vec2 pixel = uv * inputSize - 0.5;\n vec2 basePixel = floor(pixel);\n vec2 fraction = pixel - basePixel;\n vec4 color = vec4(0.0);\n float weightSum = 0.0;\n\n for (int y = -1; y <= 2; y++) {\n float wy = cubicWeight(float(y) - fraction.y);\n for (int x = -1; x <= 2; x++) {\n float wx = cubicWeight(float(x) - fraction.x);\n float weight = wx * wy;\n vec2 sampleUv = (basePixel + vec2(float(x), float(y)) + 0.5) * texelSize;\n color += readOutputColor(sampleUv) * weight;\n weightSum += weight;\n }\n }\n\n return color / max(weightSum, 0.00001);\n }\n\n void getNeighborhoodBounds(vec2 uv, out vec3 minColor, out vec3 maxColor, out vec3 blurColor) {\n vec2 texelSize = 1.0 / inputSize;\n vec3 center = readOutputColor(uv).rgb;\n vec3 north = readOutputColor(uv + vec2(0.0, texelSize.y)).rgb;\n vec3 south = readOutputColor(uv - vec2(0.0, texelSize.y)).rgb;\n vec3 east = readOutputColor(uv + vec2(texelSize.x, 0.0)).rgb;\n vec3 west = readOutputColor(uv - vec2(texelSize.x, 0.0)).rgb;\n minColor = min(center, min(min(north, south), min(east, west)));\n maxColor = max(center, max(max(north, south), max(east, west)));\n blurColor = (north + south + east + west) * 0.25;\n }\n\n vec3 applyContrastLimitedSharpen(vec2 uv, vec3 color) {\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(uv, minColor, maxColor, blurColor);\n return clamp(color + (color - blurColor) * sharpness, minColor, maxColor);\n }\n\n vec2 reprojectHistoryUv(vec2 uv, float depth) {\n vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 world = currentViewProjectionInverse * clip;\n world /= max(abs(world.w), 0.00001);\n vec4 previousClip = previousViewProjection * world;\n vec3 previousNdc = previousClip.xyz / max(abs(previousClip.w), 0.00001);\n return previousNdc.xy * 0.5 + 0.5;\n }\n\n vec4 applyTemporal(vec2 currentUv, vec4 currentColor) {\n if (historyValid < 0.5) {\n return currentColor;\n }\n\n float depth = texture2D(tDepth, clamp(currentUv, vec2(0.0), vec2(1.0))).x;\n if (depth <= 0.0 || depth >= 1.0) {\n return currentColor;\n }\n\n vec2 historyUv = reprojectHistoryUv(currentUv, depth);\n if (\n historyUv.x < 0.0 || historyUv.x > 1.0 ||\n historyUv.y < 0.0 || historyUv.y > 1.0\n ) {\n return currentColor;\n }\n\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(currentUv, minColor, maxColor, blurColor);\n vec4 historyColor = texture2D(tHistory, historyUv);\n historyColor.rgb = clamp(historyColor.rgb, minColor, maxColor);\n return mix(currentColor, historyColor, temporalFeedback);\n }\n\n void main() {\n vec2 currentUv = vUv;\n #ifdef TEMPORAL_UPSCALE\n currentUv -= currentJitterUv;\n #endif\n\n #ifdef CATMULL_ROM_UPSCALE\n gl_FragColor = sampleCatmullRom(currentUv);\n gl_FragColor.rgb = applyContrastLimitedSharpen(currentUv, gl_FragColor.rgb);\n #else\n gl_FragColor = readOutputColor(currentUv);\n #endif\n\n #ifdef TEMPORAL_UPSCALE\n gl_FragColor = applyTemporal(currentUv, gl_FragColor);\n #endif\n\n #include <dithering_fragment>\n }\n";/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,32 @@
1
+ import * as THREE from 'three';
2
+ import type { RenderingBackendDriver } from './rendering-backend.js';
3
+ import { OutlineEffect } from './outline-effect.js';
4
+ export interface WebGlBackendOptions {
5
+ readonly container: HTMLElement;
6
+ readonly pixelRatio: number;
7
+ readonly enableXR: boolean;
8
+ readonly shadows: {
9
+ readonly enabled: boolean;
10
+ readonly autoUpdate: boolean;
11
+ };
12
+ }
13
+ /**
14
+ * Owns renderer-specific resource preparation for the legacy WebGL pipeline.
15
+ * RenderingView deliberately delegates through this adapter so resource-loading
16
+ * code never has to infer which concrete renderer happens to be active.
17
+ */
18
+ export declare class WebGlBackend implements RenderingBackendDriver {
19
+ readonly renderer: THREE.WebGLRenderer;
20
+ readonly outlineEffect: OutlineEffect;
21
+ readonly kind: "webgl";
22
+ readonly canvas: HTMLCanvasElement;
23
+ private pmremGenerator;
24
+ private readonly pmremResults;
25
+ private readonly ownedPmremResults;
26
+ private constructor();
27
+ static initialize(options: WebGlBackendOptions): WebGlBackend;
28
+ initTexture(texture: THREE.Texture): void;
29
+ getEnvironmentTexture(texture: THREE.Texture): THREE.Texture;
30
+ dispose(): void;
31
+ }
32
+ //# sourceMappingURL=webgl-backend.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as e from"three";import{VRButton as t}from"three-stdlib";import{RectAreaLightUniformsLib as r}from"three/examples/jsm/lights/RectAreaLightUniformsLib.js";import{OutlineEffect as n}from"./outline-effect.js";export class WebGlBackend{constructor(e,t){this.renderer=e,this.outlineEffect=t,this.kind="webgl",this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.canvas=e.domElement}static initialize(i){r.init();const a=window,o=a.renderer??new e.WebGLRenderer({antialias:!1,powerPreference:"high-performance"});return a.renderer=o,o.setPixelRatio(i.pixelRatio),o.setSize(i.container.clientWidth,i.container.clientHeight),o.xr.enabled=i.enableXR,i.enableXR&&document.body.appendChild(t.createButton(o)),o.shadowMap.enabled=i.shadows.enabled,o.shadowMap.type=e.PCFSoftShadowMap,o.shadowMap.autoUpdate=i.shadows.autoUpdate,o.outputColorSpace=e.SRGBColorSpace,o.toneMapping=e.NoToneMapping,o.toneMappingExposure=1,o.gammaFactor=1.4,o.debug.checkShaderErrors=!1,new WebGlBackend(o,new n(o,{defaultThickness:.005,defaultColor:[0,0,0],defaultAlpha:1,defaultKeepAlive:!0}))}initTexture(e){this.renderer.initTexture(e)}getEnvironmentTexture(t){if(t.mapping===e.CubeUVReflectionMapping)return t;let r=this.pmremResults.get(t);return null==r&&(null==this.pmremGenerator&&(this.pmremGenerator=new e.PMREMGenerator(this.renderer),this.pmremGenerator.compileEquirectangularShader()),r=this.pmremGenerator.fromEquirectangular(t),this.pmremResults.set(t,r),this.ownedPmremResults.add(r)),r.texture}dispose(){this.pmremGenerator?.dispose(),this.pmremGenerator=null;for(const e of this.ownedPmremResults)e.dispose();this.ownedPmremResults.clear()}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,7 +1,9 @@
1
1
  import * as THREE from 'three';
2
2
  import { NodeMaterialWebGpuResolver } from './node-material-webgpu-resolver.js';
3
3
  import type { WorldEnvironmentState } from './environment.js';
4
+ import type { RenderingBackendDriver } from './rendering-backend.js';
4
5
  import type { PostProcessEffectStage } from './post-process-effect.js';
6
+ import type { DlssQualityMode } from './upscaling-pass.js';
5
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';
6
8
  export type { RendererFrameProfile, GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
7
9
  type SupportedCamera = THREE.PerspectiveCamera | THREE.OrthographicCamera;
@@ -12,6 +14,11 @@ export type ExperimentalWebGpuRenderGraphExtension = ((graph: FrameGraphBuilder,
12
14
  stage?: 'beforeScene' | 'afterScene';
13
15
  };
14
16
  export interface ExperimentalWebGpuPostProcessingOptions {
17
+ /** Request native DLSS-SR when supported by the host. Falls back to TAA. */
18
+ readonly nativeUpscaling?: false | {
19
+ readonly method: 'dlss';
20
+ readonly mode?: DlssQualityMode;
21
+ };
15
22
  readonly bloom?: false | BloomOptions;
16
23
  /**
17
24
  * Selects one mutually exclusive antialiasing method. When present, all
@@ -73,7 +80,7 @@ export interface WebGpuSceneCapabilitySummary {
73
80
  materialsReplaced: number;
74
81
  unsupportedCamera: number;
75
82
  }
76
- export declare class ExperimentalWebGpuBackend {
83
+ export declare class ExperimentalWebGpuBackend implements RenderingBackendDriver {
77
84
  private readonly renderer;
78
85
  private readonly fallbackMaterial;
79
86
  private readonly nodeMaterialResolver;
@@ -93,6 +100,8 @@ export declare class ExperimentalWebGpuBackend {
93
100
  private readonly renderGraphExtensions;
94
101
  private readonly antiAliasingState;
95
102
  private readonly directionalShadowState;
103
+ private readonly nativeDlss;
104
+ readonly kind: "webgpu";
96
105
  readonly canvas: HTMLCanvasElement;
97
106
  private renderScale;
98
107
  private pmremGenerator;
@@ -100,7 +109,14 @@ export declare class ExperimentalWebGpuBackend {
100
109
  private readonly ownedPmremResults;
101
110
  private readonly warnedUnsupportedPostProcessStages;
102
111
  private constructor();
103
- static create(postProcessing?: ExperimentalWebGpuPostProcessingOptions): Promise<ExperimentalWebGpuBackend>;
112
+ static probeAvailability(): Promise<{
113
+ available: true;
114
+ adapter: GPUAdapter;
115
+ } | {
116
+ available: false;
117
+ reason: string;
118
+ }>;
119
+ static create(postProcessing?: ExperimentalWebGpuPostProcessingOptions, adapter?: GPUAdapter): Promise<ExperimentalWebGpuBackend>;
104
120
  static supportsCamera(camera: THREE.Camera): camera is SupportedCamera;
105
121
  setSize(width: number, height: number, presentationPixelRatio: number, renderScale?: number): void;
106
122
  initTexture(texture: THREE.Texture): void;
@@ -117,6 +133,7 @@ export declare class ExperimentalWebGpuBackend {
117
133
  }[], lights?: readonly THREE.DirectionalLight[]): void;
118
134
  setDirectionalShadowOptions(enabled: boolean, mapSize: number): void;
119
135
  setWorldEnvironment(environment: WorldEnvironmentState | null): void;
136
+ getEnvironmentTexture(texture: THREE.Texture): THREE.Texture;
120
137
  /**
121
138
  * Invalidates state whose contents belong to the previously presented view.
122
139
  * GPU resource and pipeline caches intentionally remain resident.
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{NodeMaterialWebGpuResolver as t}from"./node-material-webgpu-resolver.js";import{float as i,varyingTransformed as n,vec4 as o}from"three-shader-graph";import{NodeShaderMaterial as r}from"../shader-nodes/index.js";import{sceneMapUniformName as s}from"../shader-nodes/scene-sample.js";import{depthUniformName as a}from"../shader-nodes/depth.js";import{MATERIAL_FLAG_ALPHA_TEST as l,MATERIAL_FLAG_RECEIVE_DECALS as d}from"../shader-nodes/material-flags.js";import{createMotionVectorOutput as c}from"./motion-vector-node.js";export class ExperimentalWebGpuBackend{constructor(e,t,i,n,o,r,s,a,l,d,c,h,u,p,m,g,f,S,v,w){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=o,this.fxaa=r,this.smaa=s,this.gtao=a,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.antiAliasingState=S,this.directionalShadowState=v,this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,this.canvas=w}static async create(p={}){const m=await import("@hology/webgpu-renderer"),g=document.createElement("canvas");g.dataset.hologyRenderer="webgpu-experimental";const f=new m.WGSLShaderMaterial({vertexShader:h,fragmentShader:u});f.side=m.DoubleSide;const S=m,v=null!=p.motionBlur&&!1!==p.motionBlur,w=!1!==p.gtao&&(null==p.gtao||!1!==p.gtao.temporal),P=!1!==p.volumetricFog&&(null==p.volumetricFog||!1!==p.volumetricFog.temporal),x=null!=(b=p).antiAliasing?b.antiAliasing:null!=b.taa&&!1!==b.taa?"taa":null!=b.smaa&&!1!==b.smaa?"smaa":null!=b.fxaa&&!1!==b.fxaa?"fxaa":!1===b.taa?"off":"taa";var b;const y=null!=p.antiAliasing,F=v||w||P||(y||"taa"===x),C=new t(S,(e,t)=>"opaque"===t?[e.outputColor.xyz.rgba(i(e.alphaTest>0?l:0).add(!1===e.userData.receiveDecals?0:d)),o((e.outputNormal??n.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??i(1)),...F?[c(e)]:[]]:void 0),M=new e.MeshStandardMaterial({color:8688803,roughness:1});if(null==C.resolve(M,"opaque"))throw f.dispose(),M.dispose(),new Error("Failed to compile the WebGPU G-buffer fallback material.");const L=!1===p.gtao?null:new m.GTAOEffect({normalSpace:"view",...m.GTAO_PRESETS.high,...p.gtao??{}}),O=!1===p.ssr||null==p.ssr?null:new m.SSREffect({normalSpace:"view",resolutionScale:.5,...p.ssr??{}}),E=!1===p.bloom?null:new m.BloomEffect({threshold:1,strength:.9,radius:.2,...p.bloom??{}}),G=y||!1!==p.fxaa&&"fxaa"===x?new m.FXAAEffect(!1===p.fxaa?{}:p.fxaa):null,R=y||!1!==p.smaa&&"smaa"===x?new m.SMAAEffect(!1===p.smaa?{}:p.smaa):null,D=y||!1!==p.taa&&"taa"===x?new m.TemporalAAEffect({renderScale:1,...!1===p.taa?{}:p.taa}):null,B={mode:x},A=!1===p.motionBlur||null==p.motionBlur?null:new m.MotionBlurEffect(p.motionBlur),T=p.volumetricFog||void 0,V=!1===p.volumetricFog?null:new m.VolumetricFogEffect(void 0,{...m.VOLUMETRIC_FOG_PRESETS.high,maxDistance:64,spatialJitter:!0,scatteringIntensity:Math.PI,...T,temporal:!1!==T?.temporal&&{...m.VOLUMETRIC_FOG_PRESETS.high.temporal,...T?.temporal},blur:!1!==T?.blur&&{...!1===m.VOLUMETRIC_FOG_PRESETS.high.blur?{}:m.VOLUMETRIC_FOG_PRESETS.high.blur,depthAwareUpsample:!0,...T?.blur}}),W=!1===p.colorGrading?null:new m.ColorGradingEffect({enabled:!1,...p.colorGrading??{}}),k=!1===p.depthOfField?null:new m.DepthOfFieldEffect({enabled:!1,...p.depthOfField??{}}),I=!1===p.outline?null:new m.OutlineEffect({enabled:!1,...p.outline??{}}),N=[],U=new WeakMap,j=new Set,H=[],$=(e,t,i)=>{let n=i;const o=N.filter(e=>e.enabled&&e.stage===t).sort((e,t)=>e.priority-t.priority||e.id-t.id);for(const t of o){if(!(t.material instanceof r)){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=U.get(t.material);null!=i&&i.version===t.material.version||(i={version:t.material.version,shader:C.compileFullscreen(t.material)},U.set(t.material,i));const o=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,shader:i.shader,inputOverrides:{[s]:n},outputs:o}),n=o}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},_={enabled:!0},z=new m.WebGpuRenderer({canvas:g,fallbackMaterial:f,materialResolver:(e,t)=>C.resolve(e,t),invokeObjectRenderCallbacks:!1,hiZOcclusionCulling:!0,renderGraphProfiling:!1,sampleCount:1,multiDrawIndirect:!1});z.setRenderScale("taa"===x?D?.renderScale??1:1),z.setRenderGraphBuilder((e,t)=>{const i=new m.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba16float"}),o=F?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of H)"beforeScene"===e.stage&&e(i,i.sceneColor);_.enabled&&i.addDirectionalShadowPass(),i.addPointShadowPass(),i.addSpotShadowPass(),i.addDepthPrepass(),i.addHiZPasses(),i.addVisibilityPass(),i.addMaterialPass({name:"OpaqueGBufferPass",outputs:null==o?[i.sceneColor,n]:[i.sceneColor,n,o],drawStage:"opaque",loadDepth:!0}),i.addHiZHistoryPass("OpaqueGBufferPass");let r=i.sceneColor;if(L?.enabled){const e=L.addPasses(i,{depth:i.mainDepth,normal:n,velocity:o??void 0});r=L.addCompositePass(i,r,e)}null!=O&&(r=O.addPasses(i,{sceneColor:r,depth:i.mainDepth,normalRoughness:n}));const s=new Set(H.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(r,{sceneColor:s.has("sceneColorSnapshot"),sceneDepth:s.has("sceneDepthSnapshot")||N.some(e=>e.enabled&&null!=e.material.uniforms[a])}),r=$(i,"beforeFog",r),i.addLatePass(r);for(const e of H)"beforeScene"!==e.stage&&e(i,r);null!=V&&(r=V.addPasses(i,{sceneColor:r,depth:i.mainDepth,velocity:o??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=A&&null!=o&&(r=A.addPass(i,r,o,i.mainDepth)),null!=E&&(r=E.addPass(i,r)),r=$(i,"beforeOutline",r),null!=I&&(r=I.addPass(i,r)),r=$(i,"beforeDepthOfField",r),null!=k&&(r=k.addPass(i,r,i.mainDepth)),r=$(i,"beforeColorAdjustment",r),null!=W&&(r=W.addPass(i,r)),r=$(i,"beforeAntiAliasing",r);let l="taa"===B.mode&&null!=D?D.addPass(i,r,i.mainDepth,o??void 0):r;"smaa"===B.mode&&null!=R?l=R.addPass(i,l):"fxaa"===B.mode&&null!=G&&(l=G.addPass(i,l)),l=$(i,"beforeOutput",l),i.present(l)});try{return await z.initialize(),new ExperimentalWebGpuBackend(z,f,C,M,E,G,R,L,O,D,A,V,W,k,I,N,H,B,_,g)}catch(e){throw z.destroy(),f.dispose(),C.dispose(),M.dispose(),L?.dispose(),R?.dispose(),A?.dispose(),V?.dispose(),I?.dispose(),e}}static supportsCamera(t){return t instanceof e.PerspectiveCamera||t instanceof e.OrthographicCamera}setSize(e,t,i,n=1){const o=this.canvas.width,r=this.canvas.height,s=Math.min(1,Math.max(.25,n)),a=s!==this.renderScale;this.renderScale=s,this.renderer.setRenderScale(s),this.taa?.setRenderScale(s),this.renderer.setSize(e,t,i),(a||this.canvas.width!==o||this.canvas.height!==r)&&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)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=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)}setDirectionalShadowOptions(e,t){this.directionalShadowState.enabled=e,this.renderer.setDirectionalShadowsEnabled(e),this.renderer.setDirectionalShadowMapSize(t)}setWorldEnvironment(t){if(null==t)return void this.nodeMaterialResolver.setWorldEnvironment(null);let i=t.source;if(i.mapping!==e.CubeUVReflectionMapping){let e=this.pmremResults.get(i);null==e&&(this.pmremGenerator??(this.pmremGenerator=this.renderer.createPMREMGenerator()),e=this.pmremGenerator.fromEquirectangular(i),this.pmremResults.set(i,e),this.ownedPmremResults.add(e)),i=e.texture}this.nodeMaterialResolver.setWorldEnvironment({texture:i,intensity:t.intensity})}resetViewHistory(){this.renderer.resetViewHistory(),this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset()}async compile(e,t){await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1){this.renderer.setHiZOcclusionCullingEnabled(!0);const n=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:"skip",allowUnsortedLateDraws:i});return 0===n.drawCount?(n.dispose(),null):n}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.motionBlur?.setJitterUv(n?.currentJitterUv.x??0,n?.currentJitterUv.y??0);let o=!1;try{this.renderer.render(e,t,i),o=!0}finally{n?.finishCamera(t),o&&this.motionBlur?.commitCamera()}}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()}inspect(e,t){return inspectWebGpuScene(e,t,this.nodeMaterialResolver)}destroy(){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 o=Array.isArray(t.material)?t.material:[t.material];for(const e of o){if(null==e)continue;e.transparent&&n.transparentMaterials++;const t=!0===e.isWGSLShaderMaterial||!0===e.isLineMaterial,o=!t&&!0===i?.canResolve(e);t||o||(n.materialsReplaced++,e.isShaderMaterial&&n.shaderMaterialsReplaced++)}}),n}export function formatWebGpuSceneCapabilitySummary(e){return`[Hology WebGPU experiment] ${JSON.stringify(e)}`}const h="\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",u="\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 o}from"three-shader-graph";import{NodeShaderMaterial as a}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,o,a,s,l,d,c,h,u,p,m,g,f,v,S,b,x){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=r,this.fxaa=o,this.smaa=a,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.antiAliasingState=v,this.directionalShadowState=S,this.nativeDlss=b,this.kind="webgpu",this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,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({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,x=b?(await import("./native-dlss-upscaler.js")).createNativeDlssUpscaler(m.nativeUpscaling?.mode??"quality"):null,P=null!=x;S.side=f.DoubleSide;const w=f,y=null!=m.motionBlur&&!1!==m.motionBlur,F=!1!==m.gtao&&(null==m.gtao||!1!==m.gtao.temporal),M=!1!==m.volumetricFog&&(null==m.volumetricFog||!1!==m.volumetricFog.temporal),C=P?"off":b?"taa":null!=(D=m).antiAliasing?D.antiAliasing:null!=D.taa&&!1!==D.taa?"taa":null!=D.smaa&&!1!==D.smaa?"smaa":null!=D.fxaa&&!1!==D.fxaa?"fxaa":!1===D.taa?"off":"taa";var D;const E=null!=m.antiAliasing,L=y||F||M||(E||"taa"===C)||P;let O=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)),o((e.outputNormal??r.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??n(1)),...L?[h(e)]:[]]:void 0,e=>O?.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??{}}),W=E||!1!==m.fxaa&&"fxaa"===C?new f.FXAAEffect(!1===m.fxaa?{}:m.fxaa):null,V=E||!1!==m.smaa&&"smaa"===C?new f.SMAAEffect(!1===m.smaa?{}:m.smaa):null,k=P||E||!1!==m.taa&&"taa"===C?new f.TemporalAAEffect({renderScale:1,...!1===m.taa?{}:m.taa}):null,U={mode:C},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=(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 a)){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)},z.set(t.material,i));const r=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,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},Q={enabled:!0},X=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:x?.postSubmit});X.setRenderScale("taa"===C?k?.renderScale??1:1),X.setRenderGraphBuilder((e,t)=>{const i=new f.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba16float"}),r=L?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of K)"beforeScene"===e.stage&&e(i,i.sceneColor);Q.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 o=i.sceneColor;if(T?.enabled){const e=T.addPasses(i,{depth:i.mainDepth,normal:n,velocity:r??void 0});o=T.addCompositePass(i,o,e)}null!=A&&(o=A.addPasses(i,{sceneColor:o,depth:i.mainDepth,normalRoughness:n}));const a=new Set(K.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(o,{sceneColor:a.has("sceneColorSnapshot"),sceneDepth:a.has("sceneDepthSnapshot")||q.some(e=>e.enabled&&null!=e.material.uniforms[l])}),o=Z(i,"beforeFog",o),i.addLatePass(o);for(const e of K)"beforeScene"!==e.stage&&e(i,o);null!=N&&(o=N.addPasses(i,{sceneColor:o,depth:i.mainDepth,velocity:r??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=I&&null!=r&&(o=I.addPass(i,o,r,i.mainDepth)),null!=B&&(o=B.addPass(i,o)),o=Z(i,"beforeOutline",o),null!=_&&(o=_.addPass(i,o)),o=Z(i,"beforeDepthOfField",o),null!=$&&(o=$.addPass(i,o,i.mainDepth)),o=Z(i,"beforeColorAdjustment",o),null!=H&&(o=H.addPass(i,o)),o=Z(i,"beforeAntiAliasing",o);let s="taa"===U.mode&&null!=k?k.addPass(i,o,i.mainDepth,r??void 0):o;"smaa"===U.mode&&null!=V?s=V.addPass(i,s):"fxaa"===U.mode&&null!=W&&(s=W.addPass(i,s)),s=Z(i,"beforeOutput",s),!0===x?.enabled&&null!=r?x.addInputPass(i,s,r):i.present(s)});try{return await X.initialize(g),O=new ExperimentalWebGpuBackend(X,S,G,R,B,W,V,T,A,k,I,N,H,$,_,q,K,U,Q,x,v),O}catch(e){throw X.destroy(),S.dispose(),G.dispose(),R.dispose(),T?.dispose(),V?.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,o=this.canvas.height;let a=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));a=this.nativeDlss.getRenderScale(n,r)}const s=a!==this.renderScale;this.renderScale=a,this.renderer.setRenderScale(a),this.taa?.setRenderScale(a),this.renderer.setSize(e,t,i),(s||this.canvas.width!==r||this.canvas.height!==o)&&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)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=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)}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){await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1){this.renderer.setHiZOcclusionCullingEnabled(!0);const n=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:"skip",allowUnsortedLateDraws:i});return 0===n.drawCount?(n.dispose(),null):n}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 o=!1;try{this.renderer.render(e,t,i),o=!0}finally{null!=r&&this.renderer.clearProjectionJitter(),n?.finishCamera(t),o&&this.motionBlur?.commitCamera(),o&&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
  */
@@ -0,0 +1,22 @@
1
+ export interface WebGpuComputeKernelDescriptor {
2
+ label?: string;
3
+ code: string;
4
+ entryPoint?: string;
5
+ bindGroupLayoutEntries: GPUBindGroupLayoutEntry[];
6
+ }
7
+ export interface WebGpuComputeKernel {
8
+ readonly layout: GPUBindGroupLayout;
9
+ readonly pipeline: GPUComputePipeline;
10
+ createBindGroup(device: GPUDevice, entries: GPUBindGroupEntry[], label?: string): GPUBindGroup;
11
+ }
12
+ interface WebGpuRuntimeBindings {
13
+ createComputeKernel(device: GPUDevice, descriptor: WebGpuComputeKernelDescriptor): WebGpuComputeKernel;
14
+ buildParticleLightingShaderHeader(receiveShadow?: boolean, modelMatrixBody?: string): string;
15
+ }
16
+ export declare function configureWebGpuRuntimeBindings(value: WebGpuRuntimeBindings): void;
17
+ /** Loads renderer-side helpers only after a WebGPU-specific feature is requested. */
18
+ export declare function ensureWebGpuRuntimeBindings(): Promise<void>;
19
+ export declare function createWebGpuComputeKernel(device: GPUDevice, descriptor: WebGpuComputeKernelDescriptor): WebGpuComputeKernel;
20
+ export declare function buildWebGpuParticleLightingShaderHeader(receiveShadow?: boolean, modelMatrixBody?: string): string;
21
+ export {};
22
+ //# sourceMappingURL=webgpu-runtime-bridge.d.ts.map