@hology/core 0.0.272 → 0.0.274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
- package/dist/effects/vfx/gpu-vfx-world-service.js +1 -1
- package/dist/effects/vfx/rates.d.ts +2 -0
- package/dist/effects/vfx/rates.js +1 -1
- package/dist/effects/vfx/vfx-actor.d.ts +2 -1
- package/dist/effects/vfx/vfx-actor.js +1 -1
- package/dist/effects/vfx/vfx-asset.d.ts +10 -1
- package/dist/effects/vfx/vfx-backend-partition.d.ts +8 -0
- package/dist/effects/vfx/vfx-backend-partition.js +4 -0
- package/dist/effects/vfx/vfx-materializer.js +1 -1
- package/dist/effects/vfx/vfx-render-preparation.js +1 -1
- package/dist/effects/vfx/vfx-renderers.d.ts +27 -2
- package/dist/effects/vfx/vfx-renderers.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +2 -0
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +19 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
- package/dist/gameplay/actors/builtin/water-spline-volume-actor.d.ts +10 -0
- package/dist/gameplay/actors/builtin/water-spline-volume-actor.js +1 -1
- package/dist/gameplay/actors/builtin/water-volume-actor.d.ts +3 -1
- package/dist/gameplay/actors/builtin/water-volume-actor.js +1 -1
- package/dist/gameplay/actors/camera/first-person-camera-component.js +1 -1
- package/dist/gameplay/actors/camera/third-person-camera-component.d.ts +7 -0
- package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
- package/dist/gameplay/ai/behavior-tree/move.d.ts +5 -0
- package/dist/gameplay/ai/behavior-tree/move.js +1 -1
- package/dist/gameplay/ai/behavior-tree/move.test.d.ts +2 -0
- package/dist/gameplay/ai/behavior-tree/move.test.js +4 -0
- package/dist/gameplay/animation/root-motion.js +1 -1
- package/dist/gameplay/input/input-service.d.ts +9 -1
- package/dist/gameplay/input/input-service.js +1 -1
- package/dist/gameplay/services/physics/physics-system.d.ts +2 -0
- package/dist/gameplay/services/physics/physics-system.js +1 -1
- package/dist/gameplay/services/render.d.ts +4 -1
- package/dist/gameplay/services/render.js +1 -1
- package/dist/gameplay/services/world.d.ts +5 -0
- package/dist/rendering/node-material-webgpu-resolver.js +1 -1
- package/dist/rendering/webgpu-experimental-backend.d.ts +4 -2
- package/dist/rendering/webgpu-experimental-backend.js +1 -1
- package/dist/rendering.d.ts +17 -2
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +4 -0
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/collision/collision-shape-import.js +1 -1
- package/dist/scene/collision/rapier-shape.js +1 -1
- package/dist/scene/landscape/landscape-geometry.d.ts +24 -0
- package/dist/scene/landscape/landscape-geometry.js +4 -0
- package/dist/scene/landscape/landscape-manager.d.ts +1 -0
- package/dist/scene/landscape/landscape-manager.js +1 -1
- package/dist/scene/materializer.d.ts +7 -1
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/scene-data-service.d.ts +2 -1
- package/dist/scene/scene-data-service.js +1 -1
- package/dist/scene/sky.d.ts +2 -0
- package/dist/scene/sky.js +1 -1
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/graph/registry.js +1 -1
- package/dist/shader/parameter.js +1 -1
- package/dist/shader/sprite-shader.js +1 -1
- package/dist/shader-nodes/depth.d.ts +6 -4
- package/dist/shader-nodes/depth.js +1 -1
- package/dist/shader-nodes/index.d.ts +2 -1
- package/dist/shader-nodes/index.js +1 -1
- package/dist/shader-nodes/surface-reflection.d.ts +9 -0
- package/dist/shader-nodes/surface-reflection.js +4 -0
- package/dist/shader-nodes/water-volume.d.ts +6 -2
- package/dist/shader-nodes/water-volume.js +1 -1
- package/dist/test/asset-resource-loader-texture-array.test.js +1 -1
- package/dist/test/character-movement-solve.test.js +1 -1
- package/dist/test/collision-shape-import.test.js +1 -1
- package/dist/test/first-person-camera-component.test.js +1 -1
- package/dist/test/frame-stats.test.js +1 -1
- package/dist/test/gpu-sprite-compiler.test.js +1 -1
- package/dist/test/input.test.js +1 -1
- package/dist/test/landscape-geometry.test.d.ts +2 -0
- package/dist/test/landscape-geometry.test.js +4 -0
- package/dist/test/material-assignment.test.js +1 -1
- package/dist/test/materializer-dynamic-transform.test.js +1 -1
- package/dist/test/materializer-prefetch.test.js +1 -1
- package/dist/test/net-character-movement.test.js +1 -1
- package/dist/test/node-material-webgpu-resolver.test.js +1 -1
- package/dist/test/parameter-definition.test.js +1 -1
- package/dist/test/physics-hitstop.test.d.ts +2 -0
- package/dist/test/physics-hitstop.test.js +4 -0
- package/dist/test/physics-ray-object.test.js +1 -1
- package/dist/test/post-process-effect.test.js +1 -1
- package/dist/test/rapier-trimesh.test.d.ts +2 -0
- package/dist/test/rapier-trimesh.test.js +4 -0
- package/dist/test/sequence-animation-retiming.test.js +1 -1
- package/dist/test/sequence-vfx.test.js +1 -1
- package/dist/test/surface-reflection.test.d.ts +2 -0
- package/dist/test/surface-reflection.test.js +4 -0
- package/dist/test/vfx-backend-partition.test.d.ts +2 -0
- package/dist/test/vfx-backend-partition.test.js +4 -0
- package/dist/test/vfx-playback-transform.test.js +1 -1
- package/dist/test/vfx-render-preparation.test.js +1 -1
- package/dist/test/water-spline-volume-actor.test.js +1 -1
- package/dist/utils/mesh.d.ts +1 -1
- package/dist/utils/mesh.js +1 -1
- package/dist/utils/three/frame-stats.d.ts +8 -0
- package/dist/utils/three/frame-stats.js +1 -1
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"three";import{compileNodeWebGpuFullscreen as a,compileNodeShaderMaterialForWebGpu as t,NodeShaderMaterial as n,webGpuRendererBindings as i,webGpuTiledRendererBindings as s,textureSampler2d as o,float as r,length as l,max as u,rgba as p,isWgslCompiler as m,isWgslFragmentCompiler as c,sqrt as f,normalize as h,transformed as d,uniformFloat as M,uniforms as v,vec4 as y,Vec3Node as g,toonMaterial as V}from"three-shader-graph";import{StandardShader as w}from"../shader/builtin/standard-shader.js";import{LambertShader as I}from"../shader/builtin/lambert-shader.js";import{ToonShader as S}from"../shader/builtin/toon-shader.js";import{UnlitShader as x}from"../shader/builtin/unlit-shader.js";import{SpriteShader as T}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as E}from"../shader-nodes/time.js";import{depthUniformName as C,farUniformName as b,nearUniformName as U,resolutionUniformName as A,sceneNormalUniformName as N}from"../shader-nodes/depth.js";import{sceneMapUniformName as W,transmissionMapUniformName as k}from"../shader-nodes/scene-sample.js";const R={...i,uniformExpressions:{...i.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[E]:{type:"float",expression:"rendererElapsedTime()"},[U]:{type:"float",expression:"rendererCameraNear()"},[b]:{type:"float",expression:"rendererCameraFar()"},[A]:{type:"vec2",expression:"rendererViewportSize()"}},graphTextures:{[k]:{resource:"physicalTransmissionSnapshot",dimension:"2d",sampleType:"float",sampler:"filtering",requiresLatePass:!0}},sceneTextures:{[W]:{semantic:"sceneColor",sampleType:"float"},[C]:{semantic:"sceneDepth",sampleType:"depth"}},attributes:{material:{shaderLocation:6,format:"float32x4",defaultValue:[0,0,0,0]},material2:{shaderLocation:7,format:"float32x4",defaultValue:[0,0,0,0]},hole:{shaderLocation:8,format:"float32",defaultValue:[0]},offset:{shaderLocation:9,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},velocity:{shaderLocation:10,format:"float32x4",stepMode:"instance",defaultValue:[0,0,0,0]},size:{shaderLocation:11,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},rotation:{shaderLocation:12,format:"float32",stepMode:"instance",defaultValue:[0]},particleData:{shaderLocation:13,format:"float32x3",stepMode:"instance",defaultValue:[1,1,0]},particleColor:{shaderLocation:14,format:"float32x4",stepMode:"instance",defaultValue:[1,1,1,1]}}};class L extends g{constructor(e){super(),this.fallback=e}compile(e){if(!m(e))return{out:e.get(this.fallback)};if(c(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const a=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${a} = input.position;\n#endif`,out:a}}}class D extends g{constructor(e){super(),this.fallback=e}compile(e){if(!m(e))return{out:e.get(this.fallback)};if(c(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const a=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${a} = input.normal;\n#endif`,out:a}}}export function setMaterialUniformValuesAutoUpdate(e,a){e.uniformValuesAutoUpdate=a}export function markMaterialUniformValuesNeedUpdate(e){const a=e;"uniformValuesNeedsUpdate"in a?a.uniformValuesNeedsUpdate=!0:a.uniformValuesAutoVersion=(a.uniformValuesAutoVersion??0)+1}function F(e){return!1!==e.uniformValuesAutoUpdate}function O(e){return e.uniformValuesAutoVersion??0}export function withThreeDefaultVertexAttributeValues(e){return e.map(e=>"uv1"===e.name&&null==e.defaultValue?{...e,defaultValue:[0,0]}:e)}const P=new WeakMap,j=new WeakMap;export function createNodeMaterialSignature(e){const a=j.get(e);if(null!=a)return a;const t=JSON.stringify({version:e.version,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,alphaTest:e.alphaTest,alphaToCoverage:e.alphaToCoverage,blending:e.blending,colorWrite:e.colorWrite,depthFunc:e.depthFunc,depthTest:e.depthTest,depthWrite:e.depthWrite,polygonOffset:e.polygonOffset,polygonOffsetFactor:e.polygonOffsetFactor,polygonOffsetUnits:e.polygonOffsetUnits,premultipliedAlpha:e.premultipliedAlpha,side:e.side,stencilWrite:e.stencilWrite,transparent:e.transparent,wireframe:e.wireframe});return j.set(e,t),t}export class NodeMaterialWebGpuResolver{constructor(e,a,t){this.webGpu=e,this.mrtResolver=a,this.environmentTextureResolver=t,this.cache=new WeakMap,this.failedSignatures=new WeakMap,this.mappedMaterialsCache=new WeakMap,this.mappedMaterialsSignatures=new WeakMap,this.observedNodeMaterials=new Map,this.outlineMaterials=new WeakMap,this.outlineUniformVersions=new WeakMap,this.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const a=e?.texture??null,t=e?.intensity??0;if(this.worldEnvironmentTexture!==a||this.worldEnvironmentIntensity!==t){if(this.worldEnvironmentTexture!==a)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=t,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=a,this.worldEnvironmentIntensity=t}}resolve(e,a=void 0){let i,o=!1;if(e instanceof n)i=e,this.observeNodeMaterial(i);else{const a=this.getOrCreateMappedNodeMaterial(e);if(null==a)return;i=a,o=!0}if("outline"===a){if(null==i.outputAlbedo)return;o&&J(e,i),i.userData.outlineParameters=e.userData?.outlineParameters,i=this.getOrCreateOutlineMaterial(i),o=!1}i.visible=e.visible,o&&(i.userData.receiveDecals=e.userData.receiveDecals);const r=a??"default",l=this.cache.get(i),u=l?.get(r);if(o&&null!=u&&u.sourceVersion===e.version&&u.worldEnvironmentRevision===this.worldEnvironmentRevision){const a=F(e),t=O(e);return u.material.uniformValuesAutoUpdate=a,this.syncInheritedWorldEnvironmentSource(i,u),a||u.sourceUniformValuesAutoVersion!==t?(J(e,i),u.compiled.syncLiveUniforms(u.material.uniforms),z(i,u.material.uniforms),B(i,u.material),u.sourceUniformValuesAutoVersion=t,a||(u.material.uniformValuesNeedsUpdate=!0),u.material):u.material}if(!o&&null!=u&&u.sourceVersion===e.version&&u.worldEnvironmentRevision===this.worldEnvironmentRevision&&_(i,u.compiled))return this.syncInheritedWorldEnvironmentSource(i,u),$(i,u),u.material;o&&J(e,i);const p=this.prepareWorldEnvironment(i),m=this.getNodeMaterialSignature(i,p);if(u?.signature===m&&_(i,u.compiled))return o?(u.material.uniformValuesAutoUpdate=F(e),u.compiled.syncLiveUniforms(u.material.uniforms),z(i,u.material.uniforms),B(i,u.material),u.sourceUniformValuesAutoVersion=O(e),u.material.uniformValuesAutoUpdate||(u.material.uniformValuesNeedsUpdate=!0)):$(i,u,!0),u.sourceVersion=e.version,u.worldEnvironmentRevision=this.worldEnvironmentRevision,u.material;try{const n=this.mrtResolver?.(i,a),c=t(i,"opaque"===a?{...R,arrays:s.arrays}:R,n),f=new this.webGpu.WGSLShaderMaterial({vertexShader:c.vertexShader,fragmentShader:c.fragmentShader,depthVertexShader:c.depthVertexShader,depthFragmentShader:c.depthFragmentShader,pointShadowVertexShader:c.pointShadowVertexShader,pointShadowFragmentShader:c.pointShadowFragmentShader,uniforms:c.uniforms,textures:c.textures,sceneTextures:c.sceneTextures,graphTextures:c.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(c.vertexAttributes),uniformValuesAutoUpdate:o?F(e):i.uniformValuesAutoUpdate,transparent:c.renderState?.transparent,alphaTest:c.renderState?.alphaTest,depthTest:c.renderState?.depthTest,depthWrite:c.renderState?.depthWrite,side:c.renderState?.side,wireframe:i.wireframe});f.name=e.name||i.name||e.uuid,f.userData.pipelineOrigin={assetId:e.userData.assetId??i.userData.assetId,assetName:e.userData.assetName??i.userData.assetName,sourceUuid:e.uuid,sourceName:e.name,sourceType:e.type,sourceVersion:e.version},f.uniformValuesAutoUpdate=o?F(e):i.uniformValuesAutoUpdate,function(e,a){if(null==e)return;Object.assign(a,e)}(c.renderState,f),null!=u&&(u.material.dispose(),this.cacheValues.delete(u));const h={signature:m,compiled:c,material:f,inheritsWorldEnvironment:p,sourceVersion:e.version,sourceUniformValuesAutoVersion:o?O(e):i.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},d=l??new Map;return d.set(r,h),this.cache.set(i,d),this.cacheValues.add(h),z(i,f.uniforms),B(i,f),f}catch(e){let a=this.failedSignatures.get(i);if(null==a&&(a=new Map,this.failedSignatures.set(i,a)),a.get(r)!==m){a.set(r,m);const t=e instanceof Error?e.message:String(e),n=i.name||i.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${n}": ${t}`,{material:i,error:e})}return}}getOrCreateOutlineMaterial(a){let t=this.outlineMaterials.get(a);if(null==t){const i=a.nodeMaterialDefinition,s=a.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const o=M("outlineThickness",.003),m=M("outlineDarkening",.65),c=M("outlineAlpha",1),g=new L(d.position.xyz),w=new D(d.normal),I=i.transform?.multiplyVec(y(g,1))??y(g,1),S=v.modelViewMatrix.multiplyVec(I),x=h(v.normalMatrix.multiplyVec(w)),T=f(u(l(S.xyz),r(1e-4))).multiply(.5),E=S.xyz.add(x.multiplyScalar(o.multiply(T))),C=v.projectionMatrix.multiplyVec(S),b=v.projectionMatrix.multiplyVec(y(E,1)),U=(i.position??C).add(b.subtract(C)),A=p(V({color:s.rgb.multiplyScalar(r(1).subtract(m))}),a.outputOpacity.multiply(c));t=new n({color:A,position:U,opacity:a.outputOpacity,discard:i.discard,alphaTest:a.alphaTest,transparent:!0,fog:!1,outputEncoding:i.outputEncoding,uniforms:i.uniforms,uniformNodes:i.uniformNodes}),t.side=e.BackSide,t.depthTest=!0,t.depthWrite=!0,this.outlineMaterials.set(a,t),this.outlineUniformVersions.delete(a)}const i=a.userData?.outlineParameters,s=i?.thickness??.003,o=e.MathUtils.clamp(i?.darkening??.65,0,1),m=e.MathUtils.clamp(i?.alpha??a.opacity,0,1),c=t.uniforms.outlineThickness.value!==s||t.uniforms.outlineDarkening.value!==o||t.uniforms.outlineAlpha.value!==m;t.uniforms.outlineThickness.value=s,t.uniforms.outlineDarkening.value=o,t.uniforms.outlineAlpha.value=m,t.userData.outlineSource=a,t.uniformValuesAutoUpdate=a.uniformValuesAutoUpdate;let g=this.outlineUniformVersions.get(a);const w=a.uniformValuesAutoUpdate||null==g||g.version!==a.uniformValuesAutoVersion||g.uniforms!==a.uniforms;if(w){for(const e in a.uniforms)null!=t.uniforms[e]&&(t.uniforms[e].value=a.uniforms[e].value);g?(g.version=a.uniformValuesAutoVersion,g.uniforms=a.uniforms):(g={version:a.uniformValuesAutoVersion,uniforms:a.uniforms},this.outlineUniformVersions.set(a,g))}return a.uniformValuesAutoUpdate||!c&&!w||(t.uniformValuesNeedsUpdate=!0),t}compileFullscreen(e){const t=a({color:e.outputColor,wgslBindings:{...R,uniformExpressions:{},graphTextures:{...R.graphTextures,[N]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),n=t.syncLiveUniforms;return{...t,syncLiveUniforms(a){n(a),z(e,a)}}}getOrCreateMappedNodeMaterial(a){const t=function(a){const t=[a.vertexColors,a.transparent,a.alphaTest,a.side,a.depthTest,a.depthWrite,a.wireframe??!1];if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){if(t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.roughnessMap?a.roughnessMap.uuid:null,a.metalnessMap?a.metalnessMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null),a instanceof e.MeshPhysicalMaterial){t.push(a.clearcoat>0,a.iridescence>0,a.transmission>0,a.sheen>0,a.anisotropy>0,1.5!==a.ior,1!==a.specularIntensity,1!==a.specularColor.r||1!==a.specularColor.g||1!==a.specularColor.b);for(const e of H)t.push(a[e]?.uuid??null)}}else a instanceof e.MeshLambertMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.MeshToonMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.gradientMap?a.gradientMap.uuid:null):a instanceof e.MeshBasicMaterial?t.push(a.map?a.map.uuid:null,a.aoMap?a.aoMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.MeshPhongMaterial?t.push(a.map?a.map.uuid:null,a.normalMap?a.normalMap.uuid:null,a.aoMap?a.aoMap.uuid:null,a.emissiveMap?a.emissiveMap.uuid:null,a.lightMap?a.lightMap.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.envMap?a.envMap.uuid:null):a instanceof e.SpriteMaterial&&t.push(a.map?a.map.uuid:null,a.alphaMap?a.alphaMap.uuid:null,a.sizeAttenuation);return t.join(",")}(a),n=this.mappedMaterialsCache.get(a),i=this.mappedMaterialsSignatures.get(a);if(null!=n&&i===t)return n;if(null!=n){n.dispose();const e=this.cache.get(n);if(null!=e){for(const a of e.values())a.material.dispose(),this.cacheValues.delete(a);this.cache.delete(n)}}const s=function(a){if(a instanceof e.SpriteMaterial){const e=new T;e.color=a.color,e.opacity=a.opacity,e.rotation=a.rotation,e.screenSpaceSize=a.sizeAttenuation?0:1,e.alphaTest=a.alphaTest,a.map&&(e.map=a.map),a.alphaMap&&(e.alphaMap=a.alphaMap);const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t}if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){const t=new w;if(t.color=a.color,t.opacity=a.opacity,t.roughness=a.roughness,t.metalness=a.metalness,t.vertexColor=a.vertexColors,a.map&&(t.map=o(a.map)),a.normalMap&&(t.normalMap=o(a.normalMap),t.normalScale=a.normalScale),a.roughnessMap&&(t.roughnessMap=o(a.roughnessMap)),a.metalnessMap&&(t.metalnessMap=o(a.metalnessMap)),a.aoMap&&(t.aoMap=o(a.aoMap),t.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(t.emissiveMap=o(a.emissiveMap)),a.lightMap&&(t.lightMap=o(a.lightMap),t.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(t.alphaMap=o(a.alphaMap)),t.emissive=a.emissive,t.emissiveIntensity=a.emissiveIntensity,t.envMap=a.envMap,t.envMapIntensity=a.envMapIntensity,t.alphaTest=a.alphaTest,a instanceof e.MeshPhysicalMaterial){for(const e of K)t[e]=a[e];for(const e of q)t[e]=a[e];for(const e of H)a[e]&&(t[e]=o(a[e]));t.clearcoatNormalScale=a.clearcoatNormalScale,t.iridescenceThicknessRange=new e.Vector2(...a.iridescenceThicknessRange),t.anisotropyRotation=a.anisotropyRotation}const n=t.build();return n.transparent=a.transparent,n.side=a.side,n.depthTest=a.depthTest,n.depthWrite=a.depthWrite,n.wireframe=a.wireframe,n}if(a instanceof e.MeshLambertMaterial){const e=new I;e.color=a.color,e.opacity=a.opacity,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.envMap=a.envMap,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}if(a instanceof e.MeshToonMaterial){const e=new S;e.color=a.color,e.opacity=a.opacity,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}if(a instanceof e.MeshBasicMaterial||a instanceof e.LineBasicMaterial){const t=new x;t.color=a.color,t.opacity=a.opacity,t.vertexColor=a.vertexColors,a instanceof e.MeshBasicMaterial&&(a.map&&(t.map=o(a.map)),a.aoMap&&(t.aoMap=o(a.aoMap),t.aoMapIntensity=a.aoMapIntensity),a.lightMap&&(t.lightMap=o(a.lightMap),t.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(t.alphaMap=o(a.alphaMap)),t.envMap=a.envMap),t.alphaTest=a.alphaTest;const n=t.build();return n.transparent=a.transparent,n.side=a.side,n.depthTest=a.depthTest,n.depthWrite=a.depthWrite,n.wireframe=a instanceof e.MeshBasicMaterial&&a.wireframe,n}if(a instanceof e.MeshPhongMaterial){const e=new w;e.color=a.color,e.opacity=a.opacity,e.roughness=Math.max(0,1-a.shininess/100),e.metalness=0,e.vertexColor=a.vertexColors,a.map&&(e.map=o(a.map)),a.normalMap&&(e.normalMap=o(a.normalMap),e.normalScale=a.normalScale),a.aoMap&&(e.aoMap=o(a.aoMap),e.aoMapIntensity=a.aoMapIntensity),a.emissiveMap&&(e.emissiveMap=o(a.emissiveMap)),a.lightMap&&(e.lightMap=o(a.lightMap),e.lightMapIntensity=a.lightMapIntensity),a.alphaMap&&(e.alphaMap=o(a.alphaMap)),e.emissive=a.emissive,e.emissiveIntensity=a.emissiveIntensity,e.envMap=a.envMap,e.alphaTest=a.alphaTest;const t=e.build();return t.transparent=a.transparent,t.side=a.side,t.depthTest=a.depthTest,t.depthWrite=a.depthWrite,t.wireframe=a.wireframe,t}return null}(a);return null==s?null:(s.wireframe=a.wireframe??!1,this.mappedMaterialsCache.set(a,s),this.mappedMaterialsSignatures.set(a,t),a.addEventListener("dispose",()=>{const e=this.mappedMaterialsCache.get(a);if(null!=e){e.dispose(),this.mappedMaterialsCache.delete(a),this.mappedMaterialsSignatures.delete(a);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}}}),s)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,a]of this.observedNodeMaterials)e.removeEventListener("dispose",a);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,a){a.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,a){const t=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return a?`${t}|worldEnvironment:${this.worldEnvironmentRevision}`:t}prepareWorldEnvironment(a){var t,n,i,s,o,r;if(null!=a.envMap){const s=this.environmentTextureResolver?.(a.envMap)??a.envMap;return(t=a.uniforms).envMap??(t.envMap={value:s}),a.uniforms.envMap.value=s,(n=a.uniforms).envMapIntensity??(n.envMapIntensity={value:1}),(i=a.uniforms).envMapRotation??(i.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.delete(a),!1}return null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(a)&&(delete a.uniforms.envMap,delete a.uniforms.envMapIntensity,delete a.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(a)),!1):((s=a.uniforms).envMap??(s.envMap={value:this.worldEnvironment.texture}),a.uniforms.envMap.value=this.worldEnvironment.texture,(o=a.uniforms).envMapIntensity??(o.envMapIntensity={value:this.worldEnvironment.intensity}),a.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(r=a.uniforms).envMapRotation??(r.envMapRotation={value:new e.Matrix3}),this.worldEnvironmentMaterials.add(a),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const a=()=>{e.removeEventListener("dispose",a),this.observedNodeMaterials.delete(e);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const n=this.outlineMaterials.get(e);if(null!=n){const a=this.cache.get(n);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(n)}this.failedSignatures.delete(n),j.delete(n),n.dispose(),this.outlineMaterials.delete(e),this.outlineUniformVersions.delete(e)}this.failedSignatures.delete(e),j.delete(e)};this.observedNodeMaterials.set(e,a),e.addEventListener("dispose",a)}}function $(e,a,t=!1){const n=a.material;n.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(t||e.uniformValuesAutoUpdate||a.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(a.compiled.syncLiveUniforms(n.uniforms),z(e,n.uniforms),B(e,n),a.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,n.uniformValuesAutoUpdate||(n.uniformValuesNeedsUpdate=!0))}function z(e,a){let t=P.get(a);if(null==t){t=[];for(const e in a){const n=a[e],i=n.value,s=!0===i?.isVector2?2:!0===i?.isVector3?3:!0===i?.isVector4?4:!0===i?.isColor?5:0;t.push({name:e,target:n,copyKind:s})}P.set(a,t)}const n=e.uniforms;for(let e=0;e<t.length;e++){const a=t[e],i=n[a.name];if(null==i)continue;const s=i.value,o=a.target.value;if(s!==o){if(0!==a.copyKind){const e=s,t=o;if((2===a.copyKind?!0===e?.isVector2:3===a.copyKind?!0===e?.isVector3:4===a.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof t?.copy){t.copy(s);continue}}a.target.value=s}}}function B(a,t){const n=a.uniforms.envMapIntensity,i=t.uniforms.envMapIntensity;null!=n&&null!=i&&(i.value=n.value);const s=a.uniforms.envMapRotation?.value,o=t.uniforms.envMapRotation?.value;s instanceof e.Matrix3&&o instanceof e.Matrix3&&o.copy(s)}function _(e,a){for(const t in a.textures){const n=a.textures[t],i=e.uniforms[t]?.value;if(G(i)&&i!==n)return!1}return!0}function G(e){return!0===e?.isTexture}const K=["ior","specularIntensity","clearcoat","clearcoatRoughness","iridescence","iridescenceIOR","transmission","thickness","attenuationDistance","dispersion","sheen","sheenRoughness","anisotropy"],q=["specularColor","attenuationColor","sheenColor"],H=["specularIntensityMap","specularColorMap","clearcoatMap","clearcoatRoughnessMap","clearcoatNormalMap","iridescenceMap","iridescenceThicknessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","anisotropyMap"];function J(a,t){if(a instanceof e.SpriteMaterial){const n=t;t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),n.rotation=a.rotation,n.screenSpaceSize=a.sizeAttenuation?0:1}else if(a instanceof e.MeshStandardMaterial||a instanceof e.MeshPhysicalMaterial){if(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=a.roughness),t.uniforms.metalness&&(t.uniforms.metalness.value=a.metalness),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity),t.uniforms.envMapIntensity&&(t.uniforms.envMapIntensity.value=a.envMapIntensity),a instanceof e.MeshPhysicalMaterial){for(const e of K)t.uniforms[e]&&(t.uniforms[e].value=a[e]);for(const n of q){const i=t.uniforms[n]?.value;i instanceof e.Vector3&&i.setFromColor(a[n])}const n=t.uniforms.clearcoatNormalScale?.value;n instanceof e.Vector2&&n.copy(a.clearcoatNormalScale),t.uniforms.iridescenceThicknessMin&&(t.uniforms.iridescenceThicknessMin.value=a.iridescenceThicknessRange[0]),t.uniforms.iridescenceThicknessMax&&(t.uniforms.iridescenceThicknessMax.value=a.iridescenceThicknessRange[1]);const i=t.uniforms.anisotropyDirection?.value;i instanceof e.Vector2&&i.set(Math.cos(a.anisotropyRotation),Math.sin(a.anisotropyRotation))}}else a instanceof e.MeshLambertMaterial||a instanceof e.MeshToonMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity)):a instanceof e.MeshBasicMaterial||a instanceof e.LineBasicMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),a instanceof e.MeshBasicMaterial&&(t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity))):a instanceof e.MeshPhongMaterial&&(t.uniforms.color&&(t.uniforms.color.value instanceof e.Vector3?t.uniforms.color.value.setFromColor(a.color):t.uniforms.color.value instanceof e.Color&&t.uniforms.color.value.copy(a.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=a.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=Math.max(0,1-a.shininess/100)),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof e.Vector3?t.uniforms.emissive.value.setFromColor(a.emissive):t.uniforms.emissive.value instanceof e.Color&&t.uniforms.emissive.value.copy(a.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=a.emissiveIntensity),t.uniforms.normalScale&&a.normalScale&&(t.uniforms.normalScale.value=a.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=a.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=a.lightMapIntensity))}/*
|
|
1
|
+
import{skyPosition as e}from"../scene/sky.js";import*as a from"three";import{compileNodeWebGpuFullscreen as t,compileNodeShaderMaterialForWebGpu as n,NodeShaderMaterial as i,deriveNodeShaderMaterial as s,webGpuRendererBindings as o,webGpuTiledRendererBindings as r,textureSampler2d as l,float as u,length as p,max as m,rgba as c,isWgslCompiler as f,isWgslFragmentCompiler as h,sqrt as d,normalize as M,transformed as v,uniformFloat as y,uniforms as g,vec4 as V,Vec3Node as w,toonMaterial as I}from"three-shader-graph";import{StandardShader as S}from"../shader/builtin/standard-shader.js";import{LambertShader as x}from"../shader/builtin/lambert-shader.js";import{ToonShader as T}from"../shader/builtin/toon-shader.js";import{UnlitShader as E}from"../shader/builtin/unlit-shader.js";import{SpriteShader as C}from"../shader/sprite-shader.js";import{elapsedTimeUniformName as b}from"../shader-nodes/time.js";import{depthUniformName as U,farUniformName as A,nearUniformName as N,resolutionUniformName as k,sceneNormalUniformName as W}from"../shader-nodes/depth.js";import{sceneMapUniformName as R,transmissionMapUniformName as L}from"../shader-nodes/scene-sample.js";const D={...o,uniformExpressions:{...o.uniformExpressions,ambientLightColor:{type:"vec3",expression:"rendererAmbientLight()"},[b]:{type:"float",expression:"rendererElapsedTime()"},[N]:{type:"float",expression:"rendererCameraNear()"},[A]:{type:"float",expression:"rendererCameraFar()"},[k]:{type:"vec2",expression:"rendererViewportSize()"}},graphTextures:{[L]:{resource:"physicalTransmissionSnapshot",dimension:"2d",sampleType:"float",sampler:"filtering",requiresLatePass:!0}},sceneTextures:{[R]:{semantic:"sceneColor",sampleType:"float"},[U]:{semantic:"sceneDepth",sampleType:"depth"}},attributes:{material:{shaderLocation:6,format:"float32x4",defaultValue:[0,0,0,0]},material2:{shaderLocation:7,format:"float32x4",defaultValue:[0,0,0,0]},hole:{shaderLocation:8,format:"float32",defaultValue:[0]},offset:{shaderLocation:9,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},velocity:{shaderLocation:10,format:"float32x4",stepMode:"instance",defaultValue:[0,0,0,0]},size:{shaderLocation:11,format:"float32x3",stepMode:"instance",defaultValue:[0,0,0]},rotation:{shaderLocation:12,format:"float32",stepMode:"instance",defaultValue:[0]},particleData:{shaderLocation:13,format:"float32x3",stepMode:"instance",defaultValue:[1,1,0]},particleColor:{shaderLocation:14,format:"float32x4",stepMode:"instance",defaultValue:[1,1,1,1]}}};class F extends w{constructor(e){super(),this.fallback=e}compile(e){if(!f(e))return{out:e.get(this.fallback)};if(h(e))throw new Error("OutlineLocalPositionNode can only be used in the vertex stage");const a=`outline_local_position_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight).xyz;\n#else\n let ${a} = input.position;\n#endif`,out:a}}}class O extends w{constructor(e){super(),this.fallback=e}compile(e){if(!f(e))return{out:e.get(this.fallback)};if(h(e))throw new Error("OutlineLocalNormalNode can only be used in the vertex stage");const a=`outline_local_normal_${e.variable()}`;return{chunk:`\n#ifdef USE_SKINNING\n let ${a} = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let ${a} = input.normal;\n#endif`,out:a}}}export function setMaterialUniformValuesAutoUpdate(e,a){e.uniformValuesAutoUpdate=a}export function markMaterialUniformValuesNeedUpdate(e){const a=e;"uniformValuesNeedsUpdate"in a?a.uniformValuesNeedsUpdate=!0:a.uniformValuesAutoVersion=(a.uniformValuesAutoVersion??0)+1}function P(e){return!1!==e.uniformValuesAutoUpdate}function j(e){return e.uniformValuesAutoVersion??0}export function withThreeDefaultVertexAttributeValues(e){return e.map(e=>"uv1"===e.name&&null==e.defaultValue?{...e,defaultValue:[0,0]}:e)}const $=new WeakMap,z=new WeakMap;export function createNodeMaterialSignature(e){const a=z.get(e);if(null!=a)return a;const t=JSON.stringify({version:e.version,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,alphaTest:e.alphaTest,alphaToCoverage:e.alphaToCoverage,blending:e.blending,colorWrite:e.colorWrite,depthFunc:e.depthFunc,depthTest:e.depthTest,depthWrite:e.depthWrite,polygonOffset:e.polygonOffset,polygonOffsetFactor:e.polygonOffsetFactor,polygonOffsetUnits:e.polygonOffsetUnits,premultipliedAlpha:e.premultipliedAlpha,side:e.side,stencilWrite:e.stencilWrite,transparent:e.transparent,wireframe:e.wireframe});return z.set(e,t),t}export class NodeMaterialWebGpuResolver{constructor(e,a,t){this.webGpu=e,this.mrtResolver=a,this.environmentTextureResolver=t,this.cache=new WeakMap,this.failedSignatures=new WeakMap,this.mappedMaterialsCache=new WeakMap,this.mappedMaterialsSignatures=new WeakMap,this.observedNodeMaterials=new Map,this.outlineMaterials=new WeakMap,this.outlineUniformVersions=new WeakMap,this.worldEnvironmentMaterials=new WeakSet,this.worldEnvironment=null,this.worldEnvironmentTexture=null,this.worldEnvironmentIntensity=0,this.worldEnvironmentRevision=0,this.cacheValues=new Set}setWorldEnvironment(e){const a=e?.texture??null,t=e?.intensity??0;if(this.worldEnvironmentTexture!==a||this.worldEnvironmentIntensity!==t){if(this.worldEnvironmentTexture!==a)this.worldEnvironmentRevision++;else if(null!=e)for(const e of this.cacheValues)e.inheritsWorldEnvironment&&null!=e.material.uniforms.envMapIntensity&&(e.material.uniforms.envMapIntensity.value=t,e.material.uniformValuesNeedsUpdate=!0);this.worldEnvironment=e,this.worldEnvironmentTexture=a,this.worldEnvironmentIntensity=t}}resolve(a,t=void 0){let o,l=!1;if(a instanceof i)o=a,this.observeNodeMaterial(o);else{const e=this.getOrCreateMappedNodeMaterial(a);if(null==e)return;o=e,l=!0}if("outline"===t){if(null==o.outputAlbedo)return;l&&X(a,o),o.userData.outlineParameters=a.userData?.outlineParameters,o=this.getOrCreateOutlineMaterial(o),l=!1}o.visible=a.visible,l&&(o.userData.receiveDecals=a.userData.receiveDecals);const u=t??"default",p=this.cache.get(o),m=p?.get(u);if(l&&null!=m&&m.sourceVersion===a.version&&m.worldEnvironmentRevision===this.worldEnvironmentRevision){const e=P(a),t=j(a);return m.material.uniformValuesAutoUpdate=e,this.syncInheritedWorldEnvironmentSource(o,m),e||m.sourceUniformValuesAutoVersion!==t?(X(a,o),m.compiled.syncLiveUniforms(m.material.uniforms),_(o,m.material.uniforms),G(o,m.material),m.sourceUniformValuesAutoVersion=t,e||(m.material.uniformValuesNeedsUpdate=!0),m.material):m.material}if(!l&&null!=m&&m.sourceVersion===a.version&&m.worldEnvironmentRevision===this.worldEnvironmentRevision&&K(o,m.compiled))return this.syncInheritedWorldEnvironmentSource(o,m),B(o,m),m.material;l&&X(a,o);const c=this.prepareWorldEnvironment(o),f=this.getNodeMaterialSignature(o,c);if(m?.signature===f&&K(o,m.compiled))return l?(m.material.uniformValuesAutoUpdate=P(a),m.compiled.syncLiveUniforms(m.material.uniforms),_(o,m.material.uniforms),G(o,m.material),m.sourceUniformValuesAutoVersion=j(a),m.material.uniformValuesAutoUpdate||(m.material.uniformValuesNeedsUpdate=!0)):B(o,m,!0),m.sourceVersion=a.version,m.worldEnvironmentRevision=this.worldEnvironmentRevision,m.material;try{const i=this.mrtResolver?.(o,t),h=!0===a.userData.isSky?s(o,{position:e,fog:o.fog}):o,d=n(h,"opaque"===t?{...D,arrays:r.arrays}:D,i),M=new this.webGpu.WGSLShaderMaterial({vertexShader:d.vertexShader,fragmentShader:d.fragmentShader,depthVertexShader:d.depthVertexShader,depthFragmentShader:d.depthFragmentShader,pointShadowVertexShader:d.pointShadowVertexShader,pointShadowFragmentShader:d.pointShadowFragmentShader,uniforms:d.uniforms,textures:d.textures,sceneTextures:d.sceneTextures,graphTextures:d.graphTextures,vertexAttributes:withThreeDefaultVertexAttributeValues(d.vertexAttributes),uniformValuesAutoUpdate:l?P(a):o.uniformValuesAutoUpdate,transparent:d.renderState?.transparent,alphaTest:d.renderState?.alphaTest,depthTest:d.renderState?.depthTest,depthWrite:d.renderState?.depthWrite,side:d.renderState?.side,wireframe:o.wireframe});M.name=a.name||o.name||a.uuid,M.userData.pipelineOrigin={assetId:a.userData.assetId??o.userData.assetId,assetName:a.userData.assetName??o.userData.assetName,sourceUuid:a.uuid,sourceName:a.name,sourceType:a.type,sourceVersion:a.version},M.uniformValuesAutoUpdate=l?P(a):o.uniformValuesAutoUpdate,function(e,a){if(null==e)return;Object.assign(a,e)}(d.renderState,M),null!=m&&(m.material.dispose(),this.cacheValues.delete(m));const v={signature:f,compiled:d,material:M,inheritsWorldEnvironment:c,sourceVersion:a.version,sourceUniformValuesAutoVersion:l?j(a):o.uniformValuesAutoVersion,worldEnvironmentRevision:this.worldEnvironmentRevision},y=p??new Map;return y.set(u,v),this.cache.set(o,y),this.cacheValues.add(v),_(o,M.uniforms),G(o,M),M}catch(e){let a=this.failedSignatures.get(o);if(null==a&&(a=new Map,this.failedSignatures.set(o,a)),a.get(u)!==f){a.set(u,f);const t=e instanceof Error?e.message:String(e),n=o.name||o.uuid;console.warn(`[Hology WebGPU experiment] Falling back for NodeShaderMaterial "${n}": ${t}`,{material:o,error:e})}return}}getOrCreateOutlineMaterial(e){let t=this.outlineMaterials.get(e);if(null==t){const n=e.nodeMaterialDefinition,s=e.outputAlbedo;if(null==s)throw new Error("Cannot derive an outline material without an albedo output");const o=y("outlineThickness",.003),r=y("outlineDarkening",.65),l=y("outlineAlpha",1),f=new F(v.position.xyz),h=new O(v.normal),w=n.transform?.multiplyVec(V(f,1))??V(f,1),S=g.modelViewMatrix.multiplyVec(w),x=M(g.normalMatrix.multiplyVec(h)),T=d(m(p(S.xyz),u(1e-4))).multiply(.5),E=S.xyz.add(x.multiplyScalar(o.multiply(T))),C=g.projectionMatrix.multiplyVec(S),b=g.projectionMatrix.multiplyVec(V(E,1)),U=(n.position??C).add(b.subtract(C)),A=c(I({color:s.rgb.multiplyScalar(u(1).subtract(r))}),e.outputOpacity.multiply(l));t=new i({color:A,position:U,opacity:e.outputOpacity,discard:n.discard,alphaTest:e.alphaTest,transparent:!0,fog:!1,outputEncoding:n.outputEncoding,uniforms:n.uniforms,uniformNodes:n.uniformNodes}),t.side=a.BackSide,t.depthTest=!0,t.depthWrite=!0,this.outlineMaterials.set(e,t),this.outlineUniformVersions.delete(e)}const n=e.userData?.outlineParameters,s=n?.thickness??.003,o=a.MathUtils.clamp(n?.darkening??.65,0,1),r=a.MathUtils.clamp(n?.alpha??e.opacity,0,1),l=t.uniforms.outlineThickness.value!==s||t.uniforms.outlineDarkening.value!==o||t.uniforms.outlineAlpha.value!==r;t.uniforms.outlineThickness.value=s,t.uniforms.outlineDarkening.value=o,t.uniforms.outlineAlpha.value=r,t.userData.outlineSource=e,t.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate;let f=this.outlineUniformVersions.get(e);const h=e.uniformValuesAutoUpdate||null==f||f.version!==e.uniformValuesAutoVersion||f.uniforms!==e.uniforms;if(h){for(const a in e.uniforms)null!=t.uniforms[a]&&(t.uniforms[a].value=e.uniforms[a].value);f?(f.version=e.uniformValuesAutoVersion,f.uniforms=e.uniforms):(f={version:e.uniformValuesAutoVersion,uniforms:e.uniforms},this.outlineUniformVersions.set(e,f))}return e.uniformValuesAutoUpdate||!l&&!h||(t.uniformValuesNeedsUpdate=!0),t}compileFullscreen(e){const a=t({color:e.outputColor,wgslBindings:{...D,uniformExpressions:{},graphTextures:{...D.graphTextures,[W]:{resource:"hologyNormalRoughness",dimension:"2d",sampleType:"float",sampler:"filtering"}}}}),n=a.syncLiveUniforms;return{...a,syncLiveUniforms(a){n(a),_(e,a)}}}getOrCreateMappedNodeMaterial(e){const t=function(e){const t=[e.vertexColors,e.transparent,e.alphaTest,e.side,e.depthTest,e.depthWrite,e.wireframe??!1];if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){if(t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.roughnessMap?e.roughnessMap.uuid:null,e.metalnessMap?e.metalnessMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null),e instanceof a.MeshPhysicalMaterial){t.push(e.clearcoat>0,e.iridescence>0,e.transmission>0,e.sheen>0,e.anisotropy>0,1.5!==e.ior,1!==e.specularIntensity,1!==e.specularColor.r||1!==e.specularColor.g||1!==e.specularColor.b);for(const a of Q)t.push(e[a]?.uuid??null)}}else e instanceof a.MeshLambertMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.MeshToonMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.gradientMap?e.gradientMap.uuid:null):e instanceof a.MeshBasicMaterial?t.push(e.map?e.map.uuid:null,e.aoMap?e.aoMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.MeshPhongMaterial?t.push(e.map?e.map.uuid:null,e.normalMap?e.normalMap.uuid:null,e.aoMap?e.aoMap.uuid:null,e.emissiveMap?e.emissiveMap.uuid:null,e.lightMap?e.lightMap.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.envMap?e.envMap.uuid:null):e instanceof a.SpriteMaterial&&t.push(e.map?e.map.uuid:null,e.alphaMap?e.alphaMap.uuid:null,e.sizeAttenuation);return t.join(",")}(e),n=this.mappedMaterialsCache.get(e),i=this.mappedMaterialsSignatures.get(e);if(null!=n&&i===t)return n;if(null!=n){n.dispose();const e=this.cache.get(n);if(null!=e){for(const a of e.values())a.material.dispose(),this.cacheValues.delete(a);this.cache.delete(n)}}const s=function(e){if(e instanceof a.SpriteMaterial){const a=new C;a.color=e.color,a.opacity=e.opacity,a.rotation=e.rotation,a.screenSpaceSize=e.sizeAttenuation?0:1,a.alphaTest=e.alphaTest,e.map&&(a.map=e.map),e.alphaMap&&(a.alphaMap=e.alphaMap);const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t}if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){const t=new S;if(t.color=e.color,t.opacity=e.opacity,t.roughness=e.roughness,t.metalness=e.metalness,t.vertexColor=e.vertexColors,e.map&&(t.map=l(e.map)),e.normalMap&&(t.normalMap=l(e.normalMap),t.normalScale=e.normalScale),e.roughnessMap&&(t.roughnessMap=l(e.roughnessMap)),e.metalnessMap&&(t.metalnessMap=l(e.metalnessMap)),e.aoMap&&(t.aoMap=l(e.aoMap),t.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(t.emissiveMap=l(e.emissiveMap)),e.lightMap&&(t.lightMap=l(e.lightMap),t.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(t.alphaMap=l(e.alphaMap)),t.emissive=e.emissive,t.emissiveIntensity=e.emissiveIntensity,t.envMap=e.envMap,t.envMapIntensity=e.envMapIntensity,t.alphaTest=e.alphaTest,e instanceof a.MeshPhysicalMaterial){for(const a of H)t[a]=e[a];for(const a of J)t[a]=e[a];for(const a of Q)e[a]&&(t[a]=l(e[a]));t.clearcoatNormalScale=e.clearcoatNormalScale,t.iridescenceThicknessRange=new a.Vector2(...e.iridescenceThicknessRange),t.anisotropyRotation=e.anisotropyRotation}const n=t.build();return n.transparent=e.transparent,n.side=e.side,n.depthTest=e.depthTest,n.depthWrite=e.depthWrite,n.wireframe=e.wireframe,n}if(e instanceof a.MeshLambertMaterial){const a=new x;a.color=e.color,a.opacity=e.opacity,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.envMap=e.envMap,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}if(e instanceof a.MeshToonMaterial){const a=new T;a.color=e.color,a.opacity=e.opacity,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}if(e instanceof a.MeshBasicMaterial||e instanceof a.LineBasicMaterial){const t=new E;t.color=e.color,t.opacity=e.opacity,t.vertexColor=e.vertexColors,e instanceof a.MeshBasicMaterial&&(e.map&&(t.map=l(e.map)),e.aoMap&&(t.aoMap=l(e.aoMap),t.aoMapIntensity=e.aoMapIntensity),e.lightMap&&(t.lightMap=l(e.lightMap),t.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(t.alphaMap=l(e.alphaMap)),t.envMap=e.envMap),t.alphaTest=e.alphaTest;const n=t.build();return n.transparent=e.transparent,n.side=e.side,n.depthTest=e.depthTest,n.depthWrite=e.depthWrite,n.wireframe=e instanceof a.MeshBasicMaterial&&e.wireframe,n}if(e instanceof a.MeshPhongMaterial){const a=new S;a.color=e.color,a.opacity=e.opacity,a.roughness=Math.max(0,1-e.shininess/100),a.metalness=0,a.vertexColor=e.vertexColors,e.map&&(a.map=l(e.map)),e.normalMap&&(a.normalMap=l(e.normalMap),a.normalScale=e.normalScale),e.aoMap&&(a.aoMap=l(e.aoMap),a.aoMapIntensity=e.aoMapIntensity),e.emissiveMap&&(a.emissiveMap=l(e.emissiveMap)),e.lightMap&&(a.lightMap=l(e.lightMap),a.lightMapIntensity=e.lightMapIntensity),e.alphaMap&&(a.alphaMap=l(e.alphaMap)),a.emissive=e.emissive,a.emissiveIntensity=e.emissiveIntensity,a.envMap=e.envMap,a.alphaTest=e.alphaTest;const t=a.build();return t.transparent=e.transparent,t.side=e.side,t.depthTest=e.depthTest,t.depthWrite=e.depthWrite,t.wireframe=e.wireframe,t}return null}(e);return null==s?null:(s.wireframe=e.wireframe??!1,this.mappedMaterialsCache.set(e,s),this.mappedMaterialsSignatures.set(e,t),e.addEventListener("dispose",()=>{const a=this.mappedMaterialsCache.get(e);if(null!=a){a.dispose(),this.mappedMaterialsCache.delete(e),this.mappedMaterialsSignatures.delete(e);const t=this.cache.get(a);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(a)}}}),s)}canResolve(e){return null!=this.resolve(e)}dispose(){for(const[e,a]of this.observedNodeMaterials)e.removeEventListener("dispose",a);this.observedNodeMaterials.clear();for(const e of this.cacheValues)e.material.dispose();this.cacheValues.clear()}syncInheritedWorldEnvironmentSource(e,a){a.inheritsWorldEnvironment&&null!=this.worldEnvironment&&(e.uniforms.envMap.value=this.worldEnvironment.texture,e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity)}getNodeMaterialSignature(e,a){const t=`${createNodeMaterialSignature(e)}|receiveDecals:${!1!==e.userData.receiveDecals}`;return a?`${t}|worldEnvironment:${this.worldEnvironmentRevision}`:t}prepareWorldEnvironment(e){var t,n,i,s,o,r;if(null!=e.envMap){const s=this.environmentTextureResolver?.(e.envMap)??e.envMap;return(t=e.uniforms).envMap??(t.envMap={value:s}),e.uniforms.envMap.value=s,(n=e.uniforms).envMapIntensity??(n.envMapIntensity={value:1}),(i=e.uniforms).envMapRotation??(i.envMapRotation={value:new a.Matrix3}),this.worldEnvironmentMaterials.delete(e),!1}return null==this.worldEnvironment?(this.worldEnvironmentMaterials.has(e)&&(delete e.uniforms.envMap,delete e.uniforms.envMapIntensity,delete e.uniforms.envMapRotation,this.worldEnvironmentMaterials.delete(e)),!1):((s=e.uniforms).envMap??(s.envMap={value:this.worldEnvironment.texture}),e.uniforms.envMap.value=this.worldEnvironment.texture,(o=e.uniforms).envMapIntensity??(o.envMapIntensity={value:this.worldEnvironment.intensity}),e.uniforms.envMapIntensity.value=this.worldEnvironment.intensity,(r=e.uniforms).envMapRotation??(r.envMapRotation={value:new a.Matrix3}),this.worldEnvironmentMaterials.add(e),!0)}observeNodeMaterial(e){if(this.observedNodeMaterials.has(e))return;const a=()=>{e.removeEventListener("dispose",a),this.observedNodeMaterials.delete(e);const t=this.cache.get(e);if(null!=t){for(const e of t.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(e)}const n=this.outlineMaterials.get(e);if(null!=n){const a=this.cache.get(n);if(null!=a){for(const e of a.values())e.material.dispose(),this.cacheValues.delete(e);this.cache.delete(n)}this.failedSignatures.delete(n),z.delete(n),n.dispose(),this.outlineMaterials.delete(e),this.outlineUniformVersions.delete(e)}this.failedSignatures.delete(e),z.delete(e)};this.observedNodeMaterials.set(e,a),e.addEventListener("dispose",a)}}function B(e,a,t=!1){const n=a.material;n.uniformValuesAutoUpdate=e.uniformValuesAutoUpdate,(t||e.uniformValuesAutoUpdate||a.sourceUniformValuesAutoVersion!==e.uniformValuesAutoVersion)&&(a.compiled.syncLiveUniforms(n.uniforms),_(e,n.uniforms),G(e,n),a.sourceUniformValuesAutoVersion=e.uniformValuesAutoVersion,n.uniformValuesAutoUpdate||(n.uniformValuesNeedsUpdate=!0))}function _(e,a){let t=$.get(a);if(null==t){t=[];for(const e in a){const n=a[e],i=n.value,s=!0===i?.isVector2?2:!0===i?.isVector3?3:!0===i?.isVector4?4:!0===i?.isColor?5:0;t.push({name:e,target:n,copyKind:s})}$.set(a,t)}const n=e.uniforms;for(let e=0;e<t.length;e++){const a=t[e],i=n[a.name];if(null==i)continue;const s=i.value,o=a.target.value;if(s!==o){if(0!==a.copyKind){const e=s,t=o;if((2===a.copyKind?!0===e?.isVector2:3===a.copyKind?!0===e?.isVector3:4===a.copyKind?!0===e?.isVector4:!0===e?.isColor)&&"function"==typeof t?.copy){t.copy(s);continue}}a.target.value=s}}}function G(e,t){const n=e.uniforms.envMapIntensity,i=t.uniforms.envMapIntensity;null!=n&&null!=i&&(i.value=n.value);const s=e.uniforms.envMapRotation?.value,o=t.uniforms.envMapRotation?.value;s instanceof a.Matrix3&&o instanceof a.Matrix3&&o.copy(s)}function K(e,a){for(const t in a.textures){const n=a.textures[t],i=e.uniforms[t]?.value;if(q(i)&&i!==n)return!1}return!0}function q(e){return!0===e?.isTexture}const H=["ior","specularIntensity","clearcoat","clearcoatRoughness","iridescence","iridescenceIOR","transmission","thickness","attenuationDistance","dispersion","sheen","sheenRoughness","anisotropy"],J=["specularColor","attenuationColor","sheenColor"],Q=["specularIntensityMap","specularColorMap","clearcoatMap","clearcoatRoughnessMap","clearcoatNormalMap","iridescenceMap","iridescenceThicknessMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","anisotropyMap"];function X(e,t){if(e instanceof a.SpriteMaterial){const n=t;t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),n.rotation=e.rotation,n.screenSpaceSize=e.sizeAttenuation?0:1}else if(e instanceof a.MeshStandardMaterial||e instanceof a.MeshPhysicalMaterial){if(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=e.roughness),t.uniforms.metalness&&(t.uniforms.metalness.value=e.metalness),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity),t.uniforms.envMapIntensity&&(t.uniforms.envMapIntensity.value=e.envMapIntensity),e instanceof a.MeshPhysicalMaterial){for(const a of H)t.uniforms[a]&&(t.uniforms[a].value=e[a]);for(const n of J){const i=t.uniforms[n]?.value;i instanceof a.Vector3&&i.setFromColor(e[n])}const n=t.uniforms.clearcoatNormalScale?.value;n instanceof a.Vector2&&n.copy(e.clearcoatNormalScale),t.uniforms.iridescenceThicknessMin&&(t.uniforms.iridescenceThicknessMin.value=e.iridescenceThicknessRange[0]),t.uniforms.iridescenceThicknessMax&&(t.uniforms.iridescenceThicknessMax.value=e.iridescenceThicknessRange[1]);const i=t.uniforms.anisotropyDirection?.value;i instanceof a.Vector2&&i.set(Math.cos(e.anisotropyRotation),Math.sin(e.anisotropyRotation))}}else e instanceof a.MeshLambertMaterial||e instanceof a.MeshToonMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity)):e instanceof a.MeshBasicMaterial||e instanceof a.LineBasicMaterial?(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),e instanceof a.MeshBasicMaterial&&(t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity))):e instanceof a.MeshPhongMaterial&&(t.uniforms.color&&(t.uniforms.color.value instanceof a.Vector3?t.uniforms.color.value.setFromColor(e.color):t.uniforms.color.value instanceof a.Color&&t.uniforms.color.value.copy(e.color)),t.uniforms.opacity&&(t.uniforms.opacity.value=e.opacity),t.uniforms.roughness&&(t.uniforms.roughness.value=Math.max(0,1-e.shininess/100)),t.uniforms.emissive&&(t.uniforms.emissive.value instanceof a.Vector3?t.uniforms.emissive.value.setFromColor(e.emissive):t.uniforms.emissive.value instanceof a.Color&&t.uniforms.emissive.value.copy(e.emissive)),t.uniforms.emissiveIntensity&&(t.uniforms.emissiveIntensity.value=e.emissiveIntensity),t.uniforms.normalScale&&e.normalScale&&(t.uniforms.normalScale.value=e.normalScale.x),t.uniforms.aoMapIntensity&&(t.uniforms.aoMapIntensity.value=e.aoMapIntensity),t.uniforms.lightMapIntensity&&(t.uniforms.lightMapIntensity.value=e.lightMapIntensity))}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -4,8 +4,8 @@ import type { WorldEnvironmentState } from './environment.js';
|
|
|
4
4
|
import type { RenderingBackendDriver } from './rendering-backend.js';
|
|
5
5
|
import type { PostProcessEffectStage } from './post-process-effect.js';
|
|
6
6
|
import type { DlssQualityMode } from './upscaling-pass.js';
|
|
7
|
-
import type { BloomOptions, ColorGradingOptions, DepthOfFieldOptions, FXAAOptions, FrameGraphBuilder, GTAOOptions, GTAOQuality, OutlineOptions, OutlineInstanceSelection, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, SSROptions, RendererFrameProfile, SMAAOptions, TemporalAAOptions, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
8
|
-
export type { RendererFrameProfile, GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
7
|
+
import type { BloomOptions, ColorGradingOptions, DepthOfFieldOptions, FXAAOptions, FrameGraphBuilder, GTAOOptions, GTAOQuality, OutlineOptions, OutlineInstanceSelection, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, SSROptions, RendererFrameProfile, RendererSceneCapture, SMAAOptions, TemporalAAOptions, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
8
|
+
export type { RendererFrameProfile, RendererSceneCapture, RendererSceneCaptureOptions, RendererSceneCapturePostProcessContext, GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from '@hology/webgpu-renderer';
|
|
9
9
|
type SupportedCamera = THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
10
10
|
export type AntiAliasingMode = 'off' | 'fxaa' | 'smaa' | 'taa';
|
|
11
11
|
export type ExperimentalWebGpuRenderGraphExtension = ((graph: FrameGraphBuilder, color: string) => void) & {
|
|
@@ -133,6 +133,7 @@ export declare class ExperimentalWebGpuBackend implements RenderingBackendDriver
|
|
|
133
133
|
initTexture(texture: THREE.Texture): void;
|
|
134
134
|
setPostProcessEffects(effects: readonly ExperimentalWebGpuPostProcessEffect[]): void;
|
|
135
135
|
getDevice(): GPUDevice | null;
|
|
136
|
+
createSceneCapture(canvas: HTMLCanvasElement | null, width?: number, height?: number): RendererSceneCapture;
|
|
136
137
|
setRenderGraphExtensions(extensions: Iterable<ExperimentalWebGpuRenderGraphExtension>): void;
|
|
137
138
|
setPresentationExtensions(extensions: Iterable<WebGpuPresentationExtension>): void;
|
|
138
139
|
setEnableOutlines(enabled: boolean): void;
|
|
@@ -156,6 +157,7 @@ export declare class ExperimentalWebGpuBackend implements RenderingBackendDriver
|
|
|
156
157
|
resetViewHistory(): void;
|
|
157
158
|
compile(scene: THREE.Scene, camera: SupportedCamera): Promise<void>;
|
|
158
159
|
createStaticDrawSet(root: THREE.Object3D, label: string, allowUnsortedLateDraws?: boolean, onUnsupported?: 'throw' | 'skip'): ExperimentalWebGpuStaticDrawSet | null;
|
|
160
|
+
registerStaticSpatialObject(root: THREE.Object3D): import('@hology/webgpu-renderer').StaticSpatialObject;
|
|
159
161
|
render(scene: THREE.Scene, camera: SupportedCamera, timeSeconds: number): void;
|
|
160
162
|
setMotionBlurOptions(options: MotionBlurOptions): void;
|
|
161
163
|
setGTAOOptions(options: GTAOOptions): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as e from"three";import{NodeMaterialWebGpuResolver as t}from"./node-material-webgpu-resolver.js";import{configureWebGpuRuntimeBindings as i}from"./webgpu-runtime-bridge.js";import{float as n,varyingTransformed as r,vec4 as a}from"three-shader-graph";import{NodeShaderMaterial as o}from"../shader-nodes/index.js";import{sceneMapUniformName as s}from"../shader-nodes/scene-sample.js";import{depthUniformName as l}from"../shader-nodes/depth.js";import{MATERIAL_FLAG_ALPHA_TEST as d,MATERIAL_FLAG_RECEIVE_DECALS as c}from"../shader-nodes/material-flags.js";import{createMotionVectorOutput as h}from"./motion-vector-node.js";export class ExperimentalWebGpuBackend{constructor(e,t,i,n,r,a,o,s,l,d,c,h,u,p,m,g,f,v,S,b,P,x){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=r,this.fxaa=a,this.smaa=o,this.gtao=s,this.ssr=l,this.taa=d,this.motionBlur=c,this.volumetricFog=h,this.colorGrading=u,this.depthOfField=p,this.outline=m,this.postProcessEffects=g,this.renderGraphExtensions=f,this.presentationExtensions=v,this.antiAliasingState=S,this.directionalShadowState=b,this.nativeDlss=P,this.kind="webgpu",this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,this.secondaryMotionPrepared=!1,this.canvas=x}static async probeAvailability(){if("undefined"==typeof navigator||!("gpu"in navigator))return{available:!1,reason:"The runtime does not expose navigator.gpu."};try{const e=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});return null==e?{available:!1,reason:"No WebGPU adapter is available."}:{available:!0,adapter:e}}catch(e){return{available:!1,reason:`Requesting a WebGPU adapter failed: ${e instanceof Error?e.message:String(e)}`}}}static async create(m={},g){const f=await import("@hology/webgpu-renderer");i({registerPipelineDiagnosticOrigin:f.registerPipelineDiagnosticOrigin,createComputeKernel:(e,t)=>new f.ComputeKernel(e,t),buildParticleLightingShaderHeader:f.buildParticleLightingShaderHeader});const v=document.createElement("canvas");v.dataset.hologyRenderer="webgpu-experimental";const S=new f.WGSLShaderMaterial({vertexShader:u,fragmentShader:p}),b=!1!==m.nativeUpscaling&&"dlss"===m.nativeUpscaling?.method,P=b?(await import("./native-dlss-upscaler.js")).createNativeDlssUpscaler(m.nativeUpscaling?.mode??"quality"):null,x=null!=P;S.side=f.DoubleSide;const w=f,y=null!=m.motionBlur&&!1!==m.motionBlur,D=!1!==m.gtao&&(null==m.gtao||!1!==m.gtao.temporal),M=!1!==m.volumetricFog&&(null==m.volumetricFog||!1!==m.volumetricFog.temporal),E=x?"off":b?"taa":null!=(O=m).antiAliasing?O.antiAliasing:null!=O.taa&&!1!==O.taa?"taa":null!=O.smaa&&!1!==O.smaa?"smaa":null!=O.fxaa&&!1!==O.fxaa?"fxaa":!1===O.taa?"off":"taa";var O;const F=null!=m.antiAliasing,L=y||D||M||(F||"taa"===E)||x;let C=null;const G=new t(w,(e,t)=>"opaque"===t?[e.outputColor.xyz.rgba(n(e.alphaTest>0?d:0).add(!1===e.userData.receiveDecals?0:c)),a((e.outputNormal??r.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??n(1)),...L?[h(e)]:[]]:void 0,e=>C?.getEnvironmentTexture(e)??e),R=new e.MeshStandardMaterial({color:8688803,roughness:1});if(null==G.resolve(R,"opaque"))throw S.dispose(),R.dispose(),new Error("Failed to compile the WebGPU G-buffer fallback material.");const T=!1===m.gtao?null:new f.GTAOEffect({normalSpace:"view",...f.GTAO_PRESETS.high,...m.gtao??{}}),A=!1===m.ssr||null==m.ssr?null:new f.SSREffect({normalSpace:"view",resolutionScale:.5,...m.ssr??{}}),B=!1===m.bloom?null:new f.BloomEffect({threshold:1,strength:.9,radius:.2,...m.bloom??{}}),U=F||!1!==m.fxaa&&"fxaa"===E?new f.FXAAEffect(!1===m.fxaa?{}:m.fxaa):null,W=F||!1!==m.smaa&&"smaa"===E?new f.SMAAEffect(!1===m.smaa?{}:m.smaa):null,k=x||F||!1!==m.taa&&"taa"===E?new f.TemporalAAEffect({renderScale:1,...!1===m.taa?{}:m.taa}):null,V={mode:E},I=!1===m.motionBlur||null==m.motionBlur?null:new f.MotionBlurEffect(m.motionBlur),N=m.volumetricFog||void 0,j=!1===m.volumetricFog?null:new f.VolumetricFogEffect(void 0,{...f.VOLUMETRIC_FOG_PRESETS.high,maxDistance:64,spatialJitter:!0,scatteringIntensity:Math.PI,...N,temporal:!1!==N?.temporal&&{...f.VOLUMETRIC_FOG_PRESETS.high.temporal,...N?.temporal},blur:!1!==N?.blur&&{...!1===f.VOLUMETRIC_FOG_PRESETS.high.blur?{}:f.VOLUMETRIC_FOG_PRESETS.high.blur,depthAwareUpsample:!0,...N?.blur}}),H=!1===m.colorGrading?null:new f.ColorGradingEffect({enabled:!1,...m.colorGrading??{}}),$=!1===m.depthOfField?null:new f.DepthOfFieldEffect({enabled:!1,...m.depthOfField??{}}),_=!1===m.outline?null:new f.OutlineEffect({enabled:!1,...m.outline??{}}),q=[],z=new WeakMap,J=new Set,K=[],Z=[],Q=(e,t,i)=>{let n=i;const r=q.filter(e=>e.enabled&&e.stage===t).sort((e,t)=>e.priority-t.priority||e.id-t.id);for(const t of r){if(!(t.material instanceof o)){const e=`${t.id}:material`;J.has(e)||(J.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: only NodeShaderMaterial effects are supported.`));continue}try{let i=z.get(t.material);null!=i&&i.version===t.material.version||(i={version:t.material.version,shader:G.compileFullscreen(t.material),diagnosticOrigin:{key:"post-process:"+String(t.material.userData.assetId??(t.material.name||t.material.uuid)),material:{name:t.material.name,uuid:t.material.uuid,version:t.material.version,assetId:t.material.userData.assetId,assetName:t.material.userData.assetName}}},z.set(t.material,i));const r=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,diagnosticOrigin:i.diagnosticOrigin,shader:i.shader,inputOverrides:{[s]:n},outputs:r}),n=r}catch(e){const i=`${t.id}:compile:${t.material.version}`;J.has(i)||(J.add(i),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: ${e instanceof Error?e.message:String(e)}`,e))}}return n},X={enabled:!0},Y=new f.WebGpuRenderer({canvas:v,fallbackMaterial:S,materialResolver:(e,t)=>G.resolve(e,t),invokeObjectRenderCallbacks:!1,hiZOcclusionCulling:!0,renderGraphProfiling:!1,sampleCount:1,multiDrawIndirect:!1,nativePostSubmit:P?.postSubmit,presentationOverlay:e=>{for(const t of Z)t(e)}});Y.setRenderScale("taa"===E?k?.renderScale??1:1),Y.setRenderGraphBuilder((e,t)=>{const i=new f.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba8unorm"}),r=L?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of K)"beforeScene"===e.stage&&e(i,i.sceneColor);X.enabled&&i.addDirectionalShadowPass(),i.addPointShadowPass(),i.addSpotShadowPass(),i.addDepthPrepass(),i.addHiZPasses(),i.addVisibilityPass(),i.addMaterialPass({name:"OpaqueGBufferPass",outputs:null==r?[i.sceneColor,n]:[i.sceneColor,n,r],drawStage:"opaque",loadDepth:!0}),i.addHiZHistoryPass("OpaqueGBufferPass");let a=i.sceneColor;if(T?.enabled){const e=T.addPasses(i,{depth:i.mainDepth,normal:n,velocity:r??void 0});a=T.addCompositePass(i,a,e)}null!=A&&(a=A.addPasses(i,{sceneColor:a,depth:i.mainDepth,normalRoughness:n}));const o=new Set(K.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(a,{sceneColor:o.has("sceneColorSnapshot"),sceneDepth:o.has("sceneDepthSnapshot")||q.some(e=>e.enabled&&null!=e.material.uniforms[l])}),a=Q(i,"beforeFog",a),i.addLatePass(a);for(const e of K)null!=e.stage&&"afterScene"!==e.stage||e(i,a);null!=j&&(a=j.addPasses(i,{sceneColor:a,depth:i.mainDepth,velocity:r??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=I&&null!=r&&(a=I.addPass(i,a,r,i.mainDepth)),null!=B&&(a=B.addPass(i,a)),a=Q(i,"beforeOutline",a),null!=_&&(a=_.addPass(i,a)),a=Q(i,"beforeDepthOfField",a),null!=$&&(a=$.addPass(i,a,i.mainDepth)),a=Q(i,"beforeColorAdjustment",a),null!=H&&(a=H.addPass(i,a)),a=Q(i,"beforeAntiAliasing",a);let s="taa"===V.mode&&null!=k?k.addPass(i,a,i.mainDepth,r??void 0):a;"smaa"===V.mode&&null!=W?s=W.addPass(i,s):"fxaa"===V.mode&&null!=U&&(s=U.addPass(i,s)),s=Q(i,"beforeOutput",s);for(const e of K)"beforePresent"===e.stage&&e(i,s);!0===P?.enabled&&null!=r?P.addInputPass(i,s,r):i.present(s)});try{return await Y.initialize(g),C=new ExperimentalWebGpuBackend(Y,S,G,R,B,U,W,T,A,k,I,j,H,$,_,q,K,Z,V,X,P,v),C}catch(e){throw Y.destroy(),S.dispose(),G.dispose(),R.dispose(),T?.dispose(),W?.dispose(),I?.dispose(),j?.dispose(),_?.dispose(),e}}static supportsCamera(t){return t instanceof e.PerspectiveCamera||t instanceof e.OrthographicCamera}setSize(e,t,i,n=1){const r=this.canvas.width,a=this.canvas.height;let o=Math.min(1,Math.max(.25,n));if(!0===this.nativeDlss?.enabled){const n=Math.max(1,Math.floor(e*i)),r=Math.max(1,Math.floor(t*i));o=this.nativeDlss.getRenderScale(n,r)}const s=o!==this.renderScale;this.renderScale=o,this.renderer.setRenderScale(o),this.taa?.setRenderScale(o),this.renderer.setSize(e,t,i),(s||this.canvas.width!==r||this.canvas.height!==a)&&this.resetViewHistory()}initTexture(e){this.renderer.initTexture(e)}setPostProcessEffects(e){this.postProcessEffects.splice(0,this.postProcessEffects.length,...e);for(const t of e){if("beforeLut"!==t.stage)continue;const e=`${t.id}:${t.stage}`;this.warnedUnsupportedPostProcessStages.has(e)||(this.warnedUnsupportedPostProcessStages.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: stage "${t.stage}" has no native WebGPU anchor.`))}}getDevice(){return this.renderer.getDevice()}setRenderGraphExtensions(e){this.renderGraphExtensions.length=0;for(const t of e)this.renderGraphExtensions.push(t)}setPresentationExtensions(e){this.presentationExtensions.length=0;for(const t of e)this.presentationExtensions.push(t)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=e)}setTiledLightingEnabled(e){this.renderer.setTiledLightingEnabled(e)}setDynamicBatchingEnabled(e){this.renderer.setDynamicBatchingEnabled(e)}setSelectedObjects(e){this.outline?.setSelectedObjects(e)}setSelectedObjectInstances(e){this.outline?.setSelectedInstances(e)}setCascadedShadowRanges(e,t=[]){this.renderer.setCascadedShadowRanges(e,t),this.volumetricFog?.setCascadedDirectionalLights(t)}setDirectionalShadowUpdateOptions(e){this.renderer.setDirectionalShadowUpdateOptions(e)}invalidateDirectionalShadows(){this.renderer.invalidateDirectionalShadows()}setDirectionalShadowOptions(e,t){this.directionalShadowState.enabled=e,this.renderer.setDirectionalShadowsEnabled(e),this.renderer.setDirectionalShadowMapSize(t)}setWorldEnvironment(e){if(null==e)return void this.nodeMaterialResolver.setWorldEnvironment(null);const t=this.getEnvironmentTexture(e.source);this.nodeMaterialResolver.setWorldEnvironment({texture:t,intensity:e.intensity})}getEnvironmentTexture(t){if(t.mapping===e.CubeUVReflectionMapping)return t;let i=this.pmremResults.get(t);return null==i&&(this.pmremGenerator??(this.pmremGenerator=this.renderer.createPMREMGenerator()),i=this.pmremGenerator.fromEquirectangular(t),this.pmremResults.set(t,i),this.ownedPmremResults.add(i)),i.texture}resetViewHistory(){this.renderer.resetViewHistory(),this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.nativeDlss?.reset()}async compile(e,t){if(!this.secondaryMotionPrepared){let t=!1;e.traverse(e=>{const i=e.userData.secondaryMotion?.regions;Array.isArray(i)&&i.some(e=>e.enabled)&&(t=!0)});const i=this.renderer.getDevice();if(t&&i){const{prepareSecondaryMotionRuntime:e}=await import("../secondary-motion/runtime.js");e(i),this.secondaryMotionPrepared=!0}}await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1,n="skip"){this.renderer.setHiZOcclusionCullingEnabled(!0);const r=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:n,allowUnsortedLateDraws:i});return 0===r.drawCount?(r.dispose(),null):r}render(e,t,i){const n="taa"===this.antiAliasingState.mode?this.taa:null;this.volumetricFog?.setScene(e),this.renderer.setMotionVectorProjection(t.projectionMatrix),this.motionBlur?.prepareCamera(t,this.canvas.width,this.canvas.height,i),this.motionBlur?.requiresRendererHistoryReset()&&(this.renderer.resetViewHistory(),this.gtao?.reset(),this.volumetricFog?.reset()),n?.prepareCamera(t,this.canvas.width,this.canvas.height),this.nativeDlss?.prepareFrame(t);const r=!0===this.nativeDlss?.enabled?this.nativeDlss.jitter:null;this.motionBlur?.setJitterUv(n?.currentJitterUv.x??(null==r?0:r.x/Math.max(1,this.canvas.width*this.renderScale)),n?.currentJitterUv.y??(null==r?0:-r.y/Math.max(1,this.canvas.height*this.renderScale))),null!=r&&this.renderer.setProjectionJitter(r.x,r.y);let a=!1;try{this.renderer.render(e,t,i),a=!0}finally{null!=r&&this.renderer.clearProjectionJitter(),n?.finishCamera(t),a&&this.motionBlur?.commitCamera(),a&&this.nativeDlss?.finishFrame(t)}}setMotionBlurOptions(e){null!=this.motionBlur&&Object.assign(this.motionBlur.options,e)}setGTAOOptions(e){this.gtao?.setOptions(e)}setAntiAliasingMode(e){e!==this.antiAliasingState.mode&&("taa"===e&&null==this.taa||"smaa"===e&&null==this.smaa||"fxaa"===e&&null==this.fxaa?console.warn(`[Hology WebGPU experiment] Anti-aliasing mode "${e}" was not initialized. Set webgpuPostProcessing.antiAliasing in the initial rendering configuration to enable runtime switching.`):(this.antiAliasingState.mode=e,this.resetTemporalHistory()))}setGTAOQuality(e){this.gtao?.applyPreset(e)}setVolumetricFogOptions(e){this.volumetricFog?.setOptions(e)}setVolumetricFogQuality(e){this.volumetricFog?.applyPreset(e)}pushMotionBlurOverride(e){return this.motionBlur?.pushOverride(e)??null}invalidateObjectMotion(e){this.renderer.invalidateObjectMotion(e)}getLastFrameProfile(){return this.renderer.getLastFrameProfile()}setPostProcessState(e){null!=this.colorGrading&&(Object.assign(this.colorGrading.options,e??{enabled:!1}),this.colorGrading.options.enabled=!0===e?.enabled),null!=this.depthOfField&&(this.depthOfField.options.enabled=null!=e?.depthFocus||null!=e?.depthAperture||null!=e?.depthMaxBlur,this.depthOfField.options.focus=e?.depthFocus,this.depthOfField.options.aperture=e?.depthAperture,this.depthOfField.options.maxBlur=e?.depthMaxBlur)}setProfilingEnabled(e){this.renderer.setRenderGraphProfilingEnabled(e)}resetTemporalHistory(){this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.renderer.resetViewHistory(),this.nativeDlss?.reset()}inspect(e,t){return inspectWebGpuScene(e,t,this.nodeMaterialResolver)}destroy(){this.nativeDlss?.dispose(),this.nodeMaterialResolver.dispose(),this.gBufferFallbackSource.dispose(),this.gtao?.dispose(),this.smaa?.dispose(),this.motionBlur?.dispose(),this.volumetricFog?.dispose();for(const e of this.ownedPmremResults)e.dispose();this.ownedPmremResults.clear(),this.renderer.destroy(),this.fallbackMaterial.dispose()}}export function inspectWebGpuScene(e,t,i){const n={meshes:0,skinnedMeshes:0,instancedMeshes:0,batchedMeshes:0,sprites:0,points:0,lines:0,missingPositionGeometry:0,transparentMaterials:0,shaderMaterialsReplaced:0,materialsReplaced:0,unsupportedCamera:ExperimentalWebGpuBackend.supportsCamera(t)?0:1};return e.traverse(e=>{if(e.isSprite)return void n.sprites++;if(e.isPoints)return void n.points++;if(e.isLine)return void n.lines++;if(!e.isMesh)return;const t=e;t.isBatchedMesh?n.batchedMeshes++:t.isInstancedMesh?n.instancedMeshes++:t.isSkinnedMesh?n.skinnedMeshes++:n.meshes++,null==t.geometry?.getAttribute("position")&&n.missingPositionGeometry++;const r=Array.isArray(t.material)?t.material:[t.material];for(const e of r){if(null==e)continue;e.transparent&&n.transparentMaterials++;const t=!0===e.isWGSLShaderMaterial||!0===e.isLineMaterial,r=!t&&!0===i?.canResolve(e);t||r||(n.materialsReplaced++,e.isShaderMaterial&&n.shaderMaterialsReplaced++)}}),n}export function formatWebGpuSceneCapabilitySummary(e){return`[Hology WebGPU experiment] ${JSON.stringify(e)}`}const u="\nstruct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) uv: vec2<f32>,\n @location(3) color: vec4<f32>,\n#ifdef USE_SKINNING\n @location(4) skinIndex: vec4<u32>,\n @location(5) skinWeight: vec4<f32>,\n#endif\n @builtin(instance_index) instanceIndex: u32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\n@vertex\nfn vsMain(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n#ifdef USE_SKINNING\n let localPosition = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight);\n let localNormal = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let localPosition = input.position;\n let localNormal = input.normal;\n#endif\n let world = rendererWorldPosition(localPosition, input.instanceIndex);\n output.position = rendererClipPosition(localPosition, input.instanceIndex);\n output.worldPosition = world.xyz;\n output.worldNormal = rendererWorldNormal(localNormal, input.instanceIndex);\n output.color = input.color * rendererObjectColor(input.instanceIndex);\n return output;\n}\n",p="\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\nfn distanceAttenuation(distanceToLight: f32, cutoffDistance: f32, decayExponent: f32) -> f32 {\n var distanceFalloff = 1.0 / max(pow(distanceToLight, decayExponent), 0.01);\n if (cutoffDistance > 0.0) {\n let ratio = distanceToLight / cutoffDistance;\n let cutoff = clamp(1.0 - ratio * ratio * ratio * ratio, 0.0, 1.0);\n distanceFalloff *= cutoff * cutoff;\n }\n return distanceFalloff;\n}\n\n@fragment\nfn fsMain(input: VertexOutput) -> @location(0) vec4<f32> {\n let normal = normalize(input.worldNormal);\n let normalTint = normal * 0.5 + vec3<f32>(0.5);\n let base = mix(vec3<f32>(0.52, 0.58, 0.64), normalTint, 0.22) * input.color.rgb;\n var lighting = rendererIndirectDiffuse(normal) + vec3<f32>(0.08);\n var directionalLighting = vec3<f32>(0.0);\n let directionalCount = rendererDirectionalLightCount();\n\n for (var index: u32 = 0u; index < directionalCount; index = index + 1u) {\n let lightDirection = rendererDirectionalLightDirectionForLight(index);\n let shadow = rendererSampleDirectionalShadowForLightWithNormal(index, input.worldPosition, normal);\n directionalLighting += rendererDirectionalLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * shadow;\n }\n if (directionalCount > 0u) {\n lighting += directionalLighting / f32(directionalCount);\n }\n\n for (var index: u32 = 0u; index < rendererPointLightCount(); index = index + 1u) {\n let lightVector = rendererPointLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let shadow = rendererSamplePointShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererPointLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * distanceAttenuation(distanceToLight, rendererPointLightRangeForLight(index), rendererPointLightDecayForLight(index)) * shadow;\n }\n\n for (var index: u32 = 0u; index < rendererSpotLightCount(); index = index + 1u) {\n let lightVector = rendererSpotLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let angleCos = dot(-lightDirection, rendererSpotLightDirectionForLight(index));\n let cone = smoothstep(rendererSpotLightConeCosForLight(index), rendererSpotLightPenumbraCosForLight(index), angleCos);\n let shadow = rendererSampleSpotShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererSpotLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * cone * distanceAttenuation(distanceToLight, rendererSpotLightRangeForLight(index), rendererSpotLightDecayForLight(index)) * shadow;\n }\n\n return vec4<f32>(base * max(lighting, vec3<f32>(0.08)), input.color.a);\n}\n";/*
|
|
1
|
+
import*as e from"three";import{NodeMaterialWebGpuResolver as t}from"./node-material-webgpu-resolver.js";import{configureWebGpuRuntimeBindings as i}from"./webgpu-runtime-bridge.js";import{float as n,varyingTransformed as r,vec4 as a}from"three-shader-graph";import{NodeShaderMaterial as o}from"../shader-nodes/index.js";import{sceneMapUniformName as s}from"../shader-nodes/scene-sample.js";import{depthUniformName as l}from"../shader-nodes/depth.js";import{MATERIAL_FLAG_ALPHA_TEST as d,MATERIAL_FLAG_RECEIVE_DECALS as c}from"../shader-nodes/material-flags.js";import{createMotionVectorOutput as h}from"./motion-vector-node.js";export class ExperimentalWebGpuBackend{constructor(e,t,i,n,r,a,o,s,l,d,c,h,u,p,m,g,f,v,S,b,P,x){this.renderer=e,this.fallbackMaterial=t,this.nodeMaterialResolver=i,this.gBufferFallbackSource=n,this.bloom=r,this.fxaa=a,this.smaa=o,this.gtao=s,this.ssr=l,this.taa=d,this.motionBlur=c,this.volumetricFog=h,this.colorGrading=u,this.depthOfField=p,this.outline=m,this.postProcessEffects=g,this.renderGraphExtensions=f,this.presentationExtensions=v,this.antiAliasingState=S,this.directionalShadowState=b,this.nativeDlss=P,this.kind="webgpu",this.renderScale=1,this.pmremGenerator=null,this.pmremResults=new WeakMap,this.ownedPmremResults=new Set,this.warnedUnsupportedPostProcessStages=new Set,this.secondaryMotionPrepared=!1,this.canvas=x}static async probeAvailability(){if("undefined"==typeof navigator||!("gpu"in navigator))return{available:!1,reason:"The runtime does not expose navigator.gpu."};try{const e=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});return null==e?{available:!1,reason:"No WebGPU adapter is available."}:{available:!0,adapter:e}}catch(e){return{available:!1,reason:`Requesting a WebGPU adapter failed: ${e instanceof Error?e.message:String(e)}`}}}static async create(m={},g){const f=await import("@hology/webgpu-renderer");i({registerPipelineDiagnosticOrigin:f.registerPipelineDiagnosticOrigin,createComputeKernel:(e,t)=>new f.ComputeKernel(e,t),buildParticleLightingShaderHeader:f.buildParticleLightingShaderHeader});const v=document.createElement("canvas");v.dataset.hologyRenderer="webgpu-experimental";const S=new f.WGSLShaderMaterial({vertexShader:u,fragmentShader:p}),b=!1!==m.nativeUpscaling&&"dlss"===m.nativeUpscaling?.method,P=b?(await import("./native-dlss-upscaler.js")).createNativeDlssUpscaler(m.nativeUpscaling?.mode??"quality"):null,x=null!=P;S.side=f.DoubleSide;const w=f,y=null!=m.motionBlur&&!1!==m.motionBlur,D=!1!==m.gtao&&(null==m.gtao||!1!==m.gtao.temporal),M=!1!==m.volumetricFog&&(null==m.volumetricFog||!1!==m.volumetricFog.temporal),O=x?"off":b?"taa":null!=(E=m).antiAliasing?E.antiAliasing:null!=E.taa&&!1!==E.taa?"taa":null!=E.smaa&&!1!==E.smaa?"smaa":null!=E.fxaa&&!1!==E.fxaa?"fxaa":!1===E.taa?"off":"taa";var E;const F=null!=m.antiAliasing,C=y||D||M||(F||"taa"===O)||x;let L=null;const G=new t(w,(e,t)=>"opaque"===t?[e.outputColor.xyz.rgba(n(e.alphaTest>0?d:0).add(!1===e.userData.receiveDecals?0:c)),a((e.outputNormal??r.normal).multiplyScalar(.5).addScalar(.5),e.outputRoughness??n(1)),...C?[h(e)]:[]]:void 0,e=>L?.getEnvironmentTexture(e)??e),R=new e.MeshStandardMaterial({color:8688803,roughness:1});if(null==G.resolve(R,"opaque"))throw S.dispose(),R.dispose(),new Error("Failed to compile the WebGPU G-buffer fallback material.");const T=!1===m.gtao?null:new f.GTAOEffect({normalSpace:"view",...f.GTAO_PRESETS.high,...m.gtao??{}}),A=!1===m.ssr||null==m.ssr?null:new f.SSREffect({normalSpace:"view",resolutionScale:.5,...m.ssr??{}}),B=!1===m.bloom?null:new f.BloomEffect({threshold:1,strength:.9,radius:.2,...m.bloom??{}}),U=F||!1!==m.fxaa&&"fxaa"===O?new f.FXAAEffect(!1===m.fxaa?{}:m.fxaa):null,W=F||!1!==m.smaa&&"smaa"===O?new f.SMAAEffect(!1===m.smaa?{}:m.smaa):null,k=x||F||!1!==m.taa&&"taa"===O?new f.TemporalAAEffect({renderScale:1,...!1===m.taa?{}:m.taa}):null,V={mode:O},I=!1===m.motionBlur||null==m.motionBlur?null:new f.MotionBlurEffect(m.motionBlur),j=m.volumetricFog||void 0,N=!1===m.volumetricFog?null:new f.VolumetricFogEffect(void 0,{...f.VOLUMETRIC_FOG_PRESETS.high,maxDistance:64,spatialJitter:!0,scatteringIntensity:Math.PI,...j,temporal:!1!==j?.temporal&&{...f.VOLUMETRIC_FOG_PRESETS.high.temporal,...j?.temporal},blur:!1!==j?.blur&&{...!1===f.VOLUMETRIC_FOG_PRESETS.high.blur?{}:f.VOLUMETRIC_FOG_PRESETS.high.blur,depthAwareUpsample:!0,...j?.blur}}),H=!1===m.colorGrading?null:new f.ColorGradingEffect({enabled:!1,...m.colorGrading??{}}),$=!1===m.depthOfField?null:new f.DepthOfFieldEffect({enabled:!1,...m.depthOfField??{}}),_=!1===m.outline?null:new f.OutlineEffect({enabled:!1,...m.outline??{}}),q=[],z=new WeakMap,J=new Set,K=[],Z=[],Q=(e,t,i)=>{let n=i;const r=q.filter(e=>e.enabled&&e.stage===t).sort((e,t)=>e.priority-t.priority||e.id-t.id);for(const t of r){if(!(t.material instanceof o)){const e=`${t.id}:material`;J.has(e)||(J.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: only NodeShaderMaterial effects are supported.`));continue}try{let i=z.get(t.material);null!=i&&i.version===t.material.version||(i={version:t.material.version,shader:G.compileFullscreen(t.material),diagnosticOrigin:{key:"post-process:"+String(t.material.userData.assetId??(t.material.name||t.material.uuid)),material:{name:t.material.name,uuid:t.material.uuid,version:t.material.version,assetId:t.material.userData.assetId,assetName:t.material.userData.assetName}}},z.set(t.material,i));const r=e.createColorTarget(`hologyCustomPostProcess${t.id}`);e.addNodeFullscreenPass({name:`HologyCustomPostProcess${t.id}`,diagnosticOrigin:i.diagnosticOrigin,shader:i.shader,inputOverrides:{[s]:n},outputs:r}),n=r}catch(e){const i=`${t.id}:compile:${t.material.version}`;J.has(i)||(J.add(i),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: ${e instanceof Error?e.message:String(e)}`,e))}}return n},X={enabled:!0},Y=new f.WebGpuRenderer({canvas:v,fallbackMaterial:S,materialResolver:(e,t)=>G.resolve(e,t),invokeObjectRenderCallbacks:!1,hiZOcclusionCulling:!0,renderGraphProfiling:!1,sampleCount:1,multiDrawIndirect:!1,nativePostSubmit:P?.postSubmit,presentationOverlay:e=>{for(const t of Z)t(e)}});Y.setRenderScale("taa"===O?k?.renderScale??1:1),Y.setRenderGraphBuilder((e,t)=>{const i=new f.FrameGraphBuilder(t),n=i.createColorTarget("hologyNormalRoughness",{format:"rgba8unorm"}),r=C?i.createColorTarget("hologyMotionVectors",{format:"rgba16float"}):null;for(const e of K)"beforeScene"===e.stage&&e(i,i.sceneColor);X.enabled&&i.addDirectionalShadowPass(),i.addPointShadowPass(),i.addSpotShadowPass(),i.addDepthPrepass(),i.addHiZPasses(),i.addVisibilityPass(),i.addMaterialPass({name:"OpaqueGBufferPass",outputs:null==r?[i.sceneColor,n]:[i.sceneColor,n,r],drawStage:"opaque",loadDepth:!0}),i.addHiZHistoryPass("OpaqueGBufferPass");let a=i.sceneColor;if(T?.enabled){const e=T.addPasses(i,{depth:i.mainDepth,normal:n,velocity:r??void 0});a=T.addCompositePass(i,a,e)}null!=A&&(a=A.addPasses(i,{sceneColor:a,depth:i.mainDepth,normalRoughness:n}));const o=new Set(K.flatMap(e=>e.getSceneTextureReads?.()??[]));i.addSceneTextureCopyPass(a,{sceneColor:o.has("sceneColorSnapshot"),sceneDepth:o.has("sceneDepthSnapshot")||q.some(e=>e.enabled&&null!=e.material.uniforms[l])}),i.addLatePass(a);for(const e of K)null!=e.stage&&"afterScene"!==e.stage||e(i,a);a=Q(i,"beforeFog",a),null!=N&&(a=N.addPasses(i,{sceneColor:a,depth:i.mainDepth,velocity:r??void 0,volumeObjects:t.fogVolumeObjects,lights:t.extractedLights})),null!=I&&null!=r&&(a=I.addPass(i,a,r,i.mainDepth)),null!=B&&(a=B.addPass(i,a)),a=Q(i,"beforeOutline",a),null!=_&&(a=_.addPass(i,a)),a=Q(i,"beforeDepthOfField",a),null!=$&&(a=$.addPass(i,a,i.mainDepth)),a=Q(i,"beforeColorAdjustment",a),null!=H&&(a=H.addPass(i,a)),a=Q(i,"beforeAntiAliasing",a);let s="taa"===V.mode&&null!=k?k.addPass(i,a,i.mainDepth,r??void 0):a;"smaa"===V.mode&&null!=W?s=W.addPass(i,s):"fxaa"===V.mode&&null!=U&&(s=U.addPass(i,s)),s=Q(i,"beforeOutput",s);for(const e of K)"beforePresent"===e.stage&&e(i,s);!0===P?.enabled&&null!=r?P.addInputPass(i,s,r):i.present(s)});try{return await Y.initialize(g),L=new ExperimentalWebGpuBackend(Y,S,G,R,B,U,W,T,A,k,I,N,H,$,_,q,K,Z,V,X,P,v),L}catch(e){throw Y.destroy(),S.dispose(),G.dispose(),R.dispose(),T?.dispose(),W?.dispose(),I?.dispose(),N?.dispose(),_?.dispose(),e}}static supportsCamera(t){return t instanceof e.PerspectiveCamera||t instanceof e.OrthographicCamera}setSize(e,t,i,n=1){const r=this.canvas.width,a=this.canvas.height;let o=Math.min(1,Math.max(.25,n));if(!0===this.nativeDlss?.enabled){const n=Math.max(1,Math.floor(e*i)),r=Math.max(1,Math.floor(t*i));o=this.nativeDlss.getRenderScale(n,r)}const s=o!==this.renderScale;this.renderScale=o,this.renderer.setRenderScale(o),this.taa?.setRenderScale(o),this.renderer.setSize(e,t,i),(s||this.canvas.width!==r||this.canvas.height!==a)&&this.resetViewHistory()}initTexture(e){this.renderer.initTexture(e)}setPostProcessEffects(e){this.postProcessEffects.splice(0,this.postProcessEffects.length,...e);for(const t of e){if("beforeLut"!==t.stage)continue;const e=`${t.id}:${t.stage}`;this.warnedUnsupportedPostProcessStages.has(e)||(this.warnedUnsupportedPostProcessStages.add(e),console.warn(`[Hology WebGPU experiment] Skipping custom post-process effect ${t.id}: stage "${t.stage}" has no native WebGPU anchor.`))}}getDevice(){return this.renderer.getDevice()}createSceneCapture(e,t,i){return this.renderer.createSceneCapture(e,t,i)}setRenderGraphExtensions(e){this.renderGraphExtensions.length=0;for(const t of e)this.renderGraphExtensions.push(t)}setPresentationExtensions(e){this.presentationExtensions.length=0;for(const t of e)this.presentationExtensions.push(t)}setEnableOutlines(e){null!=this.outline&&(this.outline.enabled=e)}setTiledLightingEnabled(e){this.renderer.setTiledLightingEnabled(e)}setDynamicBatchingEnabled(e){this.renderer.setDynamicBatchingEnabled(e)}setSelectedObjects(e){this.outline?.setSelectedObjects(e)}setSelectedObjectInstances(e){this.outline?.setSelectedInstances(e)}setCascadedShadowRanges(e,t=[]){this.renderer.setCascadedShadowRanges(e,t),this.volumetricFog?.setCascadedDirectionalLights(t)}setDirectionalShadowUpdateOptions(e){this.renderer.setDirectionalShadowUpdateOptions(e)}invalidateDirectionalShadows(){this.renderer.invalidateDirectionalShadows()}setDirectionalShadowOptions(e,t){this.directionalShadowState.enabled=e,this.renderer.setDirectionalShadowsEnabled(e),this.renderer.setDirectionalShadowMapSize(t)}setWorldEnvironment(e){if(null==e)return void this.nodeMaterialResolver.setWorldEnvironment(null);const t=this.getEnvironmentTexture(e.source);this.nodeMaterialResolver.setWorldEnvironment({texture:t,intensity:e.intensity})}getEnvironmentTexture(t){if(t.mapping===e.CubeUVReflectionMapping)return t;let i=this.pmremResults.get(t);return null==i&&(this.pmremGenerator??(this.pmremGenerator=this.renderer.createPMREMGenerator()),i=this.pmremGenerator.fromEquirectangular(t),this.pmremResults.set(t,i),this.ownedPmremResults.add(i)),i.texture}resetViewHistory(){this.renderer.resetViewHistory(),this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.nativeDlss?.reset()}async compile(e,t){if(!this.secondaryMotionPrepared){let t=!1;e.traverse(e=>{const i=e.userData.secondaryMotion?.regions;Array.isArray(i)&&i.some(e=>e.enabled)&&(t=!0)});const i=this.renderer.getDevice();if(t&&i){const{prepareSecondaryMotionRuntime:e}=await import("../secondary-motion/runtime.js");e(i),this.secondaryMotionPrepared=!0}}await this.renderer.compileAsync(e,t)}createStaticDrawSet(e,t,i=!1,n="skip"){this.renderer.setHiZOcclusionCullingEnabled(!0);const r=this.renderer.createStaticDrawSet(e,{label:t,onUnsupported:n,allowUnsortedLateDraws:i});return 0===r.drawCount?(r.dispose(),null):r}registerStaticSpatialObject(e){return this.renderer.registerStaticSpatialObject(e)}render(e,t,i){const n="taa"===this.antiAliasingState.mode?this.taa:null;this.volumetricFog?.setScene(e),this.renderer.setMotionVectorProjection(t.projectionMatrix),this.motionBlur?.prepareCamera(t,this.canvas.width,this.canvas.height,i),this.motionBlur?.requiresRendererHistoryReset()&&(this.renderer.resetViewHistory(),this.gtao?.reset(),this.volumetricFog?.reset()),n?.prepareCamera(t,this.canvas.width,this.canvas.height),this.nativeDlss?.prepareFrame(t);const r=!0===this.nativeDlss?.enabled?this.nativeDlss.jitter:null;this.motionBlur?.setJitterUv(n?.currentJitterUv.x??(null==r?0:r.x/Math.max(1,this.canvas.width*this.renderScale)),n?.currentJitterUv.y??(null==r?0:-r.y/Math.max(1,this.canvas.height*this.renderScale))),null!=r&&this.renderer.setProjectionJitter(r.x,r.y);let a=!1;try{this.renderer.render(e,t,i),a=!0}finally{null!=r&&this.renderer.clearProjectionJitter(),n?.finishCamera(t),a&&this.motionBlur?.commitCamera(),a&&this.nativeDlss?.finishFrame(t)}}setMotionBlurOptions(e){null!=this.motionBlur&&Object.assign(this.motionBlur.options,e)}setGTAOOptions(e){this.gtao?.setOptions(e)}setAntiAliasingMode(e){e!==this.antiAliasingState.mode&&("taa"===e&&null==this.taa||"smaa"===e&&null==this.smaa||"fxaa"===e&&null==this.fxaa?console.warn(`[Hology WebGPU experiment] Anti-aliasing mode "${e}" was not initialized. Set webgpuPostProcessing.antiAliasing in the initial rendering configuration to enable runtime switching.`):(this.antiAliasingState.mode=e,this.resetTemporalHistory()))}setGTAOQuality(e){this.gtao?.applyPreset(e)}setVolumetricFogOptions(e){this.volumetricFog?.setOptions(e)}setVolumetricFogQuality(e){this.volumetricFog?.applyPreset(e)}pushMotionBlurOverride(e){return this.motionBlur?.pushOverride(e)??null}invalidateObjectMotion(e){this.renderer.invalidateObjectMotion(e)}getLastFrameProfile(){return this.renderer.getLastFrameProfile()}setPostProcessState(e){null!=this.colorGrading&&(Object.assign(this.colorGrading.options,e??{enabled:!1}),this.colorGrading.options.enabled=!0===e?.enabled),null!=this.depthOfField&&(this.depthOfField.options.enabled=null!=e?.depthFocus||null!=e?.depthAperture||null!=e?.depthMaxBlur,this.depthOfField.options.focus=e?.depthFocus,this.depthOfField.options.aperture=e?.depthAperture,this.depthOfField.options.maxBlur=e?.depthMaxBlur)}setProfilingEnabled(e){this.renderer.setRenderGraphProfilingEnabled(e)}resetTemporalHistory(){this.taa?.reset(),this.motionBlur?.reset(),this.gtao?.reset(),this.volumetricFog?.reset(),this.renderer.resetViewHistory(),this.nativeDlss?.reset()}inspect(e,t){return inspectWebGpuScene(e,t,this.nodeMaterialResolver)}destroy(){this.nativeDlss?.dispose(),this.nodeMaterialResolver.dispose(),this.gBufferFallbackSource.dispose(),this.gtao?.dispose(),this.smaa?.dispose(),this.motionBlur?.dispose(),this.volumetricFog?.dispose();for(const e of this.ownedPmremResults)e.dispose();this.ownedPmremResults.clear(),this.renderer.destroy(),this.fallbackMaterial.dispose()}}export function inspectWebGpuScene(e,t,i){const n={meshes:0,skinnedMeshes:0,instancedMeshes:0,batchedMeshes:0,sprites:0,points:0,lines:0,missingPositionGeometry:0,transparentMaterials:0,shaderMaterialsReplaced:0,materialsReplaced:0,unsupportedCamera:ExperimentalWebGpuBackend.supportsCamera(t)?0:1};return e.traverse(e=>{if(e.isSprite)return void n.sprites++;if(e.isPoints)return void n.points++;if(e.isLine)return void n.lines++;if(!e.isMesh)return;const t=e;t.isBatchedMesh?n.batchedMeshes++:t.isInstancedMesh?n.instancedMeshes++:t.isSkinnedMesh?n.skinnedMeshes++:n.meshes++,null==t.geometry?.getAttribute("position")&&n.missingPositionGeometry++;const r=Array.isArray(t.material)?t.material:[t.material];for(const e of r){if(null==e)continue;e.transparent&&n.transparentMaterials++;const t=!0===e.isWGSLShaderMaterial||!0===e.isLineMaterial,r=!t&&!0===i?.canResolve(e);t||r||(n.materialsReplaced++,e.isShaderMaterial&&n.shaderMaterialsReplaced++)}}),n}export function formatWebGpuSceneCapabilitySummary(e){return`[Hology WebGPU experiment] ${JSON.stringify(e)}`}const u="\nstruct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) uv: vec2<f32>,\n @location(3) color: vec4<f32>,\n#ifdef USE_SKINNING\n @location(4) skinIndex: vec4<u32>,\n @location(5) skinWeight: vec4<f32>,\n#endif\n @builtin(instance_index) instanceIndex: u32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\n@vertex\nfn vsMain(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n#ifdef USE_SKINNING\n let localPosition = rendererSkinPosition(input.position, input.skinIndex, input.skinWeight);\n let localNormal = rendererSkinNormal(input.normal, input.skinIndex, input.skinWeight);\n#else\n let localPosition = input.position;\n let localNormal = input.normal;\n#endif\n let world = rendererWorldPosition(localPosition, input.instanceIndex);\n output.position = rendererClipPosition(localPosition, input.instanceIndex);\n output.worldPosition = world.xyz;\n output.worldNormal = rendererWorldNormal(localNormal, input.instanceIndex);\n output.color = input.color * rendererObjectColor(input.instanceIndex);\n return output;\n}\n",p="\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPosition: vec3<f32>,\n @location(1) worldNormal: vec3<f32>,\n @location(2) color: vec4<f32>,\n};\n\nfn distanceAttenuation(distanceToLight: f32, cutoffDistance: f32, decayExponent: f32) -> f32 {\n var distanceFalloff = 1.0 / max(pow(distanceToLight, decayExponent), 0.01);\n if (cutoffDistance > 0.0) {\n let ratio = distanceToLight / cutoffDistance;\n let cutoff = clamp(1.0 - ratio * ratio * ratio * ratio, 0.0, 1.0);\n distanceFalloff *= cutoff * cutoff;\n }\n return distanceFalloff;\n}\n\n@fragment\nfn fsMain(input: VertexOutput) -> @location(0) vec4<f32> {\n let normal = normalize(input.worldNormal);\n let normalTint = normal * 0.5 + vec3<f32>(0.5);\n let base = mix(vec3<f32>(0.52, 0.58, 0.64), normalTint, 0.22) * input.color.rgb;\n var lighting = rendererIndirectDiffuse(normal) + vec3<f32>(0.08);\n var directionalLighting = vec3<f32>(0.0);\n let directionalCount = rendererDirectionalLightCount();\n\n for (var index: u32 = 0u; index < directionalCount; index = index + 1u) {\n let lightDirection = rendererDirectionalLightDirectionForLight(index);\n let shadow = rendererSampleDirectionalShadowForLightWithNormal(index, input.worldPosition, normal);\n directionalLighting += rendererDirectionalLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * shadow;\n }\n if (directionalCount > 0u) {\n lighting += directionalLighting / f32(directionalCount);\n }\n\n for (var index: u32 = 0u; index < rendererPointLightCount(); index = index + 1u) {\n let lightVector = rendererPointLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let shadow = rendererSamplePointShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererPointLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * distanceAttenuation(distanceToLight, rendererPointLightRangeForLight(index), rendererPointLightDecayForLight(index)) * shadow;\n }\n\n for (var index: u32 = 0u; index < rendererSpotLightCount(); index = index + 1u) {\n let lightVector = rendererSpotLightPositionForLight(index) - input.worldPosition;\n let distanceToLight = length(lightVector);\n let lightDirection = normalize(lightVector);\n let angleCos = dot(-lightDirection, rendererSpotLightDirectionForLight(index));\n let cone = smoothstep(rendererSpotLightConeCosForLight(index), rendererSpotLightPenumbraCosForLight(index), angleCos);\n let shadow = rendererSampleSpotShadowForLightWithNormal(index, input.worldPosition, normal);\n lighting += rendererSpotLightColorForLight(index) * max(dot(normal, lightDirection), 0.0) * cone * distanceAttenuation(distanceToLight, rendererSpotLightRangeForLight(index), rendererSpotLightDecayForLight(index)) * shadow;\n }\n\n return vec4<f32>(base * max(lighting, vec3<f32>(0.08)), input.color.a);\n}\n";/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
package/dist/rendering.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { Camera, Object3D, WebGLRenderer, WebGLRenderTarget, Texture } from 'thr
|
|
|
7
7
|
import { ShaderPass } from "three-stdlib";
|
|
8
8
|
import { IRgbNode, RgbaNode } from 'three-shader-graph';
|
|
9
9
|
import { CSM } from "three/examples/jsm/csm/CSM.js";
|
|
10
|
+
import { type RenderingStatsStyle } from './utils/three/frame-stats.js';
|
|
11
|
+
export type { RenderingStatsStyle } from './utils/three/frame-stats.js';
|
|
10
12
|
import { GTAOPass } from "three/examples/jsm/postprocessing/GTAOPass.js";
|
|
11
13
|
import { OutlinePass } from './utils/three/outline-pass.js';
|
|
12
14
|
import { type PostProcessSettings, type PostProcessVolume } from "./gameplay/actors/builtin/post-process-volume-actor.js";
|
|
@@ -16,13 +18,13 @@ import { Cluster } from "./rendering/cluster-generator.js";
|
|
|
16
18
|
import { LightVolume } from "./rendering/light-probes/light-volume-capture.js";
|
|
17
19
|
import { type PostProcessMaterialSource } from "./shader/post-process-shader.js";
|
|
18
20
|
import { type UpscalingOptions } from "./rendering/upscaling-pass.js";
|
|
19
|
-
import { type AntiAliasingMode, type ExperimentalWebGpuPostProcessingOptions, type GTAOOptions, type GTAOQuality, type MotionBlurOptions, type MotionBlurOverride, type MotionBlurOverrideHandle, type RendererFrameProfile, type ExperimentalWebGpuRenderGraphExtension, type WebGpuPresentationExtension, type VolumetricFogOptions, type VolumetricFogQuality } from './rendering/webgpu-experimental-backend.js';
|
|
21
|
+
import { type AntiAliasingMode, type ExperimentalWebGpuPostProcessingOptions, type GTAOOptions, type GTAOQuality, type MotionBlurOptions, type MotionBlurOverride, type MotionBlurOverrideHandle, type RendererFrameProfile, type ExperimentalWebGpuRenderGraphExtension, type WebGpuPresentationExtension, type RendererSceneCapture, type VolumetricFogOptions, type VolumetricFogQuality } from './rendering/webgpu-experimental-backend.js';
|
|
20
22
|
import type { WorldEnvironmentState } from './rendering/environment.js';
|
|
21
23
|
import type { VfxBackendPreference } from './effects/vfx/gpu-sprite-compiler.js';
|
|
22
24
|
import { type GraphicsRuntime } from './rendering/graphics-runtime.js';
|
|
23
25
|
export { GraphicsRuntime } from './rendering/graphics-runtime.js';
|
|
24
26
|
export type { UpscalingOptions } from "./rendering/upscaling-pass.js";
|
|
25
|
-
export type { AntiAliasingMode, ExperimentalWebGpuPostProcessingOptions, ExperimentalWebGpuRenderGraphExtension, WebGpuPresentationExtension, WebGpuPresentationExtensionContext } from './rendering/webgpu-experimental-backend.js';
|
|
27
|
+
export type { AntiAliasingMode, ExperimentalWebGpuPostProcessingOptions, ExperimentalWebGpuRenderGraphExtension, WebGpuPresentationExtension, WebGpuPresentationExtensionContext, RendererSceneCapture, RendererSceneCaptureOptions, RendererSceneCapturePostProcessContext } from './rendering/webgpu-experimental-backend.js';
|
|
26
28
|
export type { GTAOOptions, GTAOQuality, MotionBlurOptions, MotionBlurOverride, MotionBlurOverrideHandle, VolumetricFogOptions, VolumetricFogQuality } from './rendering/webgpu-experimental-backend.js';
|
|
27
29
|
/** Renderer requested by a view. `webgpu-experimental` is a deprecated alias. */
|
|
28
30
|
export type RenderingBackend = 'webgl' | 'webgpu' | 'webgpu-experimental';
|
|
@@ -72,6 +74,8 @@ export type DynamicResolutionOptions = {
|
|
|
72
74
|
export type RenderingViewOptions = {
|
|
73
75
|
/** Shared device/backend/cache owner. Views in one application should use the same instance. */
|
|
74
76
|
graphicsRuntime?: GraphicsRuntime;
|
|
77
|
+
/** Defaults to detailed. Simple shows FPS/frame interval without enabling GPU profiling. */
|
|
78
|
+
statsStyle?: RenderingStatsStyle;
|
|
75
79
|
/** Retain an unused WebGPU backend briefly for fast scene tab reopening. Defaults to 0. */
|
|
76
80
|
webGpuBackendIdleRetentionMs?: number;
|
|
77
81
|
backend?: RenderingBackend;
|
|
@@ -147,6 +151,10 @@ export declare class RenderingView {
|
|
|
147
151
|
private outlinesEnabled;
|
|
148
152
|
private selectedOutlineObjects;
|
|
149
153
|
private experimentalStaticDrawSetRegistrations;
|
|
154
|
+
private readonly staticSpatialObjects;
|
|
155
|
+
/** Register a static render subtree while preserving authored object identity. */
|
|
156
|
+
registerStaticSpatialObject(root: THREE.Object3D): () => void;
|
|
157
|
+
refreshStaticSpatialObjects(root: THREE.Object3D, editing?: boolean): void;
|
|
150
158
|
private experimentalWebGpuRenderGraphExtensions;
|
|
151
159
|
private webGpuPresentationExtensions;
|
|
152
160
|
private worldEnvironment;
|
|
@@ -320,6 +328,8 @@ export declare class RenderingView {
|
|
|
320
328
|
setEnableOutlines(enabled: boolean): void;
|
|
321
329
|
registerWebGpuPresentationExtension(extension: WebGpuPresentationExtension): () => void;
|
|
322
330
|
get sharedGraphicsRuntime(): GraphicsRuntime;
|
|
331
|
+
/** Independent camera capture. Pass null for a persistent sampleable texture output. */
|
|
332
|
+
createSceneCapture(canvas: HTMLCanvasElement | null, width?: number, height?: number): RendererSceneCapture;
|
|
323
333
|
setCamera(camera: Camera): void;
|
|
324
334
|
setSelectedObjects(obj: Object3D[]): void;
|
|
325
335
|
setExperimentalWebGpuTiledLightingEnabled(enabled: boolean): void;
|
|
@@ -372,12 +382,17 @@ export declare class RenderingView {
|
|
|
372
382
|
removeOnLoop(onFrame: (deltaTime: number) => any): void;
|
|
373
383
|
private stats;
|
|
374
384
|
private readonly webGpuPassStatsDom;
|
|
385
|
+
private readonly webGpuResolutionStatsDom;
|
|
375
386
|
private readonly webGpuVisibilityStatsDom;
|
|
376
387
|
private webGpuPassStatsRows;
|
|
377
388
|
private _showStats;
|
|
378
389
|
private _profilingEnabled;
|
|
379
390
|
set showStats(value: boolean);
|
|
380
391
|
get showStats(): boolean;
|
|
392
|
+
/** Simple is intended for players; detailed retains engine diagnostics and GPU timings. */
|
|
393
|
+
set statsStyle(value: RenderingStatsStyle);
|
|
394
|
+
get statsStyle(): RenderingStatsStyle;
|
|
395
|
+
private get detailedStatsEnabled();
|
|
381
396
|
/** Latest renderer profile. Profiling data is only collected when explicitly enabled. */
|
|
382
397
|
getLastFrameProfile(): RendererFrameProfile | null;
|
|
383
398
|
/** Collect renderer timings without showing the built-in renderer panels. */
|