babylonjs-editor-tools 5.5.0 → 5.5.1-alpha.0
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/build/index.node.js +2330 -1
- package/build/src/index.js +4 -0
- package/build/src/index.js.map +1 -1
- package/build/src/loading/loader.js +7 -2
- package/build/src/loading/loader.js.map +1 -1
- package/build/src/loading/mesh.js +22 -0
- package/build/src/loading/mesh.js.map +1 -0
- package/build/src/loading/rendering.js +4 -0
- package/build/src/loading/rendering.js.map +1 -1
- package/build/src/loading/transform-node.js +4 -1
- package/build/src/loading/transform-node.js.map +1 -1
- package/build/src/rendering/tools.js +7 -0
- package/build/src/rendering/tools.js.map +1 -1
- package/build/src/rendering/volumetric/pipeline.js +915 -0
- package/build/src/rendering/volumetric/pipeline.js.map +1 -0
- package/build/src/rendering/volumetric/selector.js +525 -0
- package/build/src/rendering/volumetric/selector.js.map +1 -0
- package/build/src/rendering/volumetric/shaders-wgsl.js +1207 -0
- package/build/src/rendering/volumetric/shaders-wgsl.js.map +1 -0
- package/build/src/rendering/volumetric/shaders.js +1293 -0
- package/build/src/rendering/volumetric/shaders.js.map +1 -0
- package/build/src/rendering/volumetric/types.js +301 -0
- package/build/src/rendering/volumetric/types.js.map +1 -0
- package/build/src/rendering/volumetric-lighting.js +72 -0
- package/build/src/rendering/volumetric-lighting.js.map +1 -0
- package/build/src/tools/guards.js +14 -0
- package/build/src/tools/guards.js.map +1 -1
- package/declaration/src/index.d.ts +4 -0
- package/declaration/src/loading/mesh.d.ts +1 -0
- package/declaration/src/rendering/tools.d.ts +1 -0
- package/declaration/src/rendering/volumetric/pipeline.d.ts +231 -0
- package/declaration/src/rendering/volumetric/selector.d.ts +263 -0
- package/declaration/src/rendering/volumetric/shaders-wgsl.d.ts +21 -0
- package/declaration/src/rendering/volumetric/shaders.d.ts +60 -0
- package/declaration/src/rendering/volumetric/types.d.ts +362 -0
- package/declaration/src/rendering/volumetric-lighting.d.ts +28 -0
- package/declaration/src/tools/guards.d.ts +12 -0
- package/package.json +1 -1
package/build/index.node.js
CHANGED
|
@@ -1 +1,2330 @@
|
|
|
1
|
-
var Pe=Object.defineProperty;var In=Object.getOwnPropertyDescriptor;var En=Object.getOwnPropertyNames;var Tn=Object.prototype.hasOwnProperty;var i=(e,r)=>Pe(e,"name",{value:r,configurable:!0});var On=(e,r)=>{for(var t in r)Pe(e,t,{get:r[t],enumerable:!0})},Dn=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of En(r))!Tn.call(e,o)&&o!==t&&Pe(e,o,{get:()=>r[o],enumerable:!(n=In(r,o))||n.enumerable});return e};var Mn=e=>Dn(Pe({},"__esModule",{value:!0}),e);var $o={};On($o,{AdvancedAssetContainer:()=>de,AdvancedAssetContainerInstantiatedEntries:()=>ue,Cinematic:()=>Se,Database:()=>be,NodeParticleSystemSet:()=>dn.NodeParticleSystemSet,_applyScriptsForObject:()=>F,_getKtx2TextureName:()=>Oe,_preloadScriptsAssets:()=>xt,_registerScriptInstance:()=>Ct,_removeRegisteredScriptInstance:()=>Ie,addExcludedCompressedTexture:()=>De,animationFromSprite:()=>Fo,animationGroupFromScene:()=>fo,applyMeshesLODQuality:()=>ze,applyRenderingConfigurationForCamera:()=>mt,applyScriptOnObject:()=>ro,applyShadowsQuality:()=>kn,applyTexturesQuality:()=>io,componentFromScene:()=>mo,configureEngineToUseCompressedTextures:()=>oo,configureMeshDistanceOrScreenCoverage:()=>ke,configureShadowMapRefreshRate:()=>ve,configureShadowMapRenderListPredicate:()=>$e,copyAndParseRagdollConfiguration:()=>ft,createAndOpenDatabase:()=>_t,createDefaultRenderingPipeline:()=>nr,createMotionBlurPostProcess:()=>Zt,createSSAO2RenderingPipeline:()=>qt,createSSRRenderingPipeline:()=>Qt,createTAARenderingPipeline:()=>Yt,createVLSPostProcess:()=>jt,defaultPipelineCameraConfigurations:()=>Z,disposeDefaultRenderingPipeline:()=>lt,disposeMotionBlurPostProcess:()=>ot,disposeSSAO2RenderingPipeline:()=>et,disposeSSRRenderingPipeline:()=>Ye,disposeTAARenderingPipeline:()=>Je,disposeVLSPostProcess:()=>Ue,forceCompileAllSceneMaterials:()=>co,generateCinematicAnimationGroup:()=>Bo,getAllScriptsByClassForObject:()=>ne,getAnimationTypeForObject:()=>ye,getDefaultRenderingPipeline:()=>pe,getFromIndexDB:()=>he,getMotionBlurPostProcess:()=>nt,getPowerOfTwoUntil:()=>M,getSSAO2RenderingPipeline:()=>Wn,getSSRRenderingPipeline:()=>$n,getScriptByClassForObject:()=>vt,getTAARenderingPipeline:()=>Un,getTextureUrl:()=>Me,getVLSPostProcess:()=>je,guiFromAsset:()=>yo,isAbstractMesh:()=>$,isAnyParticleSystem:()=>Ve,isArcRotateCamera:()=>Rn,isBone:()=>wn,isCamera:()=>xe,isCinematicGroup:()=>Lo,isCinematicKey:()=>Ft,isCinematicKeyCut:()=>ie,isCinematicKeyEvent:()=>_o,isCinematicSound:()=>Vo,isClusteredLightContainer:()=>Ae,isDecalMesh:()=>Bt,isDirectionalLight:()=>Ln,isFreeCamera:()=>Fn,isGPUParticleSystem:()=>Gn,isGaussianSplattingMesh:()=>Ge,isGroundMesh:()=>Nn,isHemisphericLight:()=>Bn,isInstancedMesh:()=>le,isLight:()=>Vt,isMesh:()=>D,isNode:()=>Q,isNodeFromStaticGroup:()=>Ke,isParticleSystem:()=>Le,isPointLight:()=>_n,isScene:()=>_e,isSoundNode:()=>j,isSpotLight:()=>Vn,isSprite:()=>Be,isTexture:()=>ce,isTransformNode:()=>k,isUsingKtx2CompressedTextures:()=>ge,loadMaterialFromFile:()=>lo,loadScene:()=>ao,motionBlurPostProcessCameraConfigurations:()=>J,nodeFromDescendants:()=>uo,nodeFromScene:()=>po,normalizeAtlasJson:()=>Tt,onKeyboardEvent:()=>wo,onPointerEvent:()=>Mo,openIndexDB:()=>Rt,parseCinematic:()=>Ro,parseCinematicKeyValue:()=>_,parseDefaultRenderingPipeline:()=>pt,parseKeyFrameAnimations:()=>wt,parseMotionBlurPostProcess:()=>st,parseRagdollConfiguration:()=>cr,parseSSAO2RenderingPipeline:()=>rt,parseSSRRenderingPipeline:()=>qe,parseTAARenderingPipeline:()=>Xe,parseVLSPostProcess:()=>We,particleSystemFromScene:()=>ho,playSpriteAnimationFromName:()=>so,preloadAssetsToDatabase:()=>zo,putInIndexDB:()=>V,registerScriptAssetParser:()=>to,saveRenderingConfigurationForCamera:()=>Jn,sceneAsset:()=>go,scriptAssetsCache:()=>O,scriptAssetsParsers:()=>fe,scriptsDictionary:()=>R,serializeDefaultRenderingPipeline:()=>ct,serializeMotionBlurPostProcess:()=>it,serializeSSAO2RenderingPipeline:()=>tt,serializeSSRRenderingPipeline:()=>He,serializeTAARenderingPipeline:()=>Ze,serializeVLSPostProcess:()=>Qe,setDefaultRenderingPipelineRef:()=>qn,setMotionBlurPostProcessRef:()=>Hn,setSSAO2RenderingPipelineRef:()=>Yn,setSSRRenderingPipelineRef:()=>jn,setStaticDecalsEnabled:()=>Kn,setTAARenderingPipelineRef:()=>Qn,setUseKtx2CompressedTextures:()=>no,setVLSPostProcessRef:()=>zn,setupOfflineProvider:()=>Go,soundFromScene:()=>So,spriteFromSpriteManager:()=>No,ssaoRenderingPipelineCameraConfigurations:()=>q,ssrRenderingPipelineCameraConfigurations:()=>Y,taaRenderingPipelineCameraConfigurations:()=>H,visibleAsAsset:()=>Do,visibleAsBoolean:()=>bo,visibleAsColor3:()=>Co,visibleAsColor4:()=>Io,visibleAsEntity:()=>Eo,visibleAsKeyMap:()=>Oo,visibleAsNumber:()=>xo,visibleAsString:()=>Po,visibleAsTexture:()=>To,visibleAsVector2:()=>Ao,visibleAsVector3:()=>vo,vlsPostProcessCameraConfigurations:()=>W});module.exports=Mn($o);function $(e){switch(e.getClassName?.()){case"Mesh":case"LineMesh":case"GroundMesh":case"InstancedMesh":return!0}return!1}i($,"isAbstractMesh");function D(e){switch(e.getClassName?.()){case"Mesh":case"GroundMesh":return!0}return!1}i(D,"isMesh");function le(e){return e.getClassName?.()==="InstancedMesh"}i(le,"isInstancedMesh");function wn(e){return e.getClassName?.()==="Bone"}i(wn,"isBone");function Nn(e){return e.getClassName?.()==="GroundMesh"}i(Nn,"isGroundMesh");function k(e){return e.getClassName?.()==="TransformNode"}i(k,"isTransformNode");function ce(e){return e?.getClassName?.()==="Texture"}i(ce,"isTexture");function xe(e){switch(e.getClassName?.()){case"Camera":case"FreeCamera":case"TargetCamera":case"EditorCamera":case"ArcRotateCamera":case"UniversalCamera":return!0}return!1}i(xe,"isCamera");function Fn(e){switch(e.getClassName?.()){case"FreeCamera":case"UniversalCamera":return!0}return!1}i(Fn,"isFreeCamera");function Rn(e){return e.getClassName?.()==="ArcRotateCamera"}i(Rn,"isArcRotateCamera");function _n(e){return e.getClassName?.()==="PointLight"}i(_n,"isPointLight");function Ln(e){return e.getClassName?.()==="DirectionalLight"}i(Ln,"isDirectionalLight");function Vn(e){return e.getClassName?.()==="SpotLight"}i(Vn,"isSpotLight");function Bn(e){return e.getClassName?.()==="HemisphericLight"}i(Bn,"isHemisphericLight");function Vt(e){switch(e.getClassName?.()){case"Light":case"PointLight":case"SpotLight":case"DirectionalLight":case"HemisphericLight":return!0}return!1}i(Vt,"isLight");function Ae(e){return e.getClassName?.()==="ClusteredLightContainer"}i(Ae,"isClusteredLightContainer");function Q(e){return $(e)||k(e)||Vt(e)||xe(e)}i(Q,"isNode");function _e(e){return e.getClassName?.()==="Scene"}i(_e,"isScene");function Le(e){return e.getClassName?.()==="ParticleSystem"}i(Le,"isParticleSystem");function Gn(e){return e.getClassName?.()==="GPUParticleSystem"}i(Gn,"isGPUParticleSystem");function Ve(e){switch(e.getClassName?.()){case"ParticleSystem":case"GPUParticleSystem":return!0}return!1}i(Ve,"isAnyParticleSystem");function Be(e){return e.getClassName?.()==="Sprite"}i(Be,"isSprite");function j(e){return e.getClassName?.()==="SoundNode"}i(j,"isSoundNode");function Ge(e){return e.getClassName?.()==="GaussianSplattingMesh"}i(Ge,"isGaussianSplattingMesh");function Ke(e){let r=e;for(;r;){if(r.metadata?.isStaticGroup)return!0;r=r.parent}return!1}i(Ke,"isNodeFromStaticGroup");function ke(e){e.meshes.forEach(r=>{D(r)&&r.getLODLevels().forEach(t=>{t.mesh&&(t.mesh.originalDistanceOrScreenCoverage=t.distanceOrScreenCoverage)})})}i(ke,"configureMeshDistanceOrScreenCoverage");function ze(e,r){r.meshes.forEach(t=>{D(t)&&t.getLODLevels().forEach(n=>{if(n.mesh?.originalDistanceOrScreenCoverage)switch(e){case"very-low":n.distanceOrScreenCoverage=n.mesh.originalDistanceOrScreenCoverage*.125;break;case"low":n.distanceOrScreenCoverage=n.mesh.originalDistanceOrScreenCoverage*.25;break;case"medium":n.distanceOrScreenCoverage=n.mesh.originalDistanceOrScreenCoverage*.5;break;case"high":n.distanceOrScreenCoverage=n.mesh.originalDistanceOrScreenCoverage;break}})})}i(ze,"applyMeshesLODQuality");function Bt(e){return(e.metadata?.decal??null)!==null}i(Bt,"isDecalMesh");function Kn(e,r){r.meshes.forEach(t=>{Bt(t)&&Ke(t)&&t.setEnabled(e)})}i(Kn,"setStaticDecalsEnabled");function M(e){let r=1;for(;r<=e;)r<<=1;return r>>1}i(M,"getPowerOfTwoUntil");var Gt=require("babylonjs"),Kt=require("babylonjs");function $e(e){e.lights.forEach(r=>{let t=r.getShadowGenerator()?.getShadowMap();t&&(t.renderListPredicate=n=>Ge(n)?!1:Gt.Vector3.Distance(n.getAbsolutePosition(),r.getAbsolutePosition())<=r.range)})}i($e,"configureShadowMapRenderListPredicate");async function ve(e){e.executeWhenReady(()=>{e.lights.forEach(r=>{let t=r.getShadowGenerator()?.getShadowMap();t&&(t.refreshRate=r.metadata?.refreshRate??Kt.RenderTargetTexture.REFRESHRATE_RENDER_ONEVERYFRAME)})})}i(ve,"configureShadowMapRefreshRate");function kn(e,r){r.lights.forEach(t=>{let n=t.getShadowGenerator(),o=n?.getShadowMap();if(n?.originalMapSize){let s=n.originalMapSize;switch(e){case"medium":s=s*.5;break;case"low":s=s*.25;break;case"very-low":s=s*.125;break}s=Math.max(128,M(s)),o?.getSize().width!==s&&o.resize(s)}}),ve(r)}i(kn,"applyShadowsQuality");var kt=require("babylonjs"),zt=require("babylonjs"),$t=require("babylonjs"),I=null,W=new Map;function je(){return I}i(je,"getVLSPostProcess");function zn(e){I=e}i(zn,"setVLSPostProcessRef");function Ue(e){I&&e.activeCamera&&(I.dispose(e.activeCamera),I=null)}i(Ue,"disposeVLSPostProcess");function jt(e,r){return r??=e.meshes.find(t=>D(t)),I=new $t.VolumetricLightScatteringPostProcess("VolumetricLightScatteringPostProcess",1,e.activeCamera,r,100,zt.Texture.BILINEAR_SAMPLINGMODE,e.getEngine(),!1),I}i(jt,"createVLSPostProcess");function Qe(){return I?{meshId:I.mesh?.id,exposure:I.exposure,decay:I.decay,weight:I.weight,density:I.density,invert:I.invert,useCustomMeshPosition:I.useCustomMeshPosition,customMeshPosition:I.customMeshPosition.asArray()}:null}i(Qe,"serializeVLSPostProcess");function We(e,r){let t=null;if(r.meshId){let o=e.getMeshById(r.meshId);o&&D(o)&&(t=o)}let n=jt(e,t);return n.exposure=r.exposure,n.decay=r.decay,n.weight=r.weight,n.density=r.density,n.invert=r.invert,n.useCustomMeshPosition=r.useCustomMeshPosition,n.customMeshPosition.copyFrom(kt.Vector3.FromArray(r.customMeshPosition)),n}i(We,"parseVLSPostProcess");var Ut=require("babylonjs"),b=null,Y=new Map;function $n(){return b}i($n,"getSSRRenderingPipeline");function jn(e){b=e}i(jn,"setSSRRenderingPipelineRef");function Ye(){b&&(b.dispose(),b=null)}i(Ye,"disposeSSRRenderingPipeline");function Qt(e,r){return b=new Ut.SSRRenderingPipeline("SSRRenderingPipeline",e,[r]),b.samples=4,b}i(Qt,"createSSRRenderingPipeline");function He(){return b?{samples:b.samples,step:b.step,thickness:b.thickness,strength:b.strength,reflectionSpecularFalloffExponent:b.reflectionSpecularFalloffExponent,maxSteps:b.maxSteps,maxDistance:b.maxDistance,roughnessFactor:b.roughnessFactor,reflectivityThreshold:b.reflectivityThreshold,blurDispersionStrehgth:b.blurDispersionStrength,clipToFrustum:b.clipToFrustum,enableSmoothReflections:b.enableSmoothReflections,enableAutomaticThicknessComputation:b.enableAutomaticThicknessComputation,attenuateFacingCamera:b.attenuateFacingCamera,attenuateScreenBorders:b.attenuateScreenBorders,attenuateIntersectionDistance:b.attenuateIntersectionDistance,attenuateBackfaceReflection:b.attenuateBackfaceReflection,blurDownsample:b.blurDownsample,selfCollisionNumSkip:b.selfCollisionNumSkip,ssrDownsample:b.ssrDownsample,backfaceDepthTextureDownsample:b.backfaceDepthTextureDownsample}:null}i(He,"serializeSSRRenderingPipeline");function qe(e,r,t){if(b)return b;let n=Qt(e,r);return n.samples=t.samples,n.step=t.step,n.thickness=t.thickness,n.strength=t.strength,n.reflectionSpecularFalloffExponent=t.reflectionSpecularFalloffExponent,n.maxSteps=t.maxSteps,n.maxDistance=t.maxDistance,n.roughnessFactor=t.roughnessFactor,n.reflectivityThreshold=t.reflectivityThreshold,n.blurDispersionStrength=t.blurDispersionStrehgth,n.clipToFrustum=t.clipToFrustum,n.enableSmoothReflections=t.enableSmoothReflections,n.enableAutomaticThicknessComputation=t.enableAutomaticThicknessComputation,n.attenuateFacingCamera=t.attenuateFacingCamera,n.attenuateScreenBorders=t.attenuateScreenBorders,n.attenuateIntersectionDistance=t.attenuateIntersectionDistance,n.attenuateBackfaceReflection=t.attenuateBackfaceReflection,n.blurDownsample=t.blurDownsample,n.selfCollisionNumSkip=t.selfCollisionNumSkip,n.ssrDownsample=t.ssrDownsample,n.backfaceDepthTextureDownsample=t.backfaceDepthTextureDownsample,n}i(qe,"parseSSRRenderingPipeline");var Wt=require("babylonjs"),E=null,H=new Map;function Un(){return E}i(Un,"getTAARenderingPipeline");function Qn(e){E=e}i(Qn,"setTAARenderingPipelineRef");function Je(){E&&(E.dispose(),E=null)}i(Je,"disposeTAARenderingPipeline");function Yt(e,r){return E=new Wt.TAARenderingPipeline("TAARenderingPipeline",e,[r]),E.samples=4,E}i(Yt,"createTAARenderingPipeline");function Ze(){return E?{factor:E.factor,samples:E.samples,clampHistory:E.clampHistory,reprojectHistory:E.reprojectHistory,disableOnCameraMove:E.disableOnCameraMove}:null}i(Ze,"serializeTAARenderingPipeline");function Xe(e,r,t){if(E)return E;let n=Yt(e,r);return n.factor=t.factor,n.samples=t.samples,n.clampHistory=t.clampHistory,n.reprojectHistory=t.reprojectHistory,n.disableOnCameraMove=t.disableOnCameraMove,n}i(Xe,"parseTAARenderingPipeline");var Ht=require("babylonjs"),x=null,q=new Map;function Wn(){return x}i(Wn,"getSSAO2RenderingPipeline");function Yn(e){x=e}i(Yn,"setSSAO2RenderingPipelineRef");function et(){x&&(x.dispose(),x=null)}i(et,"disposeSSAO2RenderingPipeline");function qt(e,r){return x=new Ht.SSAO2RenderingPipeline("SSAO2RenderingPipeline",e,1,[r]),x.samples=4,x}i(qt,"createSSAO2RenderingPipeline");function tt(){return x?{radius:x.radius,totalStrength:x.totalStrength,samples:x.samples,maxZ:x.maxZ,minZAspect:x.minZAspect,epsilon:x.epsilon,textureSamples:x.textureSamples,bypassBlur:x.bypassBlur,bilateralSamples:x.bilateralSamples,bilateralSoften:x.bilateralSoften,bilateralTolerance:x.bilateralTolerance,expensiveBlur:x.expensiveBlur}:null}i(tt,"serializeSSAO2RenderingPipeline");function rt(e,r,t){if(x)return x;let n=qt(e,r);return n.radius=t.radius,n.totalStrength=t.totalStrength,n.samples=t.samples,n.maxZ=t.maxZ,n.minZAspect=t.minZAspect,n.epsilon=t.epsilon,n.textureSamples=t.textureSamples,n.bypassBlur=t.bypassBlur,n.bilateralSamples=t.bilateralSamples,n.bilateralSoften=t.bilateralSoften,n.bilateralTolerance=t.bilateralTolerance,n.expensiveBlur=t.expensiveBlur,n}i(rt,"parseSSAO2RenderingPipeline");var Jt=require("babylonjs"),T=null,J=new Map;function nt(){return T}i(nt,"getMotionBlurPostProcess");function Hn(e){T=e}i(Hn,"setMotionBlurPostProcessRef");function ot(){T&&(T.dispose(),T=null)}i(ot,"disposeMotionBlurPostProcess");function Zt(e,r){return T=new Jt.MotionBlurPostProcess("MotionBlurPostProcess",e,1,r),T.motionStrength=1,T.isObjectBased=!0,T}i(Zt,"createMotionBlurPostProcess");function it(){return T?{isObjectBased:T.isObjectBased,motionStrength:T.motionStrength,motionBlurSamples:T.motionBlurSamples}:null}i(it,"serializeMotionBlurPostProcess");function st(e,r,t){if(T)return T;let n=Zt(e,r);return n.isObjectBased=t.isObjectBased,n.motionStrength=t.motionStrength,n.motionBlurSamples=t.motionBlurSamples,n}i(st,"parseMotionBlurPostProcess");var Xt=require("babylonjs"),at=require("babylonjs"),er=require("babylonjs"),tr=require("babylonjs"),rr=require("babylonjs"),d=null,Z=new Map;function pe(){return d}i(pe,"getDefaultRenderingPipeline");function qn(e){d=e}i(qn,"setDefaultRenderingPipelineRef");function lt(){d&&(d.dispose(),d=null)}i(lt,"disposeDefaultRenderingPipeline");function nr(e,r){return d=new rr.DefaultRenderingPipeline("DefaultRenderingPipeline",!0,e,[r]),d.samples=4,d.depthOfField.lensSize=512,d.depthOfField.fStop=.25,d.depthOfField.focusDistance=55e3,d}i(nr,"createDefaultRenderingPipeline");function ct(){return d?{samples:d.samples,fxaaEnabled:d.fxaaEnabled,imageProcessingEnabled:d.imageProcessingEnabled,exposure:d.imageProcessing?.exposure,contrast:d.imageProcessing?.contrast,fromLinearSpace:d.imageProcessing?.fromLinearSpace,toneMappingEnabled:d.imageProcessing?.toneMappingEnabled,toneMappingType:d.imageProcessing?.toneMappingType,ditheringEnabled:d.imageProcessing?.ditheringEnabled,ditheringIntensity:d.imageProcessing?.ditheringIntensity,bloomEnabled:d.bloomEnabled,bloomThreshold:d.bloomThreshold,bloomWeight:d.bloomWeight,bloomScale:d.bloomScale,bloomKernel:d.bloomKernel,sharpenEnabled:d.sharpenEnabled,sharpenEdgeAmount:d.sharpen.edgeAmount,sharpenColorAmount:d.sharpen.colorAmount,grainEnabled:d.grainEnabled,grainIntensity:d.grain.intensity,grainAnimated:d.grain.animated,depthOfFieldEnabled:d.depthOfFieldEnabled,depthOfFieldBlurLevel:d.depthOfFieldBlurLevel,lensSize:d.depthOfField.lensSize,fStop:d.depthOfField.fStop,focusDistance:d.depthOfField.focusDistance,focalLength:d.depthOfField.focalLength,vignetteEnabled:d.imageProcessing?.vignetteEnabled,vignetteColor:d.imageProcessing?.vignetteColor.asArray(),vignetteWeight:d.imageProcessing?.vignetteWeight,chromaticAberrationEnabled:d.chromaticAberrationEnabled,aberrationAmount:d.chromaticAberration.aberrationAmount,radialIntensity:d.chromaticAberration.radialIntensity,direction:d.chromaticAberration.direction.asArray(),centerPosition:d.chromaticAberration.centerPosition.asArray(),glowLayerEnabled:d.glowLayerEnabled,glowLayerIntensity:d.glowLayer?.intensity,glowLayerBlurKernelSize:d.glowLayer?.blurKernelSize,colorGradingEnabled:d.imageProcessing.colorGradingEnabled,colorGradingTexture:d.imageProcessing.colorGradingTexture?.serialize(),colorGradingWithGreenDepth:d.imageProcessing.imageProcessingConfiguration.colorGradingWithGreenDepth,colorCurvesEnabled:d.imageProcessing.colorCurvesEnabled,globalHue:d.imageProcessing.colorCurves?.globalHue,globalDensity:d.imageProcessing.colorCurves?.globalDensity,globalExposure:d.imageProcessing.colorCurves?.globalExposure,globalSaturation:d.imageProcessing.colorCurves?.globalSaturation,highlightsHue:d.imageProcessing.colorCurves?.highlightsHue,highlightsDensity:d.imageProcessing.colorCurves?.highlightsDensity,highlightsExposure:d.imageProcessing.colorCurves?.highlightsExposure,highlightsSaturation:d.imageProcessing.colorCurves?.highlightsSaturation,midtonesHue:d.imageProcessing.colorCurves?.midtonesHue,midtonesDensity:d.imageProcessing.colorCurves?.midtonesDensity,midtonesExposure:d.imageProcessing.colorCurves?.midtonesExposure,midtonesSaturation:d.imageProcessing.colorCurves?.midtonesSaturation,shadowsHue:d.imageProcessing.colorCurves?.shadowsHue,shadowsDensity:d.imageProcessing.colorCurves?.shadowsDensity,shadowsExposure:d.imageProcessing.colorCurves?.shadowsExposure,shadowsSaturation:d.imageProcessing.colorCurves?.shadowsSaturation}:null}i(ct,"serializeDefaultRenderingPipeline");function pt(e,r,t,n){if(d)return d;let o=nr(e,r);if(o.samples=t.samples,o.fxaaEnabled=t.fxaaEnabled,o.imageProcessingEnabled=t.imageProcessingEnabled,o.imageProcessing){if(o.imageProcessing.exposure=t.exposure,o.imageProcessing.contrast=t.contrast,o.imageProcessing.fromLinearSpace=t.fromLinearSpace,o.imageProcessing.toneMappingEnabled=t.toneMappingEnabled,o.imageProcessing.toneMappingType=t.toneMappingType,o.imageProcessing.ditheringEnabled=t.ditheringEnabled,o.imageProcessing.ditheringIntensity=t.ditheringIntensity,o.imageProcessing.vignetteEnabled=t.vignetteEnabled??!1,o.imageProcessing.vignetteColor=Xt.Color4.FromArray(t.vignetteColor??[0,0,0]),o.imageProcessing.vignetteWeight=t.vignetteWeight??.3,o.imageProcessing.colorGradingEnabled=t.colorGradingEnabled??!1,o.imageProcessing.imageProcessingConfiguration.colorGradingWithGreenDepth=t.colorGradingWithGreenDepth??!0,t.colorGradingTexture){let s=null;if(t.colorGradingTexture.customType==="BABYLON.ColorGradingTexture"){let a=n+t.colorGradingTexture.name;s=new tr.ColorGradingTexture(a,e),s.level=t.colorGradingTexture.level}else{let a=er.Texture.Parse(t.colorGradingTexture,e,n);ce(a)&&(s=a)}o.imageProcessing.colorGradingTexture=s}o.imageProcessing.colorCurvesEnabled=t.colorCurvesEnabled??!1,o.imageProcessing.colorCurves&&(o.imageProcessing.colorCurves.globalHue=t.globalHue??30,o.imageProcessing.colorCurves.globalDensity=t.globalDensity??0,o.imageProcessing.colorCurves.globalExposure=t.globalExposure??0,o.imageProcessing.colorCurves.globalSaturation=t.globalSaturation??0,o.imageProcessing.colorCurves.highlightsHue=t.highlightsHue??30,o.imageProcessing.colorCurves.highlightsDensity=t.highlightsDensity??0,o.imageProcessing.colorCurves.highlightsExposure=t.highlightsExposure??0,o.imageProcessing.colorCurves.highlightsSaturation=t.highlightsSaturation??0,o.imageProcessing.colorCurves.midtonesHue=t.midtonesHue??30,o.imageProcessing.colorCurves.midtonesDensity=t.midtonesDensity??0,o.imageProcessing.colorCurves.midtonesExposure=t.midtonesExposure??0,o.imageProcessing.colorCurves.midtonesSaturation=t.midtonesSaturation??0,o.imageProcessing.colorCurves.shadowsHue=t.shadowsHue??30,o.imageProcessing.colorCurves.shadowsDensity=t.shadowsDensity??0,o.imageProcessing.colorCurves.shadowsExposure=t.shadowsExposure??0,o.imageProcessing.colorCurves.shadowsSaturation=t.shadowsSaturation??0)}return o.bloomEnabled=t.bloomEnabled,o.bloomThreshold=t.bloomThreshold,o.bloomWeight=t.bloomWeight,o.bloomScale=t.bloomScale,o.bloomKernel=t.bloomKernel,o.sharpenEnabled=t.sharpenEnabled,o.sharpen.edgeAmount=t.sharpenEdgeAmount,o.sharpen.colorAmount=t.sharpenColorAmount,o.grainEnabled=t.grainEnabled,o.grain.intensity=t.grainIntensity,o.grain.animated=t.grainAnimated,o.depthOfFieldEnabled=t.depthOfFieldEnabled,o.depthOfFieldBlurLevel=t.depthOfFieldBlurLevel,o.depthOfField.lensSize=t.lensSize,o.depthOfField.fStop=t.fStop,o.depthOfField.focusDistance=t.focusDistance,o.depthOfField.focalLength=t.focalLength,o.chromaticAberrationEnabled=t.chromaticAberrationEnabled??!1,o.chromaticAberration.aberrationAmount=t.aberrationAmount??10,o.chromaticAberration.radialIntensity=t.radialIntensity??1,o.chromaticAberration.direction=at.Vector2.FromArray(t.direction??[0,0]),o.chromaticAberration.centerPosition=at.Vector2.FromArray(t.centerPosition??[0,0]),o.glowLayerEnabled=t.glowLayerEnabled??!1,o.glowLayer&&(o.glowLayer.intensity=t.glowLayerIntensity??1,o.glowLayer.blurKernelSize=t.glowLayerBlurKernelSize??32),o}i(pt,"parseDefaultRenderingPipeline");function Jn(e){q.set(e,tt()),W.set(e,Qe()),Y.set(e,He()),J.set(e,it()),Z.set(e,ct()),H.set(e,Ze())}i(Jn,"saveRenderingConfigurationForCamera");function mt(e,r,t){et(),Ue(e.getScene()),Ye(),ot(),lt(),Je();let n=q.get(e);n&&!t?.ssao2Disabled&&rt(e.getScene(),e,n);let o=W.get(e);o&&!t?.vlsDisabled&&We(e.getScene(),o);let s=Y.get(e);s&&!t?.ssrDisabled&&qe(e.getScene(),e,s);let a=J.get(e);a&&!t?.motionBlurDisabled&&st(e.getScene(),e,a);let c=Z.get(e);c&&!t?.defaultPipelineDisabled&&pt(e.getScene(),e,c,r);let l=H.get(e);l&&!t?.taaDisabled&&Xe(e.getScene(),e,l)}i(mt,"applyRenderingConfigurationForCamera");var me=require("babylonjs"),or=require("babylonjs");function ir(e){let r=e.metadata?.physicsAggregate;if(!r)return;let t;D(e)?t=e:le(e)&&(t=e.sourceMesh);let n=new or.PhysicsAggregate(e,r.shape.type,{mesh:t,mass:r.massProperties.mass});n.body.setMassProperties({mass:r.massProperties.mass,inertia:r.massProperties.inertia?me.Vector3.FromArray(r.massProperties.inertia):void 0,centerOfMass:r.massProperties.centerOfMass?me.Vector3.FromArray(r.massProperties.centerOfMass):void 0,inertiaOrientation:r.massProperties.inertiaOrientation?me.Quaternion.FromArray(r.massProperties.inertiaOrientation):void 0}),n.shape.density=r.shape.density,n.body.setMotionType(r.body.motionType),n.shape.material=r.material,e.physicsAggregate=n,e.metadata.physicsAggregate=void 0}i(ir,"configurePhysicsAggregate");function sr(e,r){(Array.isArray(r)?r:[]).forEach(n=>{let o=e.getCameraById(n.cameraId);o&&(n.ssao2RenderingPipeline&&q.set(o,n.ssao2RenderingPipeline),n.vlsPostProcess&&W.set(o,n.vlsPostProcess),n.ssrRenderingPipeline&&Y.set(o,n.ssrRenderingPipeline),n.motionBlurPostProcess&&J.set(o,n.motionBlurPostProcess),n.defaultRenderingPipeline&&Z.set(o,n.defaultRenderingPipeline),n.taaRenderingPipeline&&H.set(o,n.taaRenderingPipeline))})}i(sr,"applyRenderingConfigurations");var ar=require("babylonjs");function X(e,r,t){return new Promise((n,o)=>{let s=new ar.WebRequest;s.open("GET",e),s.responseType=r,s.send(),s.addEventListener("progress",a=>{t?.({total:a.total,loaded:a.loaded})}),s.addEventListener("load",()=>{n(r==="text"?s.responseText:s.response)}),s.addEventListener("error",a=>o(a))})}i(X,"loadFile");async function N(e,r){let t=await X(e,"text",r);return JSON.parse(t)}i(N,"loadJsonFile");function ut(e,r){let t=r.getNodeByName(e);if(t)return t;let n=r.lights.filter(o=>Ae(o));for(let o of n){let s=o.lights.find(a=>a.name===e);if(s)return s}return null}i(ut,"getNodeByName");function ee(e,r){let t=r.getNodeById(e);if(t)return t;let n=r.lights.filter(o=>Ae(o));for(let o of n){let s=o.lights.find(a=>a.id===e);if(s)return s}return null}i(ee,"getNodeById");var U=require("babylonjs"),lr=require("babylonjs");function dt(e){let r=lr.Vector3.FromArray(e);return r.equals(U.Axis.X)?U.Axis.X:r.equals(U.Axis.Y)?U.Axis.Y:r.equals(U.Axis.Z)?U.Axis.Z:r}i(dt,"parseAxis");function cr(e){return e.runtimeConfiguration.forEach(r=>{r.rotationAxis&&(r.rotationAxis=dt(r.rotationAxis)),r.boneOffsetAxis&&(r.boneOffsetAxis=dt(r.boneOffsetAxis))}),e}i(cr,"parseRagdollConfiguration");function ft(e){let r={rootNodeId:e.rootNodeId,skeletonName:e.skeletonName,scalingFactor:e.scalingFactor,runtimeConfiguration:e.runtimeConfiguration.map(t=>({name:t.name,bones:t.bones,width:t.width,depth:t.depth,height:t.height,size:t.size,joint:t.joint,min:t.min,max:t.max,boxOffset:t.boxOffset,rotationAxis:t.rotationAxis?.slice(),boneOffsetAxis:t.boneOffsetAxis?.slice()}))};return cr(r)}i(ft,"copyAndParseRagdollConfiguration");function Zn(e){return new Promise(r=>{setTimeout(()=>r(),e)})}i(Zn,"waitMs");async function gt(e){for(;!e();)await Zn(150)}i(gt,"waitUntil");function yt(e){return e&&JSON.parse(JSON.stringify(e))}i(yt,"cloneJSObject");var ht=require("babylonjs"),gr=require("babylonjs"),Ce=require("babylonjs"),yr=require("babylonjs"),Sr=require("babylonjs"),hr=require("babylonjs"),z=require("babylonjs"),pr=!1,mr=null,te=[],St=new Map;function Xn(e,r){let t=(0,z._GetAudioEngine)(null);return new hr._WebAudioStaticSound(e,t,r)}i(Xn,"createSoundInstance");function ur(e){if(mr?.remove(),!te.length)return;let r=ht.Vector3.Zero();mr=e.onBeforeRenderObservable.add(()=>{let t=(0,z._GetAudioEngine)(null).listener.attachedNode;t&&(t.getWorldMatrix().getTranslationToRef(r),te.forEach(n=>{n.isEnabled(!1)&&n.autoUpdateSpatial&&n.sound?._isSpatial&&n.isPlaying()&&e.activeCamera&&ht.Vector3.Distance(r,n.getAbsolutePosition())<=n.sound.spatial.maxDistance&&n.sound.spatial.update()}))})}i(ur,"registerUpdateSoundsObserver");function dr(e){e.sound?.onDisposeObservable.addOnce(()=>{let r=te.indexOf(e);r!==-1&&te.splice(r,1)}),e.onDisposeObservable.addOnce(()=>{e.sound?.dispose()})}i(dr,"registerSoundNodeEvents");function eo(e,r){return new Promise(async(t,n)=>{if(!e.offlineProvider||!gr.Database.IDBStorageEnabled)return(0,z.CreateSoundBufferAsync)(r).then(o=>t(o)).catch(o=>n(o));e.offlineProvider.loadFile(r,o=>{(0,z.CreateSoundBufferAsync)(o).then(s=>t(s)).catch(s=>n(s))},void 0,()=>{n(null)},!0)})}i(eo,"loadSoundBuffer");function bt(e,r){if(!e.soundRelativePath||!e.sound)return;r.onSoundLoadedObservable=new yr.Observable;let t=Xn(e.soundRelativePath,{spatialAutoUpdate:!1});t._initAsync(e.sound.buffer,{spatialAutoUpdate:!0}).then(()=>{t.volume=e.volume,t._isSpatial=e.sound._isSpatial,t._isSpatial&&(t.spatial.attach(r),t.spatial.maxDistance=e.sound.spatial.maxDistance,t.spatial.panningModel=e.sound.spatial.panningModel,t.spatial.distanceModel=e.sound.spatial.distanceModel),r.sound=t,r.soundRelativePath=e.soundRelativePath,r.autoUpdateSpatial=e.autoUpdateSpatial,te.push(r),ur(r.getScene()),r.onSoundLoadedObservable.notifyObservers(r)}),dr(r),fr(r,t)}i(bt,"configureSourceNodeFrom");function fr(e,r){Object.defineProperty(e,"volume",{get:i(()=>r.volume,"get"),set:i(t=>{r.volume=t},"set")}),Object.defineProperty(e,"playbackRate",{get:i(()=>r.playbackRate,"get"),set:i(t=>{r.playbackRate=t},"set")}),e.isPaused=()=>r.state===Ce.SoundState.Paused,e.isPlaying=()=>r.state===Ce.SoundState.Started,e.isStopped=()=>r.state===Ce.SoundState.Stopped,e.pause=()=>r.pause(),e.resume=()=>r.resume(),e.stop=t=>r.stop(t),e.play=t=>r.play(t),e.setVolume=(t,n)=>r.setVolume(t,n),e.getClassName=()=>"SoundNode",e.setSoundSpatial=t=>new Promise(n=>{r._isSpatial=t,setTimeout(()=>{t&&r.spatial.attach(e),n()})}),e.cloneAsync=async(t,n,o)=>new Promise(s=>{let a=e.clone(t,n,o);bt(e,a),a.onSoundLoadedObservable.addOnce(()=>{setTimeout(()=>s(a))})})}i(fr,"configureSoundNodePrototype");function br(){pr||(pr=!0,(0,Sr.AddParser)("SoundNode",(e,r,t,n)=>{e.transformNodes?.forEach(o=>{if(!o.isSoundNode)return;let s=t.transformNodes?.find(a=>a.id===o.id);if(s&&o.soundRelativePath){let a=`${n}${o.soundRelativePath}`;r.addPendingData(a),St.has(a)||St.set(a,eo(r,a)),St.get(a).then(l=>{(0,z.CreateSoundAsync)(o.soundRelativePath,l,{spatialAutoUpdate:!1}).then(p=>{if(r.removePendingData(a),s.isDisposed())return p.dispose();p.volume=o.volume,p._isSpatial=o.isSpatial,o.isSpatial&&(p.spatial.attach(s),p.spatial.maxDistance=o.maxDistance,p.spatial.panningModel=o.panningModel,p.spatial.distanceModel=o.distanceModel),s.sound=p,s.soundRelativePath=o.soundRelativePath,s.autoUpdateSpatial=o.autoUpdateSpatial,te.push(s),dr(s),fr(s,p),ur(r)})})}})}))}i(br,"registerAudioParser");function re(e){let r=new Set;[...e.transformNodes,...e.meshes].forEach(n=>{if(n.metadata?.isStaticGroup){let o=n.getDescendants(!1);o.push(n),o.forEach(s=>{if(($(s)||k(s)&&!s.isWorldMatrixFrozen)&&s.freezeWorldMatrix(),$(s)){let a=s.material;a&&!a.isFrozen&&!r.has(a)&&(r.add(a),a.onBindObservable.addOnce(()=>{a.freeze()}))}})}})}i(re,"configureTransformNodes");var ue=class{constructor(r,t){this.entries=r;this.namingId=t}entries;namingId;static{i(this,"AdvancedAssetContainerInstantiatedEntries")}get rootNodes(){return this.entries.rootNodes}get skeletons(){return this.entries.skeletons}get animationGroups(){return this.entries.animationGroups}dispose(){this.entries.dispose()}getRootNodeByName(r){let t=`${r}-${this.namingId}`;return this.entries.rootNodes.find(n=>n.name===t)??null}getNodeByName(r){let t=`${r}-${this.namingId}`;for(let n of this.entries.rootNodes){let o=this._recursivelyGetNodeByName(t,n);if(o)return o}return null}_recursivelyGetNodeByName(r,t){if(t.name===r)return t;for(let n of t.getDescendants(!0)){let o=this._recursivelyGetNodeByName(r,n);if(o)return o}return null}getScriptByClassByObjectName(r,t){let n=this.getNodeByName(r);if(n){let o=ne(n,t);if(o?.length===1)return o[0]}return null}};var Pt=require("babylonjs"),de=class{static{i(this,"AdvancedAssetContainer")}container;_rootUrl;_scriptsMap;_originalDescendants=[];_nodesMap=new Map;_animationGroupsMap=new Map;constructor(r,t,n){this.container=r,this._rootUrl=t,this._scriptsMap=n,r.populateRootNodes(),r.rootNodes.forEach(o=>{this._originalDescendants.push(o,...o.getDescendants(!1))}),r.animationGroups.forEach(o=>{this._animationGroupsMap.set(o.name,o)}),this._originalDescendants.forEach(o=>{this._nodesMap.set(o,{node:o,metadata:yt(o.metadata)})})}removeDefault(){this.container.getNodes().forEach(r=>{R.get(r)?.forEach(n=>{Ie(r,n)})}),this.container.removeAllFromScene()}getRootNodeByName(r){return this.container.rootNodes.find(t=>t.name===r)??null}getScriptByClassByObjectName(r,t){let n=this.container.getNodes();for(let o of n)if(o.name===r){let s=ne(o,t);if(s?.length===1)return s[0]}return null}instantiate(r){let t=Pt.Tools.RandomId(),n=i(l=>l,"nameFunction"),o=this.container.instantiateModelsToScene(n,!1,{...r,predicate:i(l=>(l.name=`${l.name}@editor-tools@${t}_${l.id}`,r?.predicate?.(l)??!0),"predicate")}),s=new ue(o,t);[...this.container.transformNodes,...this.container.meshes,...this.container.lights,...this.container.cameras,...this.container.animationGroups,...this.container.skeletons].forEach(l=>{let p=l.name.split("@editor-tools@");l.name=p[0]}),o.animationGroups.forEach(l=>{let p=l.name.split("@editor-tools@");l.name=`${p[0]}-${t}`});let c=[];return o.rootNodes.forEach(l=>{c.push(l,...l.getDescendants(!1))}),c.forEach(l=>{let p=l.name.split("@editor-tools@"),m=p[1].split("_").pop();l.name=`${p[0]}-${t}`;let u=this._originalDescendants.find(f=>f.id===m);j(u)&&k(l)&&bt(u,l),l.id=Pt.Tools.RandomId(),l.metadata=yt(this._nodesMap.get(u).metadata),l.metadata??={},l.metadata.originalId=m,c.forEach(f=>{f.metadata.scripts?.forEach(g=>{Object.keys(g.values||{}).forEach(y=>{let P=g.values[y];if(P.type==="entity"){P.value===m&&(P.value=l.id),P.value===u.name&&(P.value=l.name);let A=this._animationGroupsMap.get(P.value);A&&(P.value=`${A.name}-${t}`)}})})})}),c.forEach(l=>{F(this.container.scene,l,this._scriptsMap,this._rootUrl)}),re(this.container.scene),s}};var Pr=require("babylonjs"),xr=require("babylonjs");async function Ar(e,r,t){let n=t.iblIntensity,o=t.environmentIntensity,a=e.split("/").pop().replace(".scene",".babylon"),c=await(0,xr.LoadAssetContainerAsync)(a,t,{rootUrl:r,pluginExtension:".babylon"});return Pr.SceneLoaderFlags.ForceFullSceneLoadingForIncremental&&t.meshes.forEach(l=>D(l)&&l._checkDelayState()),c.addAllToScene(),t.iblIntensity=n,t.environmentIntensity=o,re(t),c}i(Ar,"preloadSceneScriptAsset");async function vr(e,r){return N(`${r}${e}`)}i(vr,"preloadCommonScriptAsset");var O=new Map,fe=new Map;function to(e,r){fe.has(e)&&console.warn(`A parser for the extension '${e}' was already registered. It will be overwritten.`),fe.set(e,r)}i(to,"registerScriptAssetParser");async function xt(e,r,t){[r,...r.transformNodes,...r.meshes,...r.lights,...r.cameras].filter(c=>c.metadata?.scripts?.length).map(c=>c.metadata.scripts).flat().forEach(c=>{if(t[c.key]?.default?._SceneAssets?.forEach(p=>{O.get(p.sceneName)||O.set(p.sceneName,null)}),c.values)for(let p in c.values){if(!c.values.hasOwnProperty(p))continue;let m=c.values[p];m.type==="asset"&&m.value&&!O.get(m.value)&&O.set(m.value,null)}});let s=0;for(let c of O.values())c===null&&++s;if(s===0)return s;let a=[];return O.forEach((c,l)=>{O.get(l)||a.push(new Promise(async p=>{try{let m=l.split(".").pop();switch(m){case"scene":let u=await Ar(l,e,r);r.onDisposeObservable.addOnce(()=>{u.dispose(),O.delete(l)}),O.set(l,new de(u,e,t));break;default:if(fe.has(m)){let f=fe.get(m);O.set(l,await f({key:l,rootUrl:e,scene:r}));break}else O.set(l,await vr(l,e));break}}catch(m){console.error(m)}p()}))}),await Promise.all(a),s}i(xt,"_preloadScriptsAssets");var Cr=require("babylonjs"),Ee=require("babylonjs"),Ir=require("babylonjs"),Te=require("babylonjs"),Er=require("babylonjs"),Tr=require("babylonjs-gui");function At(e,r,t,n,o){let s=n.constructor;if(!s)return;s._NodesFromScene?.forEach(l=>{n[l.propertyKey.toString()]=ut(l.nodeName,e)}),s._ComponentsFromScene?.length&&e.getEngine().onBeginFrameObservable.addOnce(()=>{s._ComponentsFromScene?.forEach(l=>{let p=[];if([e,...e.transformNodes,...e.meshes,...e.lights,...e.cameras].forEach(u=>{let f=vt(u,l.componentConstructor);f&&p.push(f)}),p.length>1)throw new Error(`Multiple components of type ${s._ComponentsFromScene[0].componentConstructor.name} found in scene for property "${s._ComponentsFromScene[0].propertyKey.toString()}".`);n[l.propertyKey.toString()]=p[0]??null})}),s._NodesFromDescendants?.forEach(l=>{let p=r.getDescendants?.(l.directDescendantsOnly,m=>m.name===l.nodeName)[0];n[l.propertyKey.toString()]=p??null}),s._AnimationGroups?.forEach(l=>{n[l.propertyKey.toString()]=e.getAnimationGroupByName(l.animationGroupName)}),s._SoundsFromScene?.forEach(l=>{let p=ut(l.soundName,e);p&&j(p)&&(n[l.propertyKey.toString()]=p??null)}),(s._GuiFromAsset??[]).map(async l=>{let p=`${o}assets/${l.pathInAssets}`;try{let m=await N(p),u=Tr.AdvancedDynamicTexture.CreateFullscreenUI(m.name,!0,e);u.parseSerializedObject(m.content,!1),n[l.propertyKey.toString()]=u,l.onGuiCreated?.(n,u)}catch(m){throw console.error(`Failed to load GUI from asset: ${p}`),m}}),s._ParticleSystemsFromScene?.forEach(l=>{let p=e.particleSystems?.find(m=>m.name!==l.particleSystemName?!1:l.directDescendantsOnly?m.emitter===r:m);n[l.propertyKey.toString()]=p}),(s._VisibleInInspector??[]).forEach(l=>{let p=l.propertyKey.toString(),m=t.values;if(!m)throw new Error(`No values found for script with key "${t.key}".`);if(m.hasOwnProperty(p)&&m[p].hasOwnProperty("value")){let u=m[p].value;switch(l.configuration.type){case"number":case"boolean":case"keymap":case"string":n[p]=u;break;case"vector2":n[p]=Te.Vector2.FromArray(u);break;case"vector3":n[p]=Te.Vector3.FromArray(u);break;case"color3":n[p]=Ee.Color3.FromArray(u);break;case"color4":n[p]=Ee.Color4.FromArray(u);break;case"entity":switch(l.configuration.entityType){case"node":case"sound":n[p]=ee(u,e)??null;break;case"animationGroup":n[p]=e.getAnimationGroupByName(u)??null;break;case"particleSystem":n[p]=e.particleSystems?.find(g=>g.id===u)??null;break}break;case"texture":u&&(n[p]=Ir.Texture.Parse(u,e,o));break;case"asset":if(u){let g=l.configuration.assetType,S=O.get(u);switch(g){case"json":case"gui":case"scene":case"navmesh":case"cinematic":n[p]=S;break;case"ragdoll":n[p]=ft(S);break;case"nodeParticleSystemSet":let y=Er.NodeParticleSystemSet.Parse(S);n[p]=y;break;case"material":n[p]=Cr.Material.Parse(S,e,o);break}}}}});let a=null,c=null;if(s._PointerEvents?.length){if(s._PointerEvents.find(m=>m.options.mode==="attachedMeshOnly")&&!$(r))throw new Error('@onPointerEvent with mode "attachedMeshOnly" can only be used on scripts attached to meshes (extends AbstractMesh).');if(s._PointerEvents.find(m=>m.options.mode!=="global")&&!Q(r))throw new Error('@onPointerEvent with mode different from "global" can be used only on scripts attached to Node: Mesh, Light, Camera, TransformNode.');a=e.onPointerObservable.add(m=>{let u=null;s._PointerEvents.forEach(f=>{if(!f.eventTypes.includes(m.type))return;let g=f.propertyKey.toString();if(f.options.mode==="global")return n[g]?.(m);u=m.pickInfo,u||(u=e.pick(e.pointerX,e.pointerY,y=>y.isVisible&&y.isPickable&&y.isEnabled(!0)&&!y._masterMesh,!1));let S=u.pickedMesh;if(S&&(f.options.mode==="attachedMeshOnly"&&S===r||f.options.mode==="includeDescendants"&&Q(r)&&[r,...r.getDescendants(!1)].find(A=>A===S)))return n[g]?.(m)})})}if(s._KeyboardEvents?.length&&(c=e.onKeyboardObservable.add(l=>{s._KeyboardEvents.forEach(p=>{p.eventTypes.includes(l.type)&&n[p.propertyKey.toString()]?.(l)})})),s._SpritesFromSpriteManager?.length){let l=r;if(!k(l)||!l.isSpriteManager)return console.error("@spriteFromSpriteManager decorator can only be used on SpriteManagerNode.");if(!l.spriteManager)return console.error(`SpriteManagerNode "${l.name}" has no sprite manager assigned.`);s._SpritesFromSpriteManager?.forEach(p=>{let m=l.spriteManager?.sprites.find(u=>u.name===p.spriteName)||null;n[p.propertyKey.toString()]=m})}if(s._AnimationsFromSprite?.length){if(!Be(r))return console.error("@animationFromSprite decorator can only be used in scripts attached on Sprite.");let l=r.metadata?.spriteAnimations;if(!l?.length)return console.error(`Sprite "${r.name}" has no sprite animations assigned.`);s._AnimationsFromSprite.forEach(p=>{let m=l.find(u=>u.name===p.animationName);m?n[p.propertyKey.toString()]=m??null:console.warn(`Sprite animation named "${p.animationName}" not found on sprite "${r.name}".`)})}return s._SceneAssets?.forEach(l=>{n[l.propertyKey.toString()]=O.get(l.sceneName)}),{observers:{pointerObserver:a,keyboardObserver:c}}}i(At,"applyDecorators");function F(e,r,t,n){r.metadata?.scripts&&(r.metadata.scripts?.forEach(o=>{if(!o.enabled)return;let s=t[o.key];if(!s)return;let a=s,c={};if(s.default){a=new s.default(r);let l=At(e,r,o,a,n);Object.assign(c,l?.observers??{})}a.onStart&&(c.onStartObserver=e.onBeforeRenderObservable.addOnce(()=>a.onStart(r))),a.onUpdate&&(c.onUpdateObserver=e.onBeforeRenderObservable.add(()=>a.onUpdate(r))),Ct(r,a,o.key,c)}),r.metadata.scripts=void 0)}i(F,"_applyScriptsForObject");function ro(e,r,t){if(t??=e.getScene?.(),!t)throw new Error("Cannot apply script on object: no scene available.");let n=new r(e),o={};return At(t,e,{values:{}},n,""),n.onStart&&(o.onStartObserver=t.onBeforeRenderObservable.addOnce(()=>n.onStart())),n.onUpdate&&t.onBeforeRenderObservable.add(()=>n.onUpdate()),Ct(e,n,"runtime",o),n}i(ro,"applyScriptOnObject");var R=new Map;function Ct(e,r,t,n){let o={key:t,observers:n,instance:r};R.has(e)?R.get(e).push(o):R.set(e,[o]),(Q(e)||Ve(e)||_e(e)||j(e))&&e.onDisposeObservable.addOnce((()=>{R.get(e)?.slice()?.forEach(a=>{Ie(e,a)}),R.delete(e)}))}i(Ct,"_registerScriptInstance");function Ie(e,r){r.observers.onStartObserver?.remove(),r.observers.onUpdateObserver?.remove(),r.observers.pointerObserver?.remove(),r.observers.keyboardObserver?.remove();try{r.instance.onStop?.(e)}catch(o){console.error(`Failed to call onStop for script ${r.key} on object ${e}`,o)}let t=R.get(e),n=t?.indexOf(r)??-1;n!==-1&&t?.splice(n,1)}i(Ie,"_removeRegisteredScriptInstance");function ne(e,r){return R.get(e)?.filter(o=>o.instance.constructor===r)?.map(o=>o.instance)??null}i(ne,"getAllScriptsByClassForObject");function vt(e,r){return ne(e,r)?.[0]??null}i(vt,"getScriptByClassForObject");var Or=!1;function no(e){Or=e}i(no,"setUseKtx2CompressedTextures");function ge(){return Or}i(ge,"isUsingKtx2CompressedTextures");function Oe(e){return`${e.substring(0,e.lastIndexOf("."))}.ktx2`}i(Oe,"_getKtx2TextureName");function oo(e){e.setCompressedTextureExclusions([".env",".hdr",".dds"]),e.setTextureFormatToUse(["-dxt.ktx","-astc.ktx","-pvrtc.ktx","-etc1.ktx","-etc2.ktx"])}i(oo,"configureEngineToUseCompressedTextures");function De(e,r){e._excludedCompressedTextures&&!e._excludedCompressedTextures?.includes(r)&&e._excludedCompressedTextures?.push(r)}i(De,"addExcludedCompressedTexture");function io(e,r,t){r.loadingTexturesQuality!==e&&(r.loadingTexturesQuality=e,r.textures.forEach(n=>{if(!ce(n)||!n.url)return;let o=Me(n,r);!o||n.url.includes(o)||n.updateURL(t+o)}))}i(io,"applyTexturesQuality");function Me(e,r){if(r.loadingTexturesQuality==="high"||!e.metadata?.baseSize)return e.name;let t=e.metadata.baseSize.width,n=e.metadata.baseSize.height,o=t===M(t)||n===M(n),s="";switch(r.loadingTexturesQuality){case"medium":let f=t*.66>>0,g=n*.66>>0;o&&(f=M(f),g=M(g)),s=`_${f}_${g}`;break;case"low":case"very-low":let S=t*.33>>0,y=n*.33>>0;o&&(S=M(S),y=M(y)),s=`_${S}_${y}`;break}let a=e.name;if(!a||!s)return e.name;let c=a.split("/"),l=c.pop();if(!l)return e.name;let p=l.split(".").pop(),u=`${l.replace(`.${p}`,"")}${s}.${p}`;return c.push(u),c.join("/")}i(Me,"getTextureUrl");var It=require("babylonjs"),Dr=!1;function Mr(){if(Dr)return;Dr=!0;let e=It.SerializationHelper._TextureParser;It.SerializationHelper._TextureParser=(r,t,n)=>{ge()&&(r.name&&(r.name=Oe(r.name)),r.url&&(r.url=Oe(r.url)));let o=Me(r,t);if(!o)return e(r,t,n);let s=r.name;r.name=o;let a=e(r,t,n);return a&&(a.name=s),a}}i(Mr,"registerTextureParser");var Nr=require("babylonjs"),Fr=require("babylonjs"),we=require("babylonjs"),Rr=require("babylonjs"),wr=!1;function _r(){if(wr)return;wr=!0,(0,Rr.RegisterShadowGeneratorSceneComponent)(Fr.ShadowGenerator);let e=(0,we.GetParser)(Nr.SceneComponentConstants.NAME_SHADOWGENERATOR);(0,we.AddParser)("ShadowGeneratorEditorPlugin",(r,t,n,o)=>{let s=new Map;r.shadowGenerators?.forEach(a=>{if(s.set(a.id,a.mapSize),t.loadingShadowsQuality!=="high"){switch(t.loadingShadowsQuality){case"medium":a.mapSize=a.mapSize*.5;break;case"low":a.mapSize=a.mapSize*.25;break;case"very-low":a.mapSize=a.mapSize*.125;break}a.mapSize=Math.max(128,M(a.mapSize))}}),e?.(r,t,n,o),t.lights.forEach(a=>{let c=a.getShadowGenerator();if(c?.getShadowMap()){let p=c.id,m=s.get(p);m&&(c.originalMapSize=m)}})})}i(_r,"registerShadowGeneratorParser");var Br=require("babylonjs"),Gr=require("babylonjs"),Kr=require("babylonjs"),Et=require("babylonjs"),kr=require("babylonjs");function Lr(e,r){r?.fogEnabled!==void 0&&(e.fogEnabled=r?.fogEnabled),r?.blendMode!==void 0&&(e.blendMode=r?.blendMode),r?.disableDepthWrite!==void 0&&(e.disableDepthWrite=r?.disableDepthWrite),r?.pixelPerfect!==void 0&&(e.pixelPerfect=r?.pixelPerfect),r?.useLogarithmicDepth!==void 0&&(e.useLogarithmicDepth=r?.useLogarithmicDepth),r?.metadata!==void 0&&(e.metadata=r?.metadata);for(let t of r?.sprites??[]){let n=Gr.Sprite.Parse(t,e);n.uniqueId=t.uniqueId,n.metadata=t.metadata}}i(Lr,"parseSerializedSpriteManager");var Vr=!1;function zr(){Vr||(Vr=!0,(0,kr.AddParser)("SpriteManagerNode",(e,r,t,n)=>{e.transformNodes?.forEach(o=>{if(!o.isSpriteManager)return;let s=t.transformNodes?.find(c=>c.id===o.id);if(!s)return;let a=r.getEngine();if(s.isSpriteManager=o.isSpriteManager,o.atlasJsonRelativePath){let c=`${n}${o.atlasJsonRelativePath}`;r.addPendingData(c);let l=new Kr.WebRequest;l.open("GET",c),l.send(),l.addEventListener("load",()=>{r.removePendingData(c);let p=JSON.parse(l.responseText),m=`${Br.Tools.GetFolderPath(c)}${p.meta.image}`;De(a,m);let u=new Et.SpriteManager(s.name,m,1e3,64,r,void 0,void 0,!0,p);s.spriteManager=u,s.getClassName=()=>"SpriteManagerNode",o.spriteManager&&Lr(u,o.spriteManager)})}else if(o.spriteManager?.textureUrl){De(a,o.spriteManager.textureUrl);let c=`${n}${o.spriteManager.textureUrl}`,l=new Et.SpriteManager(s.name,c,1e3,{width:o.spriteManager.cellWidth,height:o.spriteManager.cellHeight},r,void 0,void 0,!1);s.spriteManager=l,s.getClassName=()=>"SpriteManagerNode",o.spriteManager&&Lr(l,o.spriteManager)}})}))}i(zr,"registerSpriteManagerParser");var jr=require("babylonjs"),Ur=require("babylonjs"),$r=!1;function Qr(){$r||($r=!0,(0,Ur.AddParser)("MorphTargetManagerEditorPlugin",(e,r,t,n)=>{e.morphTargetManagers.forEach(o=>{let a=t.meshes.find(p=>p.id===o.meshId)?.morphTargetManager;if(!a||o.targets.find(p=>!p.delayLoadingFile))return;let l=[];o.targets.forEach(p=>{if(!p.delayLoadingFile)return l.push(Promise.resolve(null));let m=`${n}${p.delayLoadingFile}`;r.addPendingData(m);let u=new jr.WebRequest;u.responseType="arraybuffer",u.open("GET",m),u.send(),l.push(new Promise(f=>{u.addEventListener("load",()=>{r.removePendingData(m),f(u.response)})}))}),Promise.all(l).then(p=>{for(let m=0,u=a.numTargets;m<u;++m){let f=a.getTarget(m),g=o.targets[m],S=p[m];if(g.positionsCount){let y=new Float32Array(S,g.positionsOffset,g.positionsCount);f._positions=y,f.setPositions(y)}if(g.normalsCount){let y=new Float32Array(S,g.normalsOffset,g.normalsCount);f._normals=y,f.setNormals(y)}if(g.tangentsCount){let y=new Float32Array(S,g.tangentsOffset,g.tangentsCount);f._tangents=y,f.setTangents(y)}if(g.uvsCount){let y=new Float32Array(S,g.uvsOffset,g.uvsCount);f._uvs=y,f.setUVs(y)}if(g.uv2sCount){let y=new Float32Array(S,g.uv2sOffset,g.uv2sCount);f._uv2s=y,f.setUV2s(y)}}for(let m=0,u=a.numTargets;m<u;++m)a.getTarget(m)._onDataLayoutChanged.notifyObservers()})})}))}i(Qr,"registerMorphTargetManagerParser");var Yr=require("babylonjs"),Hr=require("babylonjs"),Wr=!1;function qr(){Wr||(Wr=!0,(0,Yr.AddParser)("NodeParticleSystemSetEditorPlugin",(e,r,t,n)=>{e.meshes?.forEach(o=>{if(!o.isNodeParticleSystemMesh)return;let s=t.meshes?.find(a=>a.id===o.id);s&&(o.nodeParticleSystemSet.blocks?.forEach(a=>{a.url&&(a.url=`${n}${a.url}`)}),s.nodeParticleSystemSet=Hr.NodeParticleSystemSet.Parse(o.nodeParticleSystemSet),s.nodeParticleSystemSet.id=o.nodeParticleSystemSet.id,s.nodeParticleSystemSet.uniqueId=o.uniqueId,r.addPendingData(o.id),s.nodeParticleSystemSet.buildAsync(r,!1).then(a=>{r.removePendingData(o.id),s.particleSystemSet=a,a.systems.forEach(c=>{if(Le(c)){let l=c._sizeCreation.process;l&&(c._sizeCreation.process=(p,m)=>{l(p,m),p.scale.x*=100,p.scale.y*=100})}}),a.emitterNode=s,a.start()}))})}))}i(qr,"registerNodeParticleSystemSetParser");var Jr=require("babylonjs");function Zr(e,r){r??=new Jr.ClusteredLightContainer("Clustered Light Container",[],e);let t=e.metadata?.clusteredLight;return t&&(t.lights.length>0&&(r.horizontalTiles=t.horizontalTiles,r.verticalTiles=t.verticalTiles,r.depthSlices=t.depthSlices,r.maxRange=t.maxRange),t.lights.forEach(n=>{let o=e.getLightById(n);o&&r?.addLight(o)})),r}i(Zr,"configureLights");function Tt(e){if(!Array.isArray(e.frames)){let r=[];for(let t of Object.keys(e.frames))r.push({filename:t,...e.frames[t]});e.frames=r}}i(Tt,"normalizeAtlasJson");function so(e,r,t){let o=(e.metadata?.spriteAnimations??[]).find(s=>s.name===r);if(!o)return console.error(`Animation with name "${r}" not found on sprite.`);e.playAnimation(o.from,o.to,o.loop,o.delay,t)}i(so,"playSpriteAnimationFromName");var en=require("babylonjs"),tn=require("babylonjs"),rn=require("babylonjs"),nn=require("babylonjs"),Ot=require("babylonjs"),oe=require("babylonjs"),on=require("babylonjs"),Xr=!1;function sn(){Xr||(Xr=!0,(0,on.AddParser)("SpriteMapNode",(e,r,t,n)=>{e.transformNodes?.forEach(o=>{if(!o.isSpriteMap)return;let s=t.transformNodes?.find(l=>l.id===o.id);if(!s)return;s.isSpriteMap=o.isSpriteMap;let a=`${n}${o.atlasJsonRelativePath}`;r.addPendingData(a);let c=new rn.WebRequest;c.open("GET",a),c.send(),c.addEventListener("load",()=>{r.removePendingData(a);let l=JSON.parse(c.responseText);Tt(l);let p=`${en.Tools.GetFolderPath(a)}${l.meta.image}`,m=new Ot.Texture(p,r,!1,!1,Ot.Texture.NEAREST_NEAREST,null,null,null,!1,tn.Engine.TEXTUREFORMAT_RGBA),u=new nn.SpriteMap(s.name,l,m,{layerCount:o.options.layerCount,stageSize:oe.Vector2.FromArray(o.options.stageSize??[10,1]),outputSize:oe.Vector2.FromArray(o.options.outputSize??[100,100]),colorMultiply:oe.Vector3.FromArray(o.options.colorMultiply??[1,1,1]),flipU:!0},r);o.getClassName=()=>"SpriteMapNode",o.tiles.forEach(g=>{for(let S=0,y=g.repeatCount.x+1;S<y;++S)for(let P=0,A=g.repeatCount.y+1;P<A;++P){let v=S*(g.repeatOffset.x+1),h=P*(g.repeatOffset.y+1);u.changeTiles(g.layer,new oe.Vector2(g.position.x+v,(u.options.stageSize?.y??0)-1-g.position.y-h),g.tile)}});let f=u._output;f.parent=s,s.spriteMap=u})})}))}i(sn,"registerSpriteMapParser");var cn=require("babylonjs"),Dt=require("babylonjs"),pn=require("babylonjs"),mn=require("babylonjs"),an=new Map;async function ln(e,r){let t=e.getWaitingItemsCount();for(;!e.isDisposed&&(!e.isReady()||e.getWaitingItemsCount()>0);){await new Promise(o=>setTimeout(o,150));let n=t-e.getWaitingItemsCount();n===t&&e.textures.forEach(o=>{o.delayLoadState===Dt.Constants.DELAYLOADSTATE_NONE&&(o.delayLoadState=Dt.Constants.DELAYLOADSTATE_LOADED)}),r(n/t)}}i(ln,"waitForWaitingItems");async function ao(e,r,t,n,o){t.loadingQuality=o?.quality??"high",t.loadingTexturesQuality=o?.texturesQuality??t.loadingQuality,t.loadingShadowsQuality=o?.shadowsQuality??t.loadingQuality,t.loadingLodsQuality=o?.lodsQuality??t.loadingQuality,br(),Mr(),_r(),Qr(),sn(),zr(),qr();let s=an.get(t)??{};if(an.set(t,s),await(0,pn.AppendSceneAsync)(`${e}${r}`,t,{pluginExtension:".babylon",onProgress:i(c=>{let l=Math.min(c.loaded/c.total*.5);o?.onProgress?.(l)},"onProgress")}),await ln(t,c=>{o?.onProgress?.(.5+c*.25)}),!o?.skipAssetsPreload){let c=0;do c=await xt(e,t,n);while(c!==0&&!t.isDisposed)}mn.SceneLoaderFlags.ForceFullSceneLoadingForIncremental&&t.meshes.forEach(c=>D(c)&&c._checkDelayState());let a=Zr(t,s.clusteredLightContainer);s.clusteredLightContainer=a,await ln(t,c=>{o?.onProgress?.(.75+c*.25)}),o?.onProgress?.(1),ke(t),ze(t.loadingLodsQuality,t),$e(t),ve(t),t.metadata?.rendering&&(sr(t,t.metadata.rendering),t.activeCamera&&mt(t.activeCamera,e,o?.postProcessConfiguration)),t.metadata?.physicsGravity&&t.getPhysicsEngine()?.setGravity(cn.Vector3.FromArray(t.metadata?.physicsGravity)),F(t,t,n,e),t.transformNodes.forEach(c=>{F(t,c,n,e)}),t.meshes.forEach(c=>{ir(c),F(t,c,n,e)}),t.lights.forEach(c=>{F(t,c,n,e)}),t.cameras.forEach(c=>{F(t,c,n,e)}),t.spriteManagers?.forEach(c=>{c.sprites.forEach(l=>{F(t,l,n,e)})}),re(t)}i(ao,"loadScene");var un=require("babylonjs");async function lo(e,r,t){let n=await N(e+r),s=un.Tools.Instantiate(n.customType).Parse(n,t,e);return s.id=n.id,s.uniqueId=n.uniqueId,s}i(lo,"loadMaterialFromFile");function co(e){return Promise.all(e.materials.map(async r=>{let t=r.getBindedMeshes();await Promise.all(t.map(async n=>{le(n)||await r.forceCompilationAsync(n,{clipPlane:!!e.clipPlane,useInstances:n.hasInstances})}))}))}i(co,"forceCompileAllSceneMaterials");var B=require("babylonjs");function ye(e){if(!isNaN(parseFloat(e))&&isFinite(e))return B.Animation.ANIMATIONTYPE_FLOAT;switch(e?.getClassName?.()){case"Vector2":return B.Animation.ANIMATIONTYPE_VECTOR2;case"Vector3":return B.Animation.ANIMATIONTYPE_VECTOR3;case"Quaternion":return B.Animation.ANIMATIONTYPE_QUATERNION;case"Color3":return B.Animation.ANIMATIONTYPE_COLOR3;case"Color4":return B.Animation.ANIMATIONTYPE_COLOR4;case"Size":return B.Animation.ANIMATIONTYPE_SIZE;case"Matrix":return B.Animation.ANIMATIONTYPE_MATRIX}return null}i(ye,"getAnimationTypeForObject");var dn=require("babylonjs");function po(e){return function(r,t){let n=r.constructor;n._NodesFromScene??=[],n._NodesFromScene.push({propertyKey:t,nodeName:e})}}i(po,"nodeFromScene");function mo(e){return function(r,t){let n=r.constructor;n._ComponentsFromScene??=[],n._ComponentsFromScene.push({propertyKey:t,componentConstructor:e})}}i(mo,"componentFromScene");function uo(e,r=!1){return function(t,n){let o=t.constructor;o._NodesFromDescendants??=[],o._NodesFromDescendants.push({propertyKey:n,nodeName:e,directDescendantsOnly:r})}}i(uo,"nodeFromDescendants");function fo(e){return function(r,t){let n=r.constructor;n._AnimationGroups??=[],n._AnimationGroups.push({animationGroupName:e,propertyKey:t})}}i(fo,"animationGroupFromScene");function go(e){return function(r,t){let n=r.constructor;n._SceneAssets??=[],n._SceneAssets.push({sceneName:e,propertyKey:t})}}i(go,"sceneAsset");function yo(e,r){return function(t,n){let o=t.constructor;o._GuiFromAsset??=[],o._GuiFromAsset.push({propertyKey:n,pathInAssets:e,onGuiCreated:r})}}i(yo,"guiFromAsset");function So(e){return function(r,t){let n=r.constructor;n._SoundsFromScene??=[],n._SoundsFromScene.push({propertyKey:t,soundName:e})}}i(So,"soundFromScene");function ho(e,r=!1){return function(t,n){let o=t.constructor;o._ParticleSystemsFromScene??=[],o._ParticleSystemsFromScene.push({propertyKey:n,particleSystemName:e,directDescendantsOnly:r})}}i(ho,"particleSystemFromScene");function bo(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"boolean"}})}}i(bo,"visibleAsBoolean");function Po(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"string"}})}}i(Po,"visibleAsString");function xo(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"number"}})}}i(xo,"visibleAsNumber");function Ao(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"vector2"}})}}i(Ao,"visibleAsVector2");function vo(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"vector3"}})}}i(vo,"visibleAsVector3");function Co(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"color3"}})}}i(Co,"visibleAsColor3");function Io(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"color4"}})}}i(Io,"visibleAsColor4");function Eo(e,r,t){return function(n,o){let s=n.constructor;s._VisibleInInspector??=[],s._VisibleInInspector.push({label:r,propertyKey:o,configuration:{...t,entityType:e,type:"entity"}})}}i(Eo,"visibleAsEntity");function To(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"texture"}})}}i(To,"visibleAsTexture");function Oo(e,r){return function(t,n){let o=t.constructor;o._VisibleInInspector??=[],o._VisibleInInspector.push({label:e,propertyKey:n,configuration:{...r,type:"keymap"}})}}i(Oo,"visibleAsKeyMap");function Do(e,r,t){return function(n,o){let s=n.constructor;s._VisibleInInspector??=[],s._VisibleInInspector.push({label:r,propertyKey:o,configuration:{...t,assetType:e,type:"asset"}})}}i(Do,"visibleAsAsset");function Mo(e,r){return function(t,n){let o=t.constructor;o._PointerEvents??=[],o._PointerEvents.push({propertyKey:n,options:{mode:"global",...r??{}},eventTypes:Array.isArray(e)?e:[e]})}}i(Mo,"onPointerEvent");function wo(e){return function(r,t){let n=r.constructor;n._KeyboardEvents??=[],n._KeyboardEvents.push({propertyKey:t,eventTypes:Array.isArray(e)?e:[e]})}}i(wo,"onKeyboardEvent");function No(e){return function(r,t){let n=r.constructor;n._SpritesFromSpriteManager??=[],n._SpritesFromSpriteManager.push({propertyKey:t,spriteName:e})}}i(No,"spriteFromSpriteManager");function Fo(e){return function(r,t){let n=r.constructor;n._AnimationsFromSprite??=[],n._AnimationsFromSprite.push({propertyKey:t,animationName:e})}}i(Fo,"animationFromSprite");var Ne=require("babylonjs");function ed(e,r){let t;return e===Ne.Animation.ANIMATIONTYPE_FLOAT?t=r.value:t=r.value.clone(),{value:t,frame:r.frame,interpolation:r.interpolation,inTangent:e===Ne.Animation.ANIMATIONTYPE_FLOAT?r.inTangent:r.inTangent?.clone(),outTangent:e===Ne.Animation.ANIMATIONTYPE_FLOAT?r.outTangent:r.outTangent?.clone()}}i(ed,"cloneKey");function Fe(e,r){let t=r.split("."),n=e;for(let o=0;o<t.length;++o)n=n[t[o]];return n}i(Fe,"getPropertyValue");function Mt(e,r,t){let n=null;e.onAnimationGroupPlayObservable.add(()=>{n=r.onAfterAnimationsObservable.add(()=>{t()})}),e.onAnimationGroupPauseObservable.add(()=>{n&&(r.onAfterAnimationsObservable.remove(n),n=null)}),e.onAnimationGroupEndObservable.add(()=>{n&&(r.onAfterAnimationsObservable.remove(n),n=null)})}i(Mt,"registerAfterAnimationCallback");var G=require("babylonjs"),Re=require("babylonjs"),L=require("babylonjs");function Ro(e,r){return{name:e.name,framesPerSecond:e.framesPerSecond,outputFramesPerSecond:e.outputFramesPerSecond,tracks:e.tracks.map(t=>{let n=null,o=null;if(t.node?(n=ee(t.node,r),n||(n=r.particleSystems?.find(a=>a.id===t.node)??null)):t.defaultRenderingPipeline?n=pe():t.volumetricLightScattering&&(n=je()),t.propertyPath){let a=Fe(n,t.propertyPath);o=ye(a)}let s=null;return t.sound&&(s=ee(t.sound,r)),{node:n,sound:s,propertyPath:t.propertyPath,defaultRenderingPipeline:t.defaultRenderingPipeline,volumetricLightScattering:t.volumetricLightScattering,animationGroupWeight:t.animationGroupWeight,animationGroup:t.animationGroup?r.getAnimationGroupByName(t.animationGroup):null,animationGroups:t.animationGroups,sounds:t.sounds,soundVolume:wt(t.soundVolume??[],G.Animation.ANIMATIONTYPE_FLOAT),keyFrameEvents:t.keyFrameEvents?.map(a=>{let c={...a};switch(a.data?.type){case"set-enabled":c.data={type:"set-enabled",value:a.data.value,node:ee(a.data.node,r)};break;case"apply-impulse":c.data={type:"apply-impulse",radius:a.data.radius,mesh:r.getMeshById(a.data.mesh),force:L.Vector3.FromArray(a.data.force),contactPoint:L.Vector3.FromArray(a.data.contactPoint)};break}return c}),keyFrameAnimations:n&&o!==null&&wt(t.keyFrameAnimations??[],o)}})}}i(Ro,"parseCinematic");function _(e,r){if(e===null)return null;if(e!==void 0)switch(r){case G.Animation.ANIMATIONTYPE_FLOAT:return e;case G.Animation.ANIMATIONTYPE_VECTOR2:return L.Vector2.FromArray(e);case G.Animation.ANIMATIONTYPE_VECTOR3:return L.Vector3.FromArray(e);case G.Animation.ANIMATIONTYPE_QUATERNION:return L.Quaternion.FromArray(e);case G.Animation.ANIMATIONTYPE_COLOR3:return Re.Color3.FromArray(e);case G.Animation.ANIMATIONTYPE_COLOR4:return Re.Color4.FromArray(e);case G.Animation.ANIMATIONTYPE_MATRIX:return L.Matrix.FromArray(e)}}i(_,"parseCinematicKeyValue");function wt(e,r){return e?.map(t=>{let n=t.type==="key"?t:null;if(n)return{...n,value:_(n.value,r),inTangent:_(n.inTangent,r),outTangent:_(n.outTangent,r)};let o=t.type==="cut"?t:null;if(o)return{...o,key1:{...o.key1,value:_(o.key1.value,r),inTangent:_(o.key1.inTangent,r),outTangent:_(o.key1.outTangent,r)},key2:{...o.key2,value:_(o.key2.value,r),inTangent:_(o.key2.inTangent,r),outTangent:_(o.key2.outTangent,r)}};throw new Error(`Unknown key frame type: ${t.type}`)})}i(wt,"parseKeyFrameAnimations");function fn(e,r){e.onEventObservable.notifyObservers(r.eventName)}i(fn,"handleApplyEvent");function gn(e){e.node?.setEnabled(e.value)}i(gn,"handleSetEnabledEvent");var Nt=require("babylonjs"),yn=Nt.Vector3.Zero();function Sn(e,r){let t=r.mesh?[r.mesh]:e.meshes.filter(n=>n.physicsAggregate);r.radius&&(t=t.filter(n=>{let o=n.getBoundingInfo().boundingBox.centerWorld;return Nt.Vector3.Distance(o,r.contactPoint)<=r.radius})),t.forEach(n=>{if(n.physicsAggregate?.body){let o=r.contactPoint.subtract(n.getBoundingInfo().boundingBox.centerWorld);o.multiplyInPlace(r.force),n.physicsAggregate.body.setLinearVelocity(yn),n.physicsAggregate.body.setAngularVelocity(yn),n.physicsAggregate.body.applyImpulse(o.negateInPlace(),r.contactPoint)}})}i(Sn,"handleApplyImpulseEvent");var hn=require("babylonjs"),bn=require("babylonjs"),Se=class extends bn.AnimationGroup{static{i(this,"Cinematic")}onEventObservable=new hn.Observable;onEvent(r,t){this.onEventObservable.add(n=>{r===n&&t()})}};function Ft(e){return e.type==="key"}i(Ft,"isCinematicKey");function ie(e){return e.type==="cut"}i(ie,"isCinematicKeyCut");function _o(e){return e.type==="event"}i(_o,"isCinematicKeyEvent");function Lo(e){return e.type==="group"}i(Lo,"isCinematicGroup");function Vo(e){return e.type==="sound"}i(Vo,"isCinematicSound");var C=require("babylonjs"),se=require("babylonjs");function Bo(e,r,t){let n=new Se(e.name,r);return e.tracks.forEach(o=>{let s=o.animationGroup;if(s&&o.animationGroups?.length){let f=s.clone(`${s.name}-cinematic-temp`),g=r.animationGroups.indexOf(f);g!==-1&&r.animationGroups.splice(g,1),n.onAnimationEndObservable.add(()=>{s.stop(),f.stop()});let S=o.animationGroups.reduce((v,h)=>Math.min(v,h.frame),Number.MAX_VALUE)??0,y=o.animationGroups.reduce((v,h)=>Math.max(v,h.frame+h.endFrame),0)??0,P={frame:S},A=new C.Animation(f.name,"frame",60,C.Animation.ANIMATIONTYPE_FLOAT,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1);if(A.setKeys([{frame:S,value:0},{frame:y,value:y}]),o.animationGroups.forEach(v=>{A.addEvent(new se.AnimationEvent(v.frame,()=>{let h=v.repeatCount??0;if(f.to=v.endFrame,f.speedRatio=v.speed,f.stop(),f.play(h>0),f.from!==v.startFrame&&f.goToFrame(v.startFrame),h){let w=0;f.onAnimationGroupLoopObservable.add(()=>{++w,w>h&&f.stop()})}}))}),n.addTargetedAnimation(A,P),(o.animationGroupWeight?.length??0)>=2&&o.animationGroupWeight.find(h=>ie(h)?h.key1.value!==1||h.key2.value!==1:h.value!==1)){let h={weight:0},w=new C.Animation(`${f.name}-weights`,"weight",60,C.Animation.ANIMATIONTYPE_FLOAT,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1),K=[];o.animationGroupWeight.forEach(ae=>{ie(ae)?(K.push(ae.key1),K.push(ae.key2)):K.push(ae)}),w.setKeys(K),n.addTargetedAnimation(w,h),Mt(n,r,()=>{f.weight=h.weight})}}let a=o.sound;if(!t?.ignoreSounds&&a&&a.sound?.buffer&&o.sounds?.length){let f={dummy:0,volume:0},g=new C.Animation(a.name,"dummy",60,C.Animation.ANIMATIONTYPE_FLOAT,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1),S=0;if(o.sounds?.forEach(y=>{let P=y.endFrame-y.startFrame;S=Math.max(S,y.frame+P),g.addEvent(new se.AnimationEvent(y.frame,A=>{let h=(A-y.frame+y.startFrame)/e.framesPerSecond;a.play({startOffset:h})},!1)),g.addEvent(new se.AnimationEvent(y.frame+P,()=>{a.stop()}))}),g.setKeys([{frame:0,value:0},{frame:S,value:S}]),n.addTargetedAnimation(g,f),(o.soundVolume?.length??0)>=2){let y=new C.Animation(a.name,"volume",60,C.Animation.ANIMATIONTYPE_FLOAT,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1),P=[];o.soundVolume.forEach(A=>{ie(A)?(P.push(A.key1),P.push(A.key2)):P.push(A)}),y.setKeys(P),n.addTargetedAnimation(y,f),Mt(n,r,()=>{a.volume=f.volume})}}if(o.keyFrameEvents){let f={dummy:0},g=new C.Animation("events","dummy",60,C.Animation.ANIMATIONTYPE_FLOAT,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1),S=0;o.keyFrameEvents?.forEach(y=>{S=Math.max(S,y.frame),g.addEvent(new se.AnimationEvent(y.frame,()=>{switch(y.data?.type){case"event":fn(n,y.data);break;case"set-enabled":gn(y.data);break;case"apply-impulse":Sn(r,y.data);break}}))}),g.setKeys([{frame:0,value:0},{frame:S+1,value:S+1}]),n.addTargetedAnimation(g,f)}let c=o.defaultRenderingPipeline?pe():o.node;if(!c||!o.propertyPath||!o.keyFrameAnimations)return;let l=Fe(c,o.propertyPath),p=ye(l);if(p===null)return;let m=new C.Animation(o.propertyPath,o.propertyPath,60,p,C.Animation.ANIMATIONLOOPMODE_CYCLE,!1),u=[];o.keyFrameAnimations?.forEach(f=>{if(Ft(f))return u.push(f);ie(f)&&(u.push(f.key1),u.push(f.key2),xe(c)&&o.propertyPath==="position"&&m.addEvent(new se.AnimationEvent(f.key1.frame,()=>{let g=nt();if(!g)return;let S=g.motionStrength;g.motionStrength=0,requestAnimationFrame(()=>{g.motionStrength=S})})))}),m.setKeys(u),n.addTargetedAnimation(m,c)}),n.normalize(),n}i(Bo,"generateCinematicAnimationGroup");async function Rt(e,r){return new Promise((t,n)=>{let o=indexedDB.open(e,1);o.addEventListener("error",()=>n()),o.addEventListener("blocked",()=>n()),o.addEventListener("upgradeneeded",()=>{try{r(o.result)}catch(s){n(s)}}),o.addEventListener("success",()=>{t(o.result)})})}i(Rt,"openIndexDB");function he(e,r,t){return new Promise(n=>{let s=e.transaction(r).objectStore(r).get(t);s.addEventListener("error",()=>{n(null)}),s.addEventListener("success",()=>{n(s.result??null)})})}i(he,"getFromIndexDB");async function V(e,r,t){let o=e.transaction(r,"readwrite").objectStore(r).put(t);await new Promise((s,a)=>{o.addEventListener("error",()=>a()),o.addEventListener("success",()=>s())})}i(V,"putInIndexDB");var Pn=require("babylonjs");function Go(e){Pn.AbstractEngine.OfflineProviderFactory=(r,t,n=!1)=>new be(e,r,t,n)}i(Go,"setupOfflineProvider");async function _t(e,r){let t=await new Promise(n=>{let o=new be(e,r,s=>n(s?o:null),!1)});return await t?.open(),t}i(_t,"createAndOpenDatabase");var be=class{static{i(this,"Database")}enableSceneOffline=!0;enableTexturesOffline=!0;name;_database=null;_manifestVersion=null;_loadFilePromises=new Map;constructor(r,t,n,o){this.name=r,o?n(!1):this._checkManifest(t,n)}async _checkManifest(r,t){try{let n=await N(`${r}.manifest?${Date.now()}`);this._manifestVersion=n.version,t(!0)}catch{this.enableSceneOffline=!1,this.enableTexturesOffline=!1,t(!1)}}async open(r,t){try{this._database=await Rt(this.name,n=>{n.createObjectStore("files",{keyPath:"url"}),n.createObjectStore("images",{keyPath:"url"}),n.createObjectStore("versions",{keyPath:"url"})}),r?.()}catch{t?.()}}close(){this._database?.close(),this._database=null,this._loadFilePromises.clear()}async loadImage(r,t){if(!this._database){t.src=r;return}let n=null;await gt(()=>this._manifestVersion!==null);let o=this._loadFilePromises.get(r);if(o)return o.then(a=>{a!==null?t.src=a:t.src=r});let s=new Promise(async a=>{if(await this._getFileVersionForUrl(r)!==this._manifestVersion?(n=await X(r,"blob"),await Promise.all([V(this._database,"images",{url:r,data:n}),V(this._database,"versions",{url:r,version:this._manifestVersion})])):n=(await he(this._database,"images",r))?.data??null,n!==null){let l=URL.createObjectURL(n);t.src=l}else t.src=r;a(t.src)});this._loadFilePromises.set(r,s)}async saveImage(r){if(!this._database)throw new Error("Database is not available");let t=await X(r,"blob");await Promise.all([V(this._database,"images",{url:r,data:t}),V(this._database,"versions",{url:r,version:this._manifestVersion})])}async isFileMatchingVersion(r){return await this._getFileVersionForUrl(r)===this._manifestVersion}async loadFile(r,t,n,o,s){if(!this._database)return o?.();let a=null;await gt(()=>this._manifestVersion!==null);let c=this._loadFilePromises.get(r);if(c)return c.then(p=>{p!==null?t(p):o?.()});let l=new Promise(async p=>{await this._getFileVersionForUrl(r)!==this._manifestVersion?(a=await X(r,s?"arraybuffer":"text",n),await Promise.all([V(this._database,"files",{url:r,data:a}),V(this._database,"versions",{url:r,version:this._manifestVersion})])):a=(await he(this._database,"files",r))?.data??null,a!==null?t(a):o?.(),p(a)});this._loadFilePromises.set(r,l)}async saveFile(r,t,n){if(!this._database)throw new Error("Database is not available");let o=await X(r,t?"arraybuffer":"text",n);await Promise.all([V(this._database,"files",{url:r,data:o}),V(this._database,"versions",{url:r,version:this._manifestVersion})])}async _getFileVersionForUrl(r){return(await he(this._database,"versions",r))?.version??null}};var xn=["mp3","wav"],An=["babylonbinarymeshdata"],Ko=["ktx","ktx2","jpg","jpeg","png","bmp","webp"],vn=["babylon","json"],Lt=["jpg","jpeg","png","bmp","webp"],Cn=["bin","ktx","ktx2",...An,...xn],ko=[...vn,...Lt,...Cn];async function zo(e,r,t){let n=[],o=await N(`${r}scenes-used-files.json`),s=[];if(t?.scenesFilter){s=t.scenesFilter.map(u=>typeof u=="string"?{sceneName:u,disableSounds:!1,disableTextures:!1,disableGeometries:!1}:u);for(let[u,f]of Object.entries(o))s.find(g=>g.sceneName===u)||delete o[u]}let a=0,c=0,l=t?.engine?.textureFormatInUse?t?.engine?.texturesSupported[0]:null,p=Object.values(o).reduce((u,f)=>u+f.length,0);function m(u){++c,t?.onProgress?.(c/p),u?.()}i(m,"notifyProgress");for(let[u,f]of Object.entries(o)){let g=u.replace(".scene",".babylon"),S=await _t(e,`${r}${g}`);if(!S)continue;let y=s.find(P=>P.sceneName===u);for(let P=0,A=f.length;P<A;++P){let v=f[P],h=v.split(".").pop()?.toLowerCase();if(!h){m();continue}if(An.includes(h)&&y?.disableGeometries){m();continue}if(Ko.includes(h)&&y?.disableTextures){m();continue}if(xn.includes(h)&&y?.disableSounds){m();continue}if(Lt.includes(h)&&y?.disableTextures){m();continue}if(h==="ktx")if(l){if(!v.endsWith(l)){m();continue}}else{m();continue}if(h==="ktx2"&&!ge()){m();continue}if(n.length>300){try{await Promise.all(n)}catch{}n.splice(0,n.length)}let w=`${r}${v}`;ko.includes(h)&&n.push(new Promise(async K=>{if(await S.isFileMatchingVersion(w))return m(K);try{Lt.includes(h)?t?.disableImages||(await S.saveImage(w),++a):Cn.includes(h)?(await S.saveFile(w,!0),++a):vn.includes(h)&&(await S.saveFile(w,!1),++a)}catch{}m(K)}))}await Promise.all(n),S.close()}return await Promise.all(n),{loadedCount:a,processedFilesCount:c}}i(zo,"preloadAssetsToDatabase");0&&(module.exports={AdvancedAssetContainer,AdvancedAssetContainerInstantiatedEntries,Cinematic,Database,NodeParticleSystemSet,_applyScriptsForObject,_getKtx2TextureName,_preloadScriptsAssets,_registerScriptInstance,_removeRegisteredScriptInstance,addExcludedCompressedTexture,animationFromSprite,animationGroupFromScene,applyMeshesLODQuality,applyRenderingConfigurationForCamera,applyScriptOnObject,applyShadowsQuality,applyTexturesQuality,componentFromScene,configureEngineToUseCompressedTextures,configureMeshDistanceOrScreenCoverage,configureShadowMapRefreshRate,configureShadowMapRenderListPredicate,copyAndParseRagdollConfiguration,createAndOpenDatabase,createDefaultRenderingPipeline,createMotionBlurPostProcess,createSSAO2RenderingPipeline,createSSRRenderingPipeline,createTAARenderingPipeline,createVLSPostProcess,defaultPipelineCameraConfigurations,disposeDefaultRenderingPipeline,disposeMotionBlurPostProcess,disposeSSAO2RenderingPipeline,disposeSSRRenderingPipeline,disposeTAARenderingPipeline,disposeVLSPostProcess,forceCompileAllSceneMaterials,generateCinematicAnimationGroup,getAllScriptsByClassForObject,getAnimationTypeForObject,getDefaultRenderingPipeline,getFromIndexDB,getMotionBlurPostProcess,getPowerOfTwoUntil,getSSAO2RenderingPipeline,getSSRRenderingPipeline,getScriptByClassForObject,getTAARenderingPipeline,getTextureUrl,getVLSPostProcess,guiFromAsset,isAbstractMesh,isAnyParticleSystem,isArcRotateCamera,isBone,isCamera,isCinematicGroup,isCinematicKey,isCinematicKeyCut,isCinematicKeyEvent,isCinematicSound,isClusteredLightContainer,isDecalMesh,isDirectionalLight,isFreeCamera,isGPUParticleSystem,isGaussianSplattingMesh,isGroundMesh,isHemisphericLight,isInstancedMesh,isLight,isMesh,isNode,isNodeFromStaticGroup,isParticleSystem,isPointLight,isScene,isSoundNode,isSpotLight,isSprite,isTexture,isTransformNode,isUsingKtx2CompressedTextures,loadMaterialFromFile,loadScene,motionBlurPostProcessCameraConfigurations,nodeFromDescendants,nodeFromScene,normalizeAtlasJson,onKeyboardEvent,onPointerEvent,openIndexDB,parseCinematic,parseCinematicKeyValue,parseDefaultRenderingPipeline,parseKeyFrameAnimations,parseMotionBlurPostProcess,parseRagdollConfiguration,parseSSAO2RenderingPipeline,parseSSRRenderingPipeline,parseTAARenderingPipeline,parseVLSPostProcess,particleSystemFromScene,playSpriteAnimationFromName,preloadAssetsToDatabase,putInIndexDB,registerScriptAssetParser,saveRenderingConfigurationForCamera,sceneAsset,scriptAssetsCache,scriptAssetsParsers,scriptsDictionary,serializeDefaultRenderingPipeline,serializeMotionBlurPostProcess,serializeSSAO2RenderingPipeline,serializeSSRRenderingPipeline,serializeTAARenderingPipeline,serializeVLSPostProcess,setDefaultRenderingPipelineRef,setMotionBlurPostProcessRef,setSSAO2RenderingPipelineRef,setSSRRenderingPipelineRef,setStaticDecalsEnabled,setTAARenderingPipelineRef,setUseKtx2CompressedTextures,setVLSPostProcessRef,setupOfflineProvider,soundFromScene,spriteFromSpriteManager,ssaoRenderingPipelineCameraConfigurations,ssrRenderingPipelineCameraConfigurations,taaRenderingPipelineCameraConfigurations,visibleAsAsset,visibleAsBoolean,visibleAsColor3,visibleAsColor4,visibleAsEntity,visibleAsKeyMap,visibleAsNumber,visibleAsString,visibleAsTexture,visibleAsVector2,visibleAsVector3,vlsPostProcessCameraConfigurations});
|
|
1
|
+
var We=Object.defineProperty;var nn=Object.getOwnPropertyDescriptor;var an=Object.getOwnPropertyNames;var sn=Object.prototype.hasOwnProperty;var n=(t,e)=>We(t,"name",{value:e,configurable:!0});var ln=(t,e)=>{for(var i in e)We(t,i,{get:e[i],enumerable:!0})},cn=(t,e,i,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of an(e))!sn.call(t,r)&&r!==i&&We(t,r,{get:()=>e[r],enumerable:!(o=nn(e,r))||o.enumerable});return t};var pn=t=>cn(We({},"__esModule",{value:!0}),t);var Wa={};ln(Wa,{AdvancedAssetContainer:()=>Fe,AdvancedAssetContainerInstantiatedEntries:()=>Ve,Cinematic:()=>ze,Database:()=>ke,NodeParticleSystemSet:()=>Xr.NodeParticleSystemSet,VolumetricDebugMode:()=>lo,VolumetricDitherMode:()=>Jt,VolumetricFogMode:()=>ei,VolumetricLightingRenderingPipeline:()=>Y,VolumetricShadowKind:()=>ni,VolumetricShadowMode:()=>go,VolumetricStepDistribution:()=>so,VolumetricTransmittanceMode:()=>ai,_applyScriptsForObject:()=>B,_getKtx2TextureName:()=>lt,_preloadScriptsAssets:()=>Di,_registerScriptInstance:()=>Pi,_removeRegisteredScriptInstance:()=>nt,addExcludedCompressedTexture:()=>ct,animationFromSprite:()=>Ra,animationGroupFromScene:()=>ua,applyMeshesLODQuality:()=>wt,applyRenderingConfigurationForCamera:()=>fi,applyScriptOnObject:()=>ra,applyShadowsQuality:()=>vn,applyTexturesQuality:()=>sa,componentFromScene:()=>da,computeVolumetricBudget:()=>Ae,computeVolumetricShapeKey:()=>Rn,configureEngineToUseCompressedTextures:()=>aa,configureMeshDistanceOrScreenCoverage:()=>_t,configureShadowMapRefreshRate:()=>Ke,configureShadowMapRenderListPredicate:()=>Pt,copyAndParseRagdollConfiguration:()=>vi,createAndOpenDatabase:()=>Gi,createDefaultRenderingPipeline:()=>ao,createMotionBlurPostProcess:()=>to,createSSAO2RenderingPipeline:()=>Ji,createSSRRenderingPipeline:()=>Zi,createTAARenderingPipeline:()=>qi,createVLSPostProcess:()=>Ki,createVolumetricLightingRenderingPipeline:()=>Io,defaultPipelineCameraConfigurations:()=>ue,disposeDefaultRenderingPipeline:()=>$t,disposeMotionBlurPostProcess:()=>kt,disposeSSAO2RenderingPipeline:()=>Gt,disposeSSRRenderingPipeline:()=>It,disposeTAARenderingPipeline:()=>Vt,disposeVLSPostProcess:()=>Et,disposeVolumetricLightingRenderingPipeline:()=>mi,ensureVolumetricLightConfiguration:()=>po,forceCompileAllSceneMaterials:()=>ma,generateCinematicAnimationGroup:()=>Ba,getAllScriptsByClassForObject:()=>Ce,getAllVolumetricCandidateLights:()=>vo,getAnimationTypeForObject:()=>Be,getDefaultRenderingPipeline:()=>Ee,getDefaultVolumetricLightConfiguration:()=>qt,getDefaultVolumetricLightingConfiguration:()=>je,getFromIndexDB:()=>He,getMotionBlurPostProcess:()=>Ht,getPowerOfTwoUntil:()=>F,getSSAO2RenderingPipeline:()=>Cn,getSSRRenderingPipeline:()=>yn,getScriptByClassForObject:()=>wi,getTAARenderingPipeline:()=>xn,getTextureUrl:()=>pt,getVLSPostProcess:()=>Ot,getVolumetricLightConfiguration:()=>ii,getVolumetricLightRange:()=>qe,getVolumetricLightSteps:()=>ti,getVolumetricLightWorldDirection:()=>Te,getVolumetricLightWorldPosition:()=>Ye,getVolumetricLightingRenderingPipeline:()=>To,guiFromAsset:()=>va,isAbstractMesh:()=>ie,isAnyParticleSystem:()=>xt,isArcRotateCamera:()=>fn,isBone:()=>mn,isCamera:()=>Xe,isCascadedShadowGenerator:()=>St,isCinematicGroup:()=>Na,isCinematicKey:()=>Fi,isCinematicKeyCut:()=>_e,isCinematicKeyEvent:()=>Fa,isCinematicSound:()=>Ga,isClusteredLightContainer:()=>le,isDecalMesh:()=>Hi,isDirectionalLight:()=>ee,isFreeCamera:()=>dn,isGPUParticleSystem:()=>un,isGaussianSplattingMesh:()=>Ct,isGroundMesh:()=>hn,isHemisphericLight:()=>$e,isInstancedMesh:()=>Pe,isLight:()=>zi,isMesh:()=>V,isNode:()=>ce,isNodeFromStaticGroup:()=>Dt,isParticleSystem:()=>bt,isPointLight:()=>gt,isScene:()=>yt,isShadowGenerator:()=>vt,isSoundNode:()=>re,isSpotLight:()=>oe,isSprite:()=>Lt,isTexture:()=>Oe,isTransformNode:()=>J,isUsingKtx2CompressedTextures:()=>Ge,isVolumetricLightEnabled:()=>Pn,isVolumetricLightSupported:()=>Vn,isVolumetricLightingSupported:()=>qn,loadMaterialFromFile:()=>pa,loadScene:()=>ca,markVolumetricLightsDirty:()=>Qn,maxVolumetricArrayLights:()=>$,maxVolumetricDirectionalLights:()=>Qt,maxVolumetricShadowSlots:()=>A,motionBlurPostProcessCameraConfigurations:()=>fe,nodeFromDescendants:()=>fa,nodeFromScene:()=>ha,normalizeAtlasJson:()=>Ei,normalizeVolumetricLightConfiguration:()=>co,normalizeVolumetricLightingConfiguration:()=>ge,onKeyboardEvent:()=>Ia,onPointerEvent:()=>Ta,openIndexDB:()=>Ni,parseCinematic:()=>Va,parseCinematicKeyValue:()=>k,parseDefaultRenderingPipeline:()=>jt,parseKeyFrameAnimations:()=>Ri,parseMotionBlurPostProcess:()=>Wt,parseRagdollConfiguration:()=>Go,parseSSAO2RenderingPipeline:()=>zt,parseSSRRenderingPipeline:()=>Rt,parseTAARenderingPipeline:()=>Nt,parseVLSPostProcess:()=>Tt,parseVolumetricLightingRenderingPipeline:()=>di,particleSystemFromScene:()=>ya,playSpriteAnimationFromName:()=>la,preloadAssetsToDatabase:()=>Ua,putInIndexDB:()=>W,registerScriptAssetParser:()=>oa,resolveVolumetricShadowSlot:()=>So,saveRenderingConfigurationForCamera:()=>Jn,sceneAsset:()=>ga,scriptAssetsCache:()=>I,scriptAssetsParsers:()=>Ne,scriptsDictionary:()=>H,selectVolumetricLights:()=>si,serializeDefaultRenderingPipeline:()=>Kt,serializeMotionBlurPostProcess:()=>Ut,serializeSSAO2RenderingPipeline:()=>Bt,serializeSSRRenderingPipeline:()=>Mt,serializeTAARenderingPipeline:()=>Ft,serializeVLSPostProcess:()=>At,serializeVolumetricLightingRenderingPipeline:()=>hi,setDefaultRenderingPipelineRef:()=>wn,setMotionBlurPostProcessRef:()=>_n,setSSAO2RenderingPipelineRef:()=>Dn,setSSRRenderingPipelineRef:()=>bn,setStaticDecalsEnabled:()=>gn,setTAARenderingPipelineRef:()=>Ln,setUseKtx2CompressedTextures:()=>na,setVLSPostProcessRef:()=>Sn,setVolumetricLightingRenderingPipelineRef:()=>Yn,setupOfflineProvider:()=>za,soundFromScene:()=>Sa,spriteFromSpriteManager:()=>Ma,ssaoRenderingPipelineCameraConfigurations:()=>de,ssrRenderingPipelineCameraConfigurations:()=>me,taaRenderingPipelineCameraConfigurations:()=>he,visibleAsAsset:()=>Aa,visibleAsBoolean:()=>ba,visibleAsColor3:()=>_a,visibleAsColor4:()=>wa,visibleAsEntity:()=>Pa,visibleAsKeyMap:()=>Ea,visibleAsNumber:()=>La,visibleAsString:()=>xa,visibleAsTexture:()=>Oa,visibleAsVector2:()=>Ca,visibleAsVector3:()=>Da,vlsPostProcessCameraConfigurations:()=>pe,volumetricLightMetadataKey:()=>ne,volumetricLightingRenderingPipelineCameraConfigurations:()=>Se});module.exports=pn(Wa);function ie(t){switch(t.getClassName?.()){case"Mesh":case"LineMesh":case"GroundMesh":case"InstancedMesh":return!0}return!1}n(ie,"isAbstractMesh");function V(t){switch(t.getClassName?.()){case"Mesh":case"GroundMesh":return!0}return!1}n(V,"isMesh");function Pe(t){return t.getClassName?.()==="InstancedMesh"}n(Pe,"isInstancedMesh");function mn(t){return t.getClassName?.()==="Bone"}n(mn,"isBone");function hn(t){return t.getClassName?.()==="GroundMesh"}n(hn,"isGroundMesh");function J(t){return t.getClassName?.()==="TransformNode"}n(J,"isTransformNode");function Oe(t){return t?.getClassName?.()==="Texture"}n(Oe,"isTexture");function Xe(t){switch(t.getClassName?.()){case"Camera":case"FreeCamera":case"TargetCamera":case"EditorCamera":case"ArcRotateCamera":case"UniversalCamera":return!0}return!1}n(Xe,"isCamera");function dn(t){switch(t.getClassName?.()){case"FreeCamera":case"UniversalCamera":return!0}return!1}n(dn,"isFreeCamera");function fn(t){return t.getClassName?.()==="ArcRotateCamera"}n(fn,"isArcRotateCamera");function gt(t){return t.getClassName?.()==="PointLight"}n(gt,"isPointLight");function ee(t){return t.getClassName?.()==="DirectionalLight"}n(ee,"isDirectionalLight");function oe(t){return t.getClassName?.()==="SpotLight"}n(oe,"isSpotLight");function $e(t){return t.getClassName?.()==="HemisphericLight"}n($e,"isHemisphericLight");function zi(t){switch(t.getClassName?.()){case"Light":case"PointLight":case"SpotLight":case"DirectionalLight":case"HemisphericLight":return!0}return!1}n(zi,"isLight");function vt(t){return t.getClassName?.()==="ShadowGenerator"}n(vt,"isShadowGenerator");function St(t){return t.getClassName?.()==="CascadedShadowGenerator"}n(St,"isCascadedShadowGenerator");function le(t){return t.getClassName?.()==="ClusteredLightContainer"}n(le,"isClusteredLightContainer");function ce(t){return ie(t)||J(t)||zi(t)||Xe(t)}n(ce,"isNode");function yt(t){return t.getClassName?.()==="Scene"}n(yt,"isScene");function bt(t){return t.getClassName?.()==="ParticleSystem"}n(bt,"isParticleSystem");function un(t){return t.getClassName?.()==="GPUParticleSystem"}n(un,"isGPUParticleSystem");function xt(t){switch(t.getClassName?.()){case"ParticleSystem":case"GPUParticleSystem":return!0}return!1}n(xt,"isAnyParticleSystem");function Lt(t){return t.getClassName?.()==="Sprite"}n(Lt,"isSprite");function re(t){return t.getClassName?.()==="SoundNode"}n(re,"isSoundNode");function Ct(t){return t.getClassName?.()==="GaussianSplattingMesh"}n(Ct,"isGaussianSplattingMesh");function Dt(t){let e=t;for(;e;){if(e.metadata?.isStaticGroup)return!0;e=e.parent}return!1}n(Dt,"isNodeFromStaticGroup");function _t(t){t.meshes.forEach(e=>{V(e)&&e.getLODLevels().forEach(i=>{i.mesh&&(i.mesh.originalDistanceOrScreenCoverage=i.distanceOrScreenCoverage)})})}n(_t,"configureMeshDistanceOrScreenCoverage");function wt(t,e){e.meshes.forEach(i=>{V(i)&&i.getLODLevels().forEach(o=>{if(o.mesh?.originalDistanceOrScreenCoverage)switch(t){case"very-low":o.distanceOrScreenCoverage=o.mesh.originalDistanceOrScreenCoverage*.125;break;case"low":o.distanceOrScreenCoverage=o.mesh.originalDistanceOrScreenCoverage*.25;break;case"medium":o.distanceOrScreenCoverage=o.mesh.originalDistanceOrScreenCoverage*.5;break;case"high":o.distanceOrScreenCoverage=o.mesh.originalDistanceOrScreenCoverage;break}})})}n(wt,"applyMeshesLODQuality");function Hi(t){return(t.metadata?.decal??null)!==null}n(Hi,"isDecalMesh");function gn(t,e){e.meshes.forEach(i=>{Hi(i)&&Dt(i)&&i.setEnabled(t)})}n(gn,"setStaticDecalsEnabled");function F(t){let e=1;for(;e<=t;)e<<=1;return e>>1}n(F,"getPowerOfTwoUntil");var ki=require("babylonjs"),Ui=require("babylonjs");function Pt(t){t.lights.forEach(e=>{let i=e.getShadowGenerator()?.getShadowMap();i&&(i.renderListPredicate=o=>Ct(o)?!1:ki.Vector3.Distance(o.getAbsolutePosition(),e.getAbsolutePosition())<=e.range)})}n(Pt,"configureShadowMapRenderListPredicate");async function Ke(t){t.executeWhenReady(()=>{t.lights.forEach(e=>{let i=e.getShadowGenerator()?.getShadowMap();i&&(i.refreshRate=e.metadata?.refreshRate??Ui.RenderTargetTexture.REFRESHRATE_RENDER_ONEVERYFRAME)})})}n(Ke,"configureShadowMapRefreshRate");function vn(t,e){e.lights.forEach(i=>{let o=i.getShadowGenerator(),r=o?.getShadowMap();if(o?.originalMapSize){let a=o.originalMapSize;switch(t){case"medium":a=a*.5;break;case"low":a=a*.25;break;case"very-low":a=a*.125;break}a=Math.max(128,F(a)),r?.getSize().width!==a&&r.resize(a)}}),Ke(e)}n(vn,"applyShadowsQuality");var Wi=require("babylonjs"),Xi=require("babylonjs"),$i=require("babylonjs"),O=null,pe=new Map;function Ot(){return O}n(Ot,"getVLSPostProcess");function Sn(t){O=t}n(Sn,"setVLSPostProcessRef");function Et(t){O&&t.activeCamera&&(O.dispose(t.activeCamera),O=null)}n(Et,"disposeVLSPostProcess");function Ki(t,e){return e??=t.meshes.find(i=>V(i)),O=new $i.VolumetricLightScatteringPostProcess("VolumetricLightScatteringPostProcess",1,t.activeCamera,e,100,Xi.Texture.BILINEAR_SAMPLINGMODE,t.getEngine(),!1),O}n(Ki,"createVLSPostProcess");function At(){return O?{meshId:O.mesh?.id,exposure:O.exposure,decay:O.decay,weight:O.weight,density:O.density,invert:O.invert,useCustomMeshPosition:O.useCustomMeshPosition,customMeshPosition:O.customMeshPosition.asArray()}:null}n(At,"serializeVLSPostProcess");function Tt(t,e){let i=null;if(e.meshId){let r=t.getMeshById(e.meshId);r&&V(r)&&(i=r)}let o=Ki(t,i);return o.exposure=e.exposure,o.decay=e.decay,o.weight=e.weight,o.density=e.density,o.invert=e.invert,o.useCustomMeshPosition=e.useCustomMeshPosition,o.customMeshPosition.copyFrom(Wi.Vector3.FromArray(e.customMeshPosition)),o}n(Tt,"parseVLSPostProcess");var ji=require("babylonjs"),D=null,me=new Map;function yn(){return D}n(yn,"getSSRRenderingPipeline");function bn(t){D=t}n(bn,"setSSRRenderingPipelineRef");function It(){D&&(D.dispose(),D=null)}n(It,"disposeSSRRenderingPipeline");function Zi(t,e){return D=new ji.SSRRenderingPipeline("SSRRenderingPipeline",t,[e]),D.samples=4,D}n(Zi,"createSSRRenderingPipeline");function Mt(){return D?{samples:D.samples,step:D.step,thickness:D.thickness,strength:D.strength,reflectionSpecularFalloffExponent:D.reflectionSpecularFalloffExponent,maxSteps:D.maxSteps,maxDistance:D.maxDistance,roughnessFactor:D.roughnessFactor,reflectivityThreshold:D.reflectivityThreshold,blurDispersionStrehgth:D.blurDispersionStrength,clipToFrustum:D.clipToFrustum,enableSmoothReflections:D.enableSmoothReflections,enableAutomaticThicknessComputation:D.enableAutomaticThicknessComputation,attenuateFacingCamera:D.attenuateFacingCamera,attenuateScreenBorders:D.attenuateScreenBorders,attenuateIntersectionDistance:D.attenuateIntersectionDistance,attenuateBackfaceReflection:D.attenuateBackfaceReflection,blurDownsample:D.blurDownsample,selfCollisionNumSkip:D.selfCollisionNumSkip,ssrDownsample:D.ssrDownsample,backfaceDepthTextureDownsample:D.backfaceDepthTextureDownsample}:null}n(Mt,"serializeSSRRenderingPipeline");function Rt(t,e,i){if(D)return D;let o=Zi(t,e);return o.samples=i.samples,o.step=i.step,o.thickness=i.thickness,o.strength=i.strength,o.reflectionSpecularFalloffExponent=i.reflectionSpecularFalloffExponent,o.maxSteps=i.maxSteps,o.maxDistance=i.maxDistance,o.roughnessFactor=i.roughnessFactor,o.reflectivityThreshold=i.reflectivityThreshold,o.blurDispersionStrength=i.blurDispersionStrehgth,o.clipToFrustum=i.clipToFrustum,o.enableSmoothReflections=i.enableSmoothReflections,o.enableAutomaticThicknessComputation=i.enableAutomaticThicknessComputation,o.attenuateFacingCamera=i.attenuateFacingCamera,o.attenuateScreenBorders=i.attenuateScreenBorders,o.attenuateIntersectionDistance=i.attenuateIntersectionDistance,o.attenuateBackfaceReflection=i.attenuateBackfaceReflection,o.blurDownsample=i.blurDownsample,o.selfCollisionNumSkip=i.selfCollisionNumSkip,o.ssrDownsample=i.ssrDownsample,o.backfaceDepthTextureDownsample=i.backfaceDepthTextureDownsample,o}n(Rt,"parseSSRRenderingPipeline");var Yi=require("babylonjs"),E=null,he=new Map;function xn(){return E}n(xn,"getTAARenderingPipeline");function Ln(t){E=t}n(Ln,"setTAARenderingPipelineRef");function Vt(){E&&(E.dispose(),E=null)}n(Vt,"disposeTAARenderingPipeline");function qi(t,e){return E=new Yi.TAARenderingPipeline("TAARenderingPipeline",t,[e]),E.samples=4,E}n(qi,"createTAARenderingPipeline");function Ft(){return E?{factor:E.factor,samples:E.samples,clampHistory:E.clampHistory,reprojectHistory:E.reprojectHistory,disableOnCameraMove:E.disableOnCameraMove}:null}n(Ft,"serializeTAARenderingPipeline");function Nt(t,e,i){if(E)return E;let o=qi(t,e);return o.factor=i.factor,o.samples=i.samples,o.clampHistory=i.clampHistory,o.reprojectHistory=i.reprojectHistory,o.disableOnCameraMove=i.disableOnCameraMove,o}n(Nt,"parseTAARenderingPipeline");var Qi=require("babylonjs"),w=null,de=new Map;function Cn(){return w}n(Cn,"getSSAO2RenderingPipeline");function Dn(t){w=t}n(Dn,"setSSAO2RenderingPipelineRef");function Gt(){w&&(w.dispose(),w=null)}n(Gt,"disposeSSAO2RenderingPipeline");function Ji(t,e){return w=new Qi.SSAO2RenderingPipeline("SSAO2RenderingPipeline",t,1,[e]),w.samples=4,w}n(Ji,"createSSAO2RenderingPipeline");function Bt(){return w?{radius:w.radius,totalStrength:w.totalStrength,samples:w.samples,maxZ:w.maxZ,minZAspect:w.minZAspect,epsilon:w.epsilon,textureSamples:w.textureSamples,bypassBlur:w.bypassBlur,bilateralSamples:w.bilateralSamples,bilateralSoften:w.bilateralSoften,bilateralTolerance:w.bilateralTolerance,expensiveBlur:w.expensiveBlur}:null}n(Bt,"serializeSSAO2RenderingPipeline");function zt(t,e,i){if(w)return w;let o=Ji(t,e);return o.radius=i.radius,o.totalStrength=i.totalStrength,o.samples=i.samples,o.maxZ=i.maxZ,o.minZAspect=i.minZAspect,o.epsilon=i.epsilon,o.textureSamples=i.textureSamples,o.bypassBlur=i.bypassBlur,o.bilateralSamples=i.bilateralSamples,o.bilateralSoften=i.bilateralSoften,o.bilateralTolerance=i.bilateralTolerance,o.expensiveBlur=i.expensiveBlur,o}n(zt,"parseSSAO2RenderingPipeline");var eo=require("babylonjs"),T=null,fe=new Map;function Ht(){return T}n(Ht,"getMotionBlurPostProcess");function _n(t){T=t}n(_n,"setMotionBlurPostProcessRef");function kt(){T&&(T.dispose(),T=null)}n(kt,"disposeMotionBlurPostProcess");function to(t,e){return T=new eo.MotionBlurPostProcess("MotionBlurPostProcess",t,1,e),T.motionStrength=1,T.isObjectBased=!0,T}n(to,"createMotionBlurPostProcess");function Ut(){return T?{isObjectBased:T.isObjectBased,motionStrength:T.motionStrength,motionBlurSamples:T.motionBlurSamples}:null}n(Ut,"serializeMotionBlurPostProcess");function Wt(t,e,i){if(T)return T;let o=to(t,e);return o.isObjectBased=i.isObjectBased,o.motionStrength=i.motionStrength,o.motionBlurSamples=i.motionBlurSamples,o}n(Wt,"parseMotionBlurPostProcess");var io=require("babylonjs"),Xt=require("babylonjs"),oo=require("babylonjs"),ro=require("babylonjs"),no=require("babylonjs"),u=null,ue=new Map;function Ee(){return u}n(Ee,"getDefaultRenderingPipeline");function wn(t){u=t}n(wn,"setDefaultRenderingPipelineRef");function $t(){u&&(u.dispose(),u=null)}n($t,"disposeDefaultRenderingPipeline");function ao(t,e){return u=new no.DefaultRenderingPipeline("DefaultRenderingPipeline",!0,t,[e]),u.samples=4,u.depthOfField.lensSize=512,u.depthOfField.fStop=.25,u.depthOfField.focusDistance=55e3,u}n(ao,"createDefaultRenderingPipeline");function Kt(){return u?{samples:u.samples,fxaaEnabled:u.fxaaEnabled,imageProcessingEnabled:u.imageProcessingEnabled,exposure:u.imageProcessing?.exposure,contrast:u.imageProcessing?.contrast,fromLinearSpace:u.imageProcessing?.fromLinearSpace,toneMappingEnabled:u.imageProcessing?.toneMappingEnabled,toneMappingType:u.imageProcessing?.toneMappingType,ditheringEnabled:u.imageProcessing?.ditheringEnabled,ditheringIntensity:u.imageProcessing?.ditheringIntensity,bloomEnabled:u.bloomEnabled,bloomThreshold:u.bloomThreshold,bloomWeight:u.bloomWeight,bloomScale:u.bloomScale,bloomKernel:u.bloomKernel,sharpenEnabled:u.sharpenEnabled,sharpenEdgeAmount:u.sharpen.edgeAmount,sharpenColorAmount:u.sharpen.colorAmount,grainEnabled:u.grainEnabled,grainIntensity:u.grain.intensity,grainAnimated:u.grain.animated,depthOfFieldEnabled:u.depthOfFieldEnabled,depthOfFieldBlurLevel:u.depthOfFieldBlurLevel,lensSize:u.depthOfField.lensSize,fStop:u.depthOfField.fStop,focusDistance:u.depthOfField.focusDistance,focalLength:u.depthOfField.focalLength,vignetteEnabled:u.imageProcessing?.vignetteEnabled,vignetteColor:u.imageProcessing?.vignetteColor.asArray(),vignetteWeight:u.imageProcessing?.vignetteWeight,chromaticAberrationEnabled:u.chromaticAberrationEnabled,aberrationAmount:u.chromaticAberration.aberrationAmount,radialIntensity:u.chromaticAberration.radialIntensity,direction:u.chromaticAberration.direction.asArray(),centerPosition:u.chromaticAberration.centerPosition.asArray(),glowLayerEnabled:u.glowLayerEnabled,glowLayerIntensity:u.glowLayer?.intensity,glowLayerBlurKernelSize:u.glowLayer?.blurKernelSize,colorGradingEnabled:u.imageProcessing.colorGradingEnabled,colorGradingTexture:u.imageProcessing.colorGradingTexture?.serialize(),colorGradingWithGreenDepth:u.imageProcessing.imageProcessingConfiguration.colorGradingWithGreenDepth,colorCurvesEnabled:u.imageProcessing.colorCurvesEnabled,globalHue:u.imageProcessing.colorCurves?.globalHue,globalDensity:u.imageProcessing.colorCurves?.globalDensity,globalExposure:u.imageProcessing.colorCurves?.globalExposure,globalSaturation:u.imageProcessing.colorCurves?.globalSaturation,highlightsHue:u.imageProcessing.colorCurves?.highlightsHue,highlightsDensity:u.imageProcessing.colorCurves?.highlightsDensity,highlightsExposure:u.imageProcessing.colorCurves?.highlightsExposure,highlightsSaturation:u.imageProcessing.colorCurves?.highlightsSaturation,midtonesHue:u.imageProcessing.colorCurves?.midtonesHue,midtonesDensity:u.imageProcessing.colorCurves?.midtonesDensity,midtonesExposure:u.imageProcessing.colorCurves?.midtonesExposure,midtonesSaturation:u.imageProcessing.colorCurves?.midtonesSaturation,shadowsHue:u.imageProcessing.colorCurves?.shadowsHue,shadowsDensity:u.imageProcessing.colorCurves?.shadowsDensity,shadowsExposure:u.imageProcessing.colorCurves?.shadowsExposure,shadowsSaturation:u.imageProcessing.colorCurves?.shadowsSaturation}:null}n(Kt,"serializeDefaultRenderingPipeline");function jt(t,e,i,o){if(u)return u;let r=ao(t,e);if(r.samples=i.samples,r.fxaaEnabled=i.fxaaEnabled,r.imageProcessingEnabled=i.imageProcessingEnabled,r.imageProcessing){if(r.imageProcessing.exposure=i.exposure,r.imageProcessing.contrast=i.contrast,r.imageProcessing.fromLinearSpace=i.fromLinearSpace,r.imageProcessing.toneMappingEnabled=i.toneMappingEnabled,r.imageProcessing.toneMappingType=i.toneMappingType,r.imageProcessing.ditheringEnabled=i.ditheringEnabled,r.imageProcessing.ditheringIntensity=i.ditheringIntensity,r.imageProcessing.vignetteEnabled=i.vignetteEnabled??!1,r.imageProcessing.vignetteColor=io.Color4.FromArray(i.vignetteColor??[0,0,0]),r.imageProcessing.vignetteWeight=i.vignetteWeight??.3,r.imageProcessing.colorGradingEnabled=i.colorGradingEnabled??!1,r.imageProcessing.imageProcessingConfiguration.colorGradingWithGreenDepth=i.colorGradingWithGreenDepth??!0,i.colorGradingTexture){let a=null;if(i.colorGradingTexture.customType==="BABYLON.ColorGradingTexture"){let l=o+i.colorGradingTexture.name;a=new ro.ColorGradingTexture(l,t),a.level=i.colorGradingTexture.level}else{let l=oo.Texture.Parse(i.colorGradingTexture,t,o);Oe(l)&&(a=l)}r.imageProcessing.colorGradingTexture=a}r.imageProcessing.colorCurvesEnabled=i.colorCurvesEnabled??!1,r.imageProcessing.colorCurves&&(r.imageProcessing.colorCurves.globalHue=i.globalHue??30,r.imageProcessing.colorCurves.globalDensity=i.globalDensity??0,r.imageProcessing.colorCurves.globalExposure=i.globalExposure??0,r.imageProcessing.colorCurves.globalSaturation=i.globalSaturation??0,r.imageProcessing.colorCurves.highlightsHue=i.highlightsHue??30,r.imageProcessing.colorCurves.highlightsDensity=i.highlightsDensity??0,r.imageProcessing.colorCurves.highlightsExposure=i.highlightsExposure??0,r.imageProcessing.colorCurves.highlightsSaturation=i.highlightsSaturation??0,r.imageProcessing.colorCurves.midtonesHue=i.midtonesHue??30,r.imageProcessing.colorCurves.midtonesDensity=i.midtonesDensity??0,r.imageProcessing.colorCurves.midtonesExposure=i.midtonesExposure??0,r.imageProcessing.colorCurves.midtonesSaturation=i.midtonesSaturation??0,r.imageProcessing.colorCurves.shadowsHue=i.shadowsHue??30,r.imageProcessing.colorCurves.shadowsDensity=i.shadowsDensity??0,r.imageProcessing.colorCurves.shadowsExposure=i.shadowsExposure??0,r.imageProcessing.colorCurves.shadowsSaturation=i.shadowsSaturation??0)}return r.bloomEnabled=i.bloomEnabled,r.bloomThreshold=i.bloomThreshold,r.bloomWeight=i.bloomWeight,r.bloomScale=i.bloomScale,r.bloomKernel=i.bloomKernel,r.sharpenEnabled=i.sharpenEnabled,r.sharpen.edgeAmount=i.sharpenEdgeAmount,r.sharpen.colorAmount=i.sharpenColorAmount,r.grainEnabled=i.grainEnabled,r.grain.intensity=i.grainIntensity,r.grain.animated=i.grainAnimated,r.depthOfFieldEnabled=i.depthOfFieldEnabled,r.depthOfFieldBlurLevel=i.depthOfFieldBlurLevel,r.depthOfField.lensSize=i.lensSize,r.depthOfField.fStop=i.fStop,r.depthOfField.focusDistance=i.focusDistance,r.depthOfField.focalLength=i.focalLength,r.chromaticAberrationEnabled=i.chromaticAberrationEnabled??!1,r.chromaticAberration.aberrationAmount=i.aberrationAmount??10,r.chromaticAberration.radialIntensity=i.radialIntensity??1,r.chromaticAberration.direction=Xt.Vector2.FromArray(i.direction??[0,0]),r.chromaticAberration.centerPosition=Xt.Vector2.FromArray(i.centerPosition??[0,0]),r.glowLayerEnabled=i.glowLayerEnabled??!1,r.glowLayer&&(r.glowLayer.intensity=i.glowLayerIntensity??1,r.glowLayer.blurKernelSize=i.glowLayerBlurKernelSize??32),r}n(jt,"parseDefaultRenderingPipeline");var ne="volumetricLighting",A=8,$=256,Qt=4,so=(i=>(i[i.Linear=0]="Linear",i[i.Exponential=1]="Exponential",i))(so||{}),Jt=(o=>(o[o.None=0]="None",o[o.Bayer=1]="Bayer",o[o.InterleavedGradientNoise=2]="InterleavedGradientNoise",o))(Jt||{}),ei=(o=>(o[o.Exponential=0]="Exponential",o[o.ExponentialSquared=1]="ExponentialSquared",o[o.Linear=2]="Linear",o))(ei||{}),lo=(r=>(r[r.None=0]="None",r[r.Scattering=1]="Scattering",r[r.Transmittance=2]="Transmittance",r[r.LightCount=3]="LightCount",r))(lo||{});function qt(){return{enabled:!1,volumeIntensity:1,anisotropy:.35,useCustomColor:!1,color:[1,1,1],castVolumetricShadows:!0,shadowDarkness:1,rangeMultiplier:1,priority:0}}n(qt,"getDefaultVolumetricLightConfiguration");function je(){return{steps:40,lightSteps:0,resolutionScale:.5,stepDistribution:1,ditherMode:2,ditherStrength:1,temporalJitter:!1,fogMode:0,fogDensity:5e-4,fogStart:0,fogEnd:2e3,fogColor:[1,1,1],albedo:1,maxDistance:1e4,heightFogEnabled:!1,heightFogBaseHeight:0,heightFogFalloff:.01,intensity:1.5,lightExtinctionEnabled:!0,lightExtinctionClamp:1e3,extinctionAmount:0,ambientColor:[1,1,1],ambientIntensity:0,screenSpaceShadows:!0,screenSpaceShadowSteps:6,screenSpaceShadowBias:.02,screenSpaceShadowMaxDistance:2e3,screenSpaceShadowThickness:4,blurPasses:2,blurRadius:3,blurDepthThreshold:.02,upsampleDepthThreshold:.02,maxLights:128,maxShadowedLights:4,pcfTaps:4,selectionRefreshRate:2,debugMode:0}}n(je,"getDefaultVolumetricLightingConfiguration");function ti(t){return t.lightSteps>0?t.lightSteps:Math.max(4,Math.min(64,Math.round(t.steps*.3)))}n(ti,"getVolumetricLightSteps");function y(t,e,i,o){let r=typeof t=="number"&&isFinite(t)?t:e;return Math.min(o,Math.max(i,r))}n(y,"normalizeNumber");function Zt(t,e){return!Array.isArray(t)||t.length<3?e.slice():[y(t[0],e[0],0,100),y(t[1],e[1],0,100),y(t[2],e[2],0,100)]}n(Zt,"normalizeColor");function co(t){let e=qt();return!t||typeof t!="object"?e:{enabled:t.enabled??e.enabled,volumeIntensity:y(t.volumeIntensity,e.volumeIntensity,0,1e3),anisotropy:y(t.anisotropy,e.anisotropy,-.95,.95),useCustomColor:t.useCustomColor??e.useCustomColor,color:Zt(t.color,e.color),castVolumetricShadows:t.castVolumetricShadows??e.castVolumetricShadows,shadowDarkness:y(t.shadowDarkness,e.shadowDarkness,0,1),rangeMultiplier:y(t.rangeMultiplier,e.rangeMultiplier,0,100),priority:y(t.priority,e.priority,-1e3,1e3)}}n(co,"normalizeVolumetricLightConfiguration");function ge(t){let e=je();return!t||typeof t!="object"?e:{steps:Math.round(y(t.steps,e.steps,4,256)),lightSteps:Math.round(y(t.lightSteps,e.lightSteps,0,128)),resolutionScale:y(t.resolutionScale,e.resolutionScale,.1,1),stepDistribution:Math.round(y(t.stepDistribution,e.stepDistribution,0,1)),ditherMode:Math.round(y(t.ditherMode,e.ditherMode,0,2)),ditherStrength:y(t.ditherStrength,e.ditherStrength,0,1),temporalJitter:t.temporalJitter??e.temporalJitter,fogMode:Math.round(y(t.fogMode,e.fogMode,0,2)),fogDensity:y(t.fogDensity,e.fogDensity,0,100),fogStart:y(t.fogStart,e.fogStart,0,1e6),fogEnd:Math.max(y(t.fogEnd,e.fogEnd,0,1e7),y(t.fogStart,e.fogStart,0,1e6)+.001),fogColor:Zt(t.fogColor,e.fogColor),albedo:y(t.albedo,e.albedo,0,1),maxDistance:y(t.maxDistance,e.maxDistance,1,1e6),heightFogEnabled:t.heightFogEnabled??e.heightFogEnabled,heightFogBaseHeight:y(t.heightFogBaseHeight,e.heightFogBaseHeight,-1e6,1e6),heightFogFalloff:y(t.heightFogFalloff,e.heightFogFalloff,0,10),intensity:y(t.intensity,e.intensity,0,100),lightExtinctionEnabled:t.lightExtinctionEnabled??e.lightExtinctionEnabled,lightExtinctionClamp:y(t.lightExtinctionClamp,e.lightExtinctionClamp,0,1e6),extinctionAmount:y(t.extinctionAmount,e.extinctionAmount,0,1),ambientColor:Zt(t.ambientColor,e.ambientColor),ambientIntensity:y(t.ambientIntensity,e.ambientIntensity,0,100),screenSpaceShadows:t.screenSpaceShadows??e.screenSpaceShadows,screenSpaceShadowSteps:Math.round(y(t.screenSpaceShadowSteps,e.screenSpaceShadowSteps,1,32)),screenSpaceShadowBias:y(t.screenSpaceShadowBias,e.screenSpaceShadowBias,0,1),screenSpaceShadowMaxDistance:y(t.screenSpaceShadowMaxDistance,e.screenSpaceShadowMaxDistance,1,1e7),screenSpaceShadowThickness:y(t.screenSpaceShadowThickness,e.screenSpaceShadowThickness,.01,1e3),blurPasses:Math.round(y(t.blurPasses,e.blurPasses,0,2)),blurRadius:Math.round(y(t.blurRadius,e.blurRadius,1,6)),blurDepthThreshold:y(t.blurDepthThreshold,e.blurDepthThreshold,1e-4,1),upsampleDepthThreshold:y(t.upsampleDepthThreshold,e.upsampleDepthThreshold,1e-4,1),maxLights:Math.round(y(t.maxLights,e.maxLights,0,$)),maxShadowedLights:Math.round(y(t.maxShadowedLights,e.maxShadowedLights,0,A)),pcfTaps:y(t.pcfTaps,e.pcfTaps,1,4)>=4?4:1,selectionRefreshRate:Math.round(y(t.selectionRefreshRate,e.selectionRefreshRate,1,60)),debugMode:Math.round(y(t.debugMode,e.debugMode,0,3))}}n(ge,"normalizeVolumetricLightingConfiguration");var Yt=new WeakSet;function po(t){t.metadata??={};let e=t.metadata[ne];if(!e||typeof e!="object")return t.metadata[ne]=co(null),Yt.add(t.metadata[ne]),t.metadata[ne];if(Yt.has(e))return e;let i=qt();return Object.keys(i).forEach(o=>{e[o]===void 0&&(e[o]=i[o])}),Yt.add(e),e}n(po,"ensureVolumetricLightConfiguration");function ii(t){let e=t.metadata?.[ne];return e&&typeof e=="object"?po(t):null}n(ii,"getVolumetricLightConfiguration");function Pn(t){return t.metadata?.[ne]?.enabled===!0}n(Pn,"isVolumetricLightEnabled");var Ze=require("babylonjs"),uo=require("babylonjs"),ri=require("babylonjs"),K=require("babylonjs"),ni=(o=>(o[o.Texture2D=0]="Texture2D",o[o.Sampler2DShadow=1]="Sampler2DShadow",o[o.Cube=2]="Cube",o))(ni||{}),go=(o=>(o[o.Standard=0]="Standard",o[o.Esm=1]="Esm",o[o.CloseEsm=2]="CloseEsm",o))(go||{}),ai=(o=>(o[o.Analytic=0]="Analytic",o[o.AnalyticHeight=1]="AnalyticHeight",o[o.Numeric=2]="Numeric",o))(ai||{}),mo=10,On=4,En=22,An=32,Tn=.15;function Ae(t,e){let i=t.getCaps(),o=i.maxFragmentUniformVectors||224,r=t.isWebGPU?Math.floor(o/4):o,a=Math.max(224,r)-An,l=Math.max(8,i.maxTexturesImageUnits||16)-1,p=l>=2,s=p?En:0,c=Math.max(0,Math.min(A,e.maxShadowedLights,l-(p?1:0),Math.floor((a-s)/mo))),m=Math.max(0,Math.min($,e.maxLights,Math.floor((a-s-c*mo)/On)));return{maxShadowSlots:c,maxArrayLights:m,maxDirectionalLights:Math.min(Qt,m),allowCsm:p}}n(Ae,"computeVolumetricBudget");function vo(t){let e=[];return t.lights.forEach(i=>{le(i)?i.lights.forEach(o=>{e.push({light:o,isClustered:!0})}):e.push({light:i,isClustered:!1})}),e}n(vo,"getAllVolumetricCandidateLights");function So(t,e){let i=t.getShadowGenerator(e.activeCamera)??t.getShadowGenerator();if(!i||!vt(i))return null;let o=i.getShadowMapForRendering();if(!o?.isReady())return null;let r=i.getShadowMap()?.getSize().width??1024,a=o.textureType===ri.Constants.TEXTURETYPE_UNSIGNED_BYTE,l=!ee(t),p=t.needCube?.()===!0;switch(i.filter){case K.ShadowGenerator.FILTER_PCF:case K.ShadowGenerator.FILTER_PCSS:return{generator:i,kind:p?2:1,mode:0,packed:a,mapSize:r,local:l};case K.ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP:case K.ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP:return{generator:i,kind:p?2:0,mode:1,packed:a,mapSize:r,local:l};case K.ShadowGenerator.FILTER_CLOSEEXPONENTIALSHADOWMAP:case K.ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP:return{generator:i,kind:p?2:0,mode:2,packed:a,mapSize:r,local:l};default:return{generator:i,kind:p?2:0,mode:0,packed:a,mapSize:r,local:l}}}n(So,"resolveVolumetricShadowSlot");function Ye(t,e){let i=t;return i.computeTransformedInformation?.()&&i.transformedPosition?e.copyFrom(i.transformedPosition):i.position?e.copyFrom(i.position):e.copyFromFloats(0,0,0),e}n(Ye,"getVolumetricLightWorldPosition");function Te(t,e){let i=t;return i.computeTransformedInformation?.()&&i.transformedDirection?e.copyFrom(i.transformedDirection):i.direction?e.copyFrom(i.direction):e.copyFromFloats(0,0,1),e.normalize()}n(Te,"getVolumetricLightWorldDirection");function qe(t,e,i){let o=t.range>0&&t.range<Number.MAX_VALUE?t.range:i.maxDistance;return Math.max(.001,Math.min(o*e.rangeMultiplier,34e37))}n(qe,"getVolumetricLightRange");var oi=new Ze.Vector3,ho=new Ze.Vector3;function In(t,e,i){if(Ye(t,i),!oe(t))return e;let o=Math.cos(t.angle*.5);if(o<=.5)return e;let r=e/(2*o);return Te(t,ho),i.addInPlace(ho.scaleInPlace(r)),r}n(In,"computeVolumetricLightBounds");function Mn(t,e,i){for(let o=0;o<i.length;++o)if(i[o].dotCoordinate(t)<=-e)return!1;return!0}n(Mn,"isSphereInFrustum");function fo(t){return(t.local?64:0)+t.kind*16+t.mode*4+(t.packed?1:0)}n(fo,"getShadowSlotSignature");function si(t,e,i,o,r){let a={candidateCount:0,culledCount:0,shadowedCount:0,unshadowedCount:0,droppedCount:0,perLight:new Map},l=uo.Frustum.GetPlanes(t.getTransformMatrix()),p=e.globalPosition,s=[];vo(t).forEach(({light:v,isClustered:L})=>{let R=ii(v);if(!R?.enabled)return;if(a.candidateCount++,$e(v)||!v.isEnabled()||v.intensity<=0||R.volumeIntensity<=0){a.perLight.set(v.uniqueId,{state:"disabled",slot:-1,reason:$e(v)?"Hemispheric lights have no position nor direction and can't produce light shafts.":"The light is disabled or its intensity is zero."});return}let X=ee(v),se=R.priority*1e3;if(X)se+=1e6;else{let Ue=Math.min(qe(v,R,i),i.maxDistance),ut=In(v,Ue,oi);if(!Mn(oi,ut,l)){a.culledCount++,a.perLight.set(v.uniqueId,{state:"culled",slot:-1,reason:"The light is outside of the frustum of the camera and doesn't reach it."});return}let rn=Math.max(1,Ze.Vector3.Distance(oi,p)-ut);se+=R.volumeIntensity*v.intensity*Math.min(4,ut/rn)}s.push({light:v,config:R,isClustered:L,typeId:v.getTypeID(),score:se})}),s.sort((v,L)=>L.score-v.score);let c=new Map;r?.shadowed.forEach((v,L)=>{c.set(v.candidate.light.uniqueId,L)});let m=[],h=[],d=new Map,f=null;s.forEach(v=>{let{light:L,config:R}=v;if(!R.castVolumetricShadows){d.set(L.uniqueId,"occlusion is disabled on this light."),h.push(v);return}if(v.isClustered){d.set(L.uniqueId,"clustered lighting doesn't support shadow maps."),h.push(v);return}if(!L.shadowEnabled||!t.shadowsEnabled){d.set(L.uniqueId,"shadows are disabled on this light or on the scene."),h.push(v);return}let X=L.getShadowGenerator(t.activeCamera)??L.getShadowGenerator();if(!X){d.set(L.uniqueId,"the light has no shadow generator."),h.push(v);return}if(St(X)&&o.allowCsm){let Ue=X.getShadowMapForRendering();if(!f&&Ue?.isReady()){f={candidate:v,generator:X,cascades:X.numCascades,kind:X.filter===K.ShadowGenerator.FILTER_PCF||X.filter===K.ShadowGenerator.FILTER_PCSS?1:0,packed:Ue.textureType===ri.Constants.TEXTURETYPE_UNSIGNED_BYTE};return}d.set(L.uniqueId,f?"another light already uses the single cascaded shadow map slot.":"its cascaded shadow map is not ready yet."),h.push(v);return}let se=So(L,t);if(!se){d.set(L.uniqueId,"the shadow map of the light is not ready yet."),h.push(v);return}m.push({candidate:v,shadow:se})});function S(v){let L=v.candidate.score;return c.get(v.candidate.light.uniqueId)===void 0?L:L+Math.abs(L)*Tn}n(S,"getHysteresisScore");function g(v){return c.get(v.candidate.light.uniqueId)??Number.MAX_SAFE_INTEGER}n(g,"getPreviousSlot"),m.sort((v,L)=>{let R=S(L)-S(v);return R!==0?R:g(v)-g(L)});let b=m.slice(0,o.maxShadowSlots);b.sort((v,L)=>fo(v.shadow)-fo(L.shadow)||g(v)-g(L)),m.slice(o.maxShadowSlots).forEach(v=>{d.set(v.candidate.light.uniqueId,"the shadowed lights budget is full."),h.push(v.candidate)}),h.sort((v,L)=>L.score-v.score);let C=[],_=[],x=[];h.forEach(v=>{ee(v.light)?C.length<o.maxDirectionalLights?C.push(v):x.push({candidate:v,reason:`Not rendered: at most ${o.maxDirectionalLights} directional light(s) without a shadow map can take part in the effect.`}):_.push(v)});let M=Math.max(0,o.maxArrayLights-C.length);_.slice(M).forEach(v=>{x.push({candidate:v,reason:'Not rendered: the lights budget is full. Raise "Max Lights" or lower the priority of the other lights.'})});let G=C.concat(_.slice(0,M));if(b.forEach((v,L)=>{a.shadowedCount++,a.perLight.set(v.candidate.light.uniqueId,{state:"shadowed",slot:L,reason:`Casting volumetric shadows using slot ${L+1} of ${o.maxShadowSlots}.`})}),f){let v=f;a.shadowedCount++,a.perLight.set(v.candidate.light.uniqueId,{state:"shadowed",slot:-1,reason:`Casting volumetric shadows using its ${v.cascades} shadow cascades.`})}return G.forEach(v=>{a.unshadowedCount++;let L=v.config.castVolumetricShadows?"Occluded using the depth buffer":"Not occluded by the geometry",R=d.get(v.light.uniqueId)??"the light has no shadow map.";a.perLight.set(v.light.uniqueId,{state:"unshadowed",slot:-1,reason:`${L}: ${R}`})}),x.forEach(({candidate:v,reason:L})=>{a.droppedCount++,a.perLight.set(v.light.uniqueId,{state:"dropped",slot:-1,reason:L})}),{shadowed:b,unshadowed:G,directionalCount:C.length,csm:f,stats:a}}n(si,"selectVolumetricLights");function Rn(t,e,i){let o=t.shadowed.map(a=>`${a.shadow.kind}.${a.shadow.mode}.${a.shadow.packed?1:0}.${a.shadow.local?1:0}`).join("|"),r=t.csm?`${t.csm.kind}.${t.csm.cascades}.${t.csm.packed?1:0}`:"-";return[e.steps,i.lightSteps,e.stepDistribution,e.ditherMode,e.temporalJitter?1:0,e.heightFogEnabled?1:0,e.lightExtinctionEnabled?1:0,e.pcfTaps,e.blurRadius,e.debugMode,e.screenSpaceShadows?e.screenSpaceShadowSteps:0,i.fogMode,i.transmittance,i.depthMode,i.ldrEncode?1:0,i.reverseDepth?1:0,i.ndcHalfZ?1:0,i.linearDepthPacked?1:0,i.arrayLightCapacity,t.directionalCount,o,r].join(",")}n(Rn,"computeVolumetricShapeKey");function Vn(t){return gt(t)||oe(t)||ee(t)}n(Vn,"isVolumetricLightSupported");var Qe=`
|
|
2
|
+
fn volUnpack(color: vec4f) -> f32 {
|
|
3
|
+
let bitShift = vec4f(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
|
|
4
|
+
return dot(color, bitShift);
|
|
5
|
+
}
|
|
6
|
+
`,Fn=`
|
|
7
|
+
fn volSampleDepth(uv: vec2f) -> f32 {
|
|
8
|
+
#ifdef VOL_DEPTH_PACKED
|
|
9
|
+
return volUnpack(textureSampleLevel(depthSampler, depthSamplerSampler, uv, 0.0));
|
|
10
|
+
#else
|
|
11
|
+
return textureSampleLevel(depthSampler, depthSamplerSampler, uv, 0.0).r;
|
|
12
|
+
#endif
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Converts the raw value stored in the depth map into a distance along the view axis, in scene units.
|
|
16
|
+
fn volLinearDepth(d: f32) -> f32 {
|
|
17
|
+
#ifdef VOL_DEPTH_VIEWZ
|
|
18
|
+
// The depth renderer stores the view space Z directly. The sky is cleared to 0.
|
|
19
|
+
return select(d, uniforms.volCameraMinMaxZ.y, d <= 0.0);
|
|
20
|
+
#else
|
|
21
|
+
// The depth renderer stores "(clipZ + minZ) / (minZ + maxZ)", which is affine in the view space Z
|
|
22
|
+
// for both the perspective and the orthographic projections. "volDepthUnpack" holds the two
|
|
23
|
+
// coefficients of the exact inverse, computed on the CPU from the projection matrix of the scene.
|
|
24
|
+
return uniforms.volDepthUnpack.x * d + uniforms.volDepthUnpack.y;
|
|
25
|
+
#endif
|
|
26
|
+
}
|
|
27
|
+
`;function li(t){return`
|
|
28
|
+
// Returns the distance along the view axis, in scene units, of the texel at the given coordinates.
|
|
29
|
+
fn volReadLinearDepth(coordinates: vec2i) -> f32 {
|
|
30
|
+
#ifdef VOL_LINEAR_DEPTH_PACKED
|
|
31
|
+
return volUnpack(textureLoad(${t}, coordinates, 0)) * uniforms.volCameraMinMaxZ.y;
|
|
32
|
+
#else
|
|
33
|
+
return textureLoad(${t}, coordinates, 0).r;
|
|
34
|
+
#endif
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Returns the texel of the linear depth under the center of the given texel of the scattering buffer.
|
|
38
|
+
// @see the GLSL version.
|
|
39
|
+
fn volScatterToDepthTexel(scatterTexel: vec2i, depthSize: vec2i) -> vec2i {
|
|
40
|
+
return min(vec2i((vec2f(scatterTexel) + 0.5) * uniforms.volDepthRatio), depthSize - 1);
|
|
41
|
+
}
|
|
42
|
+
`}n(li,"buildLinearDepthHelpers");function Nn(){return`
|
|
43
|
+
varying vUV: vec2f;
|
|
44
|
+
|
|
45
|
+
var textureSamplerSampler: sampler;
|
|
46
|
+
var textureSampler: texture_2d<f32>;
|
|
47
|
+
var depthSamplerSampler: sampler;
|
|
48
|
+
var depthSampler: texture_2d<f32>;
|
|
49
|
+
|
|
50
|
+
uniform volCameraMinMaxZ: vec2f;
|
|
51
|
+
uniform volDepthUnpack: vec2f;
|
|
52
|
+
|
|
53
|
+
${Qe}
|
|
54
|
+
${Fn}
|
|
55
|
+
|
|
56
|
+
fn volPack(depth: f32) -> vec4f {
|
|
57
|
+
let bitShift = vec4f(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);
|
|
58
|
+
let bitMask = vec4f(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
|
|
59
|
+
|
|
60
|
+
var result = fract(depth * bitShift);
|
|
61
|
+
result -= result.xxyz * bitMask;
|
|
62
|
+
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@fragment
|
|
67
|
+
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
68
|
+
let viewZ = volLinearDepth(volSampleDepth(input.vUV));
|
|
69
|
+
|
|
70
|
+
#ifdef VOL_LINEAR_DEPTH_PACKED
|
|
71
|
+
fragmentOutputs.color = volPack(clamp(viewZ / uniforms.volCameraMinMaxZ.y, 0.0, 0.9999999));
|
|
72
|
+
#else
|
|
73
|
+
fragmentOutputs.color = vec4f(viewZ, 0.0, 0.0, 1.0);
|
|
74
|
+
#endif
|
|
75
|
+
}
|
|
76
|
+
`}n(Nn,"buildVolumetricLightingLinearDepthShaderWGSL");function yo(t,e){return`
|
|
77
|
+
let chordLength = t1 - t0;
|
|
78
|
+
|
|
79
|
+
// The point of the view ray closest to the light splits the chord in two halves over which both the
|
|
80
|
+
// attenuation and the phase function are monotonic, which is where stratified samples do best.
|
|
81
|
+
var closest = clamp(dot(data.xyz, volRayDir), t0, t1);
|
|
82
|
+
if (closest - t0 < 0.02 * chordLength) {
|
|
83
|
+
closest = t0;
|
|
84
|
+
} else if (t1 - closest < 0.02 * chordLength) {
|
|
85
|
+
closest = t1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let count = volLocalSampleCount(chordLength, falloff.x, tEnd - tStart);
|
|
89
|
+
|
|
90
|
+
var firstCount = clamp(i32(f32(count) * (closest - t0) / chordLength + 0.5), 1, count - 1);
|
|
91
|
+
if (closest <= t0) {
|
|
92
|
+
firstCount = 0;
|
|
93
|
+
} else if (closest >= t1) {
|
|
94
|
+
firstCount = count;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let firstWidth = (closest - t0) / f32(max(firstCount, 1));
|
|
98
|
+
let secondWidth = (t1 - closest) / f32(max(count - firstCount, 1));
|
|
99
|
+
let stratum = volStratumOffset(${t});
|
|
100
|
+
|
|
101
|
+
var result = vec3f(0.0);
|
|
102
|
+
|
|
103
|
+
for (var k: i32 = 0; k < VOL_LOCAL_MAX_STEPS; k++) {
|
|
104
|
+
if (k >= count) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let inFirstHalf = k < firstCount;
|
|
109
|
+
let width = select(secondWidth, firstWidth, inFirstHalf);
|
|
110
|
+
let t = select(closest + width * (f32(k - firstCount) + stratum), t0 + width * (f32(k) + stratum), inFirstHalf);
|
|
111
|
+
|
|
112
|
+
let position = volRayDir * t;
|
|
113
|
+
let sigmaT = volExtinctionAt(uniforms.volCameraPosition.y + position.y, t);
|
|
114
|
+
|
|
115
|
+
let lightSample = volEvalLocalLight(data, diffuse, direction, falloff, position);
|
|
116
|
+
var contribution = lightSample.xyz;
|
|
117
|
+
let distanceToLight = lightSample.w;
|
|
118
|
+
|
|
119
|
+
if (contribution.r + contribution.g + contribution.b > 0.0) {
|
|
120
|
+
${e}
|
|
121
|
+
result += contribution * (volCombinedTransmittance(t, sigmaT, distanceToLight) * sigmaT * width);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return vec4f(result, 1.0);
|
|
126
|
+
`}n(yo,"buildLocalLightIntegrationWGSL");function Gn(t){let e=[],i=[],o=[];for(let r=0;r<t;++r)e.push(`
|
|
127
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
128
|
+
#if VOL_SHADOW_KIND{X} == 2
|
|
129
|
+
var volShadowSampler{X}Sampler: sampler;
|
|
130
|
+
var volShadowSampler{X}: texture_cube<f32>;
|
|
131
|
+
#elif VOL_SHADOW_KIND{X} == 1
|
|
132
|
+
var volShadowSampler{X}Sampler: sampler_comparison;
|
|
133
|
+
var volShadowSampler{X}: texture_depth_2d;
|
|
134
|
+
#else
|
|
135
|
+
var volShadowSampler{X}Sampler: sampler;
|
|
136
|
+
var volShadowSampler{X}: texture_2d<f32>;
|
|
137
|
+
#endif
|
|
138
|
+
|
|
139
|
+
// Returns the shadowing of a point given its position relative to the camera and, for the 2d shadow maps, its
|
|
140
|
+
// position in the clip space of the light. @see the GLSL version.
|
|
141
|
+
fn volShadow{X}(position: vec3f, clip: vec4f) -> f32 {
|
|
142
|
+
let info = uniforms.volShadowInfo[{X}];
|
|
143
|
+
let edge = uniforms.volShadowLightFalloff[{X}].z;
|
|
144
|
+
|
|
145
|
+
#if VOL_SHADOW_KIND{X} == 2
|
|
146
|
+
// Cube shadow map of a point light. It stores the radial distance to the light.
|
|
147
|
+
var toFragment = position - uniforms.volShadowLightData[{X}].xyz;
|
|
148
|
+
let depth = clamp((length(toFragment) + info.z) / info.w, 0.0, 1.0);
|
|
149
|
+
|
|
150
|
+
toFragment = normalize(toFragment);
|
|
151
|
+
toFragment.y = -toFragment.y;
|
|
152
|
+
|
|
153
|
+
#ifdef VOL_SHADOW_PACKED{X}
|
|
154
|
+
let shadowMapSample = volUnpack(textureSampleLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, toFragment, 0.0));
|
|
155
|
+
#else
|
|
156
|
+
let shadowMapSample = textureSampleLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, toFragment, 0.0).x;
|
|
157
|
+
#endif
|
|
158
|
+
|
|
159
|
+
#if VOL_SHADOW_MODE{X} == 1
|
|
160
|
+
// Exponential shadow map, same encoding as the 2d case. "info.y" holds the depth scale.
|
|
161
|
+
return 1.0 - clamp(exp(min(87.0, info.y * depth)) * shadowMapSample, 0.0, 1.0 - info.x);
|
|
162
|
+
#elif VOL_SHADOW_MODE{X} == 2
|
|
163
|
+
return clamp(exp(min(87.0, -info.y * (depth - shadowMapSample))), info.x, 1.0);
|
|
164
|
+
#else
|
|
165
|
+
return select(1.0, info.x, depth > shadowMapSample);
|
|
166
|
+
#endif
|
|
167
|
+
#else
|
|
168
|
+
let clipSpace = clip.xyz / clip.w;
|
|
169
|
+
|
|
170
|
+
// "getTransformMatrix" gives the world to light clip space matrix without the [-1, 1] -> [0, 1] bias.
|
|
171
|
+
#if VOL_SHADOW_KIND{X} == 1
|
|
172
|
+
var uvDepth = 0.5 * clipSpace + vec3f(0.5);
|
|
173
|
+
#ifdef VOL_NDC_HALF_Z
|
|
174
|
+
uvDepth.z = clipSpace.z;
|
|
175
|
+
#endif
|
|
176
|
+
|
|
177
|
+
// Same guard as "computeShadowWithPCF1": past the far plane of the shadow map the hardware
|
|
178
|
+
// comparison would fail against every texel a caster wrote, reporting the sample as occluded
|
|
179
|
+
// while the surfaces at the same distance are lit by the material path.
|
|
180
|
+
let pcfDepthMetric = volDepthMetric(clip, info.zw);
|
|
181
|
+
if (pcfDepthMetric < 0.0 || pcfDepthMetric > 1.0 || uvDepth.x < 0.0 || uvDepth.x > 1.0 || uvDepth.y < 0.0 || uvDepth.y > 1.0) {
|
|
182
|
+
return 1.0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Hardware comparison sampling. "info.y" holds the inverse of the size of the shadow map.
|
|
186
|
+
#if VOL_PCF_TAPS == 4
|
|
187
|
+
let shadow = 0.25 * (
|
|
188
|
+
textureSampleCompareLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uvDepth.xy + vec2f(-0.5 * info.y, -0.5 * info.y), uvDepth.z) +
|
|
189
|
+
textureSampleCompareLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uvDepth.xy + vec2f( 0.5 * info.y, -0.5 * info.y), uvDepth.z) +
|
|
190
|
+
textureSampleCompareLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uvDepth.xy + vec2f(-0.5 * info.y, 0.5 * info.y), uvDepth.z) +
|
|
191
|
+
textureSampleCompareLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uvDepth.xy + vec2f( 0.5 * info.y, 0.5 * info.y), uvDepth.z)
|
|
192
|
+
);
|
|
193
|
+
#else
|
|
194
|
+
let shadow = textureSampleCompareLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uvDepth.xy, uvDepth.z);
|
|
195
|
+
#endif
|
|
196
|
+
|
|
197
|
+
return volFallOff(mix(info.x, 1.0, shadow), clipSpace.xy, edge);
|
|
198
|
+
#else
|
|
199
|
+
let uv = 0.5 * clipSpace.xy + vec2f(0.5);
|
|
200
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
201
|
+
return 1.0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let depthMetric = clamp(volDepthMetric(clip, info.zw), 0.0, 1.0);
|
|
205
|
+
|
|
206
|
+
#ifdef VOL_SHADOW_PACKED{X}
|
|
207
|
+
let shadowMapSample = volUnpack(textureSampleLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uv, 0.0));
|
|
208
|
+
#else
|
|
209
|
+
let shadowMapSample = textureSampleLevel(volShadowSampler{X}, volShadowSampler{X}Sampler, uv, 0.0).x;
|
|
210
|
+
#endif
|
|
211
|
+
|
|
212
|
+
#if VOL_SHADOW_MODE{X} == 1
|
|
213
|
+
// Exponential shadow map. "info.y" holds the depth scale of the generator.
|
|
214
|
+
return volFallOff(1.0 - clamp(exp(min(87.0, info.y * depthMetric)) * shadowMapSample, 0.0, 1.0 - info.x), clipSpace.xy, edge);
|
|
215
|
+
#elif VOL_SHADOW_MODE{X} == 2
|
|
216
|
+
// Close exponential shadow map.
|
|
217
|
+
return volFallOff(clamp(exp(min(87.0, -info.y * (depthMetric - shadowMapSample))), info.x, 1.0), clipSpace.xy, edge);
|
|
218
|
+
#else
|
|
219
|
+
return select(1.0, volFallOff(info.x, clipSpace.xy, edge), depthMetric > shadowMapSample);
|
|
220
|
+
#endif
|
|
221
|
+
#endif
|
|
222
|
+
#endif
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
#if VOL_SHADOW_LOCAL{X} == 1
|
|
226
|
+
// Point or spot light casting volumetric shadows: integrated over its own volume, like the others.
|
|
227
|
+
fn volIntegrateShadowSlot{X}(tStart: f32, tEnd: f32) -> vec4f {
|
|
228
|
+
let data = uniforms.volShadowLightData[{X}];
|
|
229
|
+
let direction = uniforms.volShadowLightDirection[{X}];
|
|
230
|
+
let falloff = uniforms.volShadowLightFalloff[{X}];
|
|
231
|
+
|
|
232
|
+
let chord = volLightChord(data, direction, falloff.x);
|
|
233
|
+
let t0 = max(chord.x, tStart);
|
|
234
|
+
let t1 = min(chord.y, tEnd);
|
|
235
|
+
|
|
236
|
+
if (t1 <= t0) {
|
|
237
|
+
return vec4f(0.0);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let diffuse = uniforms.volShadowLightDiffuse[{X}];
|
|
241
|
+
|
|
242
|
+
// The light clip space position of the points of the view ray is affine in their distance to the camera.
|
|
243
|
+
let clipOrigin = uniforms.volShadowMatrix[{X}] * vec4f(uniforms.volCameraPosition, 1.0);
|
|
244
|
+
let clipDirection = uniforms.volShadowMatrix[{X}] * vec4f(volRayDir, 0.0);
|
|
245
|
+
${yo("f32({X}) + 0.5","contribution *= mix(1.0, volShadow{X}(position, clipOrigin + clipDirection * t), falloff.w);")}
|
|
246
|
+
}
|
|
247
|
+
#endif
|
|
248
|
+
#endif
|
|
249
|
+
`.replace(/\{X\}/g,r.toString())),i.push(`
|
|
250
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
251
|
+
#if VOL_SHADOW_LOCAL{X} == 0
|
|
252
|
+
{
|
|
253
|
+
// Recomputed rather than kept affine to keep fewer registers alive across the march. @see the GLSL version.
|
|
254
|
+
let shadow = volShadow{X}(position, uniforms.volShadowMatrix[{X}] * vec4f(uniforms.volCameraPosition + position, 1.0));
|
|
255
|
+
scattering += volEvalDirectionalLight(uniforms.volShadowLightData[{X}], uniforms.volShadowLightDiffuse[{X}]) * mix(1.0, shadow, uniforms.volShadowLightFalloff[{X}].w);
|
|
256
|
+
stepLights += 1.0;
|
|
257
|
+
}
|
|
258
|
+
#endif
|
|
259
|
+
#endif
|
|
260
|
+
`.replace(/\{X\}/g,r.toString())),o.push(`
|
|
261
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
262
|
+
#if VOL_SHADOW_LOCAL{X} == 1
|
|
263
|
+
lightResult = volIntegrateShadowSlot{X}(tStart, tEnd);
|
|
264
|
+
accumulated += lightResult.xyz;
|
|
265
|
+
evaluatedLights += lightResult.w;
|
|
266
|
+
#endif
|
|
267
|
+
#endif
|
|
268
|
+
`.replace(/\{X\}/g,r.toString()));return`
|
|
269
|
+
varying vUV: vec2f;
|
|
270
|
+
|
|
271
|
+
// Full resolution linear depth of the scene, written by the linear depth pass.
|
|
272
|
+
var textureSampler: texture_2d<f32>;
|
|
273
|
+
|
|
274
|
+
// Ratio between the resolution of the linear depth and the resolution of the scattering buffer.
|
|
275
|
+
uniform volDepthRatio: vec2f;
|
|
276
|
+
|
|
277
|
+
uniform volInverseViewProjection: mat4x4f;
|
|
278
|
+
uniform volCameraPosition: vec3f;
|
|
279
|
+
uniform volCameraForward: vec3f;
|
|
280
|
+
uniform volCameraMinMaxZ: vec2f;
|
|
281
|
+
uniform volFrameIndex: f32;
|
|
282
|
+
|
|
283
|
+
uniform volFogInfos: vec4f;
|
|
284
|
+
uniform volFogColor: vec3f;
|
|
285
|
+
uniform volLinearFogEps: f32;
|
|
286
|
+
uniform volMedium: vec4f;
|
|
287
|
+
|
|
288
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
289
|
+
uniform volViewProjection: mat4x4f;
|
|
290
|
+
uniform volScreenShadowParams: vec4f;
|
|
291
|
+
#endif
|
|
292
|
+
uniform volAmbient: vec3f;
|
|
293
|
+
|
|
294
|
+
// (maximum distance, dithering strength, light extinction clamp, number of point and spot lights in the arrays)
|
|
295
|
+
uniform volParams: vec4f;
|
|
296
|
+
|
|
297
|
+
#if VOL_MAX_ARRAY_LIGHTS > 0
|
|
298
|
+
uniform volLightData: array<vec4f, VOL_MAX_ARRAY_LIGHTS>;
|
|
299
|
+
uniform volLightDiffuse: array<vec4f, VOL_MAX_ARRAY_LIGHTS>;
|
|
300
|
+
uniform volLightDirection: array<vec4f, VOL_MAX_ARRAY_LIGHTS>;
|
|
301
|
+
uniform volLightFalloff: array<vec4f, VOL_MAX_ARRAY_LIGHTS>;
|
|
302
|
+
#endif
|
|
303
|
+
|
|
304
|
+
#if VOL_SHADOW_SLOT_COUNT > 0
|
|
305
|
+
uniform volShadowLightData: array<vec4f, VOL_SHADOW_SLOT_COUNT>;
|
|
306
|
+
uniform volShadowLightDiffuse: array<vec4f, VOL_SHADOW_SLOT_COUNT>;
|
|
307
|
+
uniform volShadowLightDirection: array<vec4f, VOL_SHADOW_SLOT_COUNT>;
|
|
308
|
+
uniform volShadowLightFalloff: array<vec4f, VOL_SHADOW_SLOT_COUNT>;
|
|
309
|
+
uniform volShadowInfo: array<vec4f, VOL_SHADOW_SLOT_COUNT>;
|
|
310
|
+
uniform volShadowMatrix: array<mat4x4f, VOL_SHADOW_SLOT_COUNT>;
|
|
311
|
+
#endif
|
|
312
|
+
|
|
313
|
+
#ifdef VOL_CSM
|
|
314
|
+
uniform volCsmLightData: vec4f;
|
|
315
|
+
uniform volCsmLightDiffuse: vec4f;
|
|
316
|
+
uniform volCsmLightDirection: vec4f;
|
|
317
|
+
uniform volCsmLightFalloff: vec4f;
|
|
318
|
+
uniform volCsmInfo: vec4f;
|
|
319
|
+
uniform volCsmMatrices: array<mat4x4f, VOL_CSM_CASCADES>;
|
|
320
|
+
|
|
321
|
+
#if VOL_CSM_KIND == 1
|
|
322
|
+
var volCsmSamplerSampler: sampler_comparison;
|
|
323
|
+
var volCsmSampler: texture_depth_2d_array;
|
|
324
|
+
#else
|
|
325
|
+
var volCsmSamplerSampler: sampler;
|
|
326
|
+
var volCsmSampler: texture_2d_array<f32>;
|
|
327
|
+
#endif
|
|
328
|
+
#endif
|
|
329
|
+
|
|
330
|
+
// Values shared by every function of the pass, computed once per pixel. Every position the raymarching
|
|
331
|
+
// manipulates is relative to the camera, which keeps the precision of the lights far from the origin.
|
|
332
|
+
var<private> volRayDir: vec3f;
|
|
333
|
+
var<private> volCosForward: f32;
|
|
334
|
+
var<private> volNoise: f32;
|
|
335
|
+
var<private> volJitter: f32;
|
|
336
|
+
|
|
337
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
338
|
+
var<private> volDepthSize: vec2i;
|
|
339
|
+
var<private> volClipOrigin: vec4f;
|
|
340
|
+
var<private> volClipDirection: vec4f;
|
|
341
|
+
#endif
|
|
342
|
+
|
|
343
|
+
${Qe}
|
|
344
|
+
${li("textureSampler")}
|
|
345
|
+
|
|
346
|
+
fn volMod(x: f32, y: f32) -> f32 {
|
|
347
|
+
return x - y * floor(x / y);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
fn volFallOff(value: f32, clipSpaceXY: vec2f, frustumEdgeFalloff: f32) -> f32 {
|
|
351
|
+
let mask = smoothstep(1.0 - frustumEdgeFalloff, 1.00000012, clamp(dot(clipSpaceXY, clipSpaceXY), 0.0, 1.0));
|
|
352
|
+
return mix(value, 1.0, mask);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Reproduces the depth metric computed by the "shadowsVertex" include of Babylon.js: the raw clip space
|
|
356
|
+
// Z is used, without the perspective divide, so the comparison matches what the shadow map stores.
|
|
357
|
+
fn volDepthMetric(clip: vec4f, depthValues: vec2f) -> f32 {
|
|
358
|
+
#ifdef VOL_REVERSE_DEPTH
|
|
359
|
+
return (-clip.z + depthValues.x) / depthValues.y;
|
|
360
|
+
#else
|
|
361
|
+
return (clip.z + depthValues.x) / depthValues.y;
|
|
362
|
+
#endif
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Henyey-Greenstein phase function, normalised to 1 for an isotropic medium. @see the GLSL version.
|
|
366
|
+
fn volPhaseHG(c: f32, g: f32) -> f32 {
|
|
367
|
+
let g2 = g * g;
|
|
368
|
+
let d = max(1.0 + g2 - 2.0 * g * c, 1e-4);
|
|
369
|
+
return (1.0 - g2) / (d * sqrt(d));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
fn volBayer4(p: vec2f) -> f32 {
|
|
373
|
+
let p1 = vec2f(volMod(floor(p.x), 2.0), volMod(floor(p.y), 2.0));
|
|
374
|
+
let p2 = vec2f(volMod(floor(p.x * 0.5), 2.0), volMod(floor(p.y * 0.5), 2.0));
|
|
375
|
+
|
|
376
|
+
let b1 = 2.0 * p1.x + 3.0 * p1.y - 4.0 * p1.x * p1.y;
|
|
377
|
+
let b2 = 2.0 * p2.x + 3.0 * p2.y - 4.0 * p2.x * p2.y;
|
|
378
|
+
|
|
379
|
+
return (b1 * 4.0 + b2) / 16.0;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
fn volInterleavedGradientNoise(p: vec2f) -> f32 {
|
|
383
|
+
return fract(52.9829189 * fract(dot(p, vec2f(0.06711056, 0.00583715))));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Returns the offset of the samples of a light inside their strata. @see the GLSL version.
|
|
387
|
+
fn volStratumOffset(seed: f32) -> f32 {
|
|
388
|
+
#if VOL_DITHER == 0
|
|
389
|
+
return 0.5;
|
|
390
|
+
#else
|
|
391
|
+
return mix(0.5, fract(volNoise + seed * 0.618034), uniforms.volParams.y);
|
|
392
|
+
#endif
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// sigma(t) = -d/dt ln(T(t)), the exact analytic derivative of the optical depth. @see the GLSL version.
|
|
396
|
+
fn volFogExtinction(t: f32) -> f32 {
|
|
397
|
+
#if VOL_FOG_MODE == 2
|
|
398
|
+
return select(1.0 / max(uniforms.volFogInfos.z - t, uniforms.volLinearFogEps), 0.0, t < uniforms.volFogInfos.y);
|
|
399
|
+
#elif VOL_FOG_MODE == 1
|
|
400
|
+
return 2.0 * uniforms.volFogInfos.w * uniforms.volFogInfos.w * t;
|
|
401
|
+
#else
|
|
402
|
+
return uniforms.volFogInfos.w;
|
|
403
|
+
#endif
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// "height" is the absolute altitude of the sample, "t" its distance to the camera.
|
|
407
|
+
fn volExtinctionAt(height: f32, t: f32) -> f32 {
|
|
408
|
+
var sigma = volFogExtinction(t);
|
|
409
|
+
|
|
410
|
+
#ifdef VOL_HEIGHT_FOG
|
|
411
|
+
sigma *= exp(-max(0.0, height - uniforms.volMedium.y) * uniforms.volMedium.z);
|
|
412
|
+
#endif
|
|
413
|
+
|
|
414
|
+
return sigma;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Transmittance of the medium between the camera and the point of the view ray at the distance "t".
|
|
418
|
+
// @see the GLSL version.
|
|
419
|
+
#if VOL_TRANSMITTANCE == 1
|
|
420
|
+
fn volHeightSegment(s1: f32, s2: f32) -> f32 {
|
|
421
|
+
let y0 = uniforms.volCameraPosition.y - uniforms.volMedium.y;
|
|
422
|
+
let h1 = y0 + s1 * volRayDir.y;
|
|
423
|
+
let h2 = y0 + s2 * volRayDir.y;
|
|
424
|
+
|
|
425
|
+
if (h1 + h2 <= 0.0) {
|
|
426
|
+
return s2 - s1;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
let e1 = exp(-uniforms.volMedium.z * max(h1, 0.0));
|
|
430
|
+
let e2 = exp(-uniforms.volMedium.z * max(h2, 0.0));
|
|
431
|
+
let slope = uniforms.volMedium.z * volRayDir.y;
|
|
432
|
+
|
|
433
|
+
return select((e1 - e2) / slope, 0.5 * (e1 + e2) * (s2 - s1), abs(slope * (s2 - s1)) < 1e-4);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
fn volOpticalDepth(t: f32) -> f32 {
|
|
437
|
+
let crossing = select(-1.0, (uniforms.volMedium.y - uniforms.volCameraPosition.y) / volRayDir.y, abs(volRayDir.y) > 1e-6);
|
|
438
|
+
|
|
439
|
+
var opticalLength = 0.0;
|
|
440
|
+
if (crossing > 0.0 && crossing < t) {
|
|
441
|
+
opticalLength = volHeightSegment(0.0, crossing) + volHeightSegment(crossing, t);
|
|
442
|
+
} else {
|
|
443
|
+
opticalLength = volHeightSegment(0.0, t);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return uniforms.volFogInfos.w * opticalLength;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
fn volTransmittance(t: f32) -> f32 {
|
|
450
|
+
return exp(-volOpticalDepth(t));
|
|
451
|
+
}
|
|
452
|
+
#elif VOL_TRANSMITTANCE == 2
|
|
453
|
+
var<private> volOpticalDepths: array<f32, VOL_TRANSMITTANCE_SAMPLES + 1>;
|
|
454
|
+
var<private> volOpticalDepthStart: f32;
|
|
455
|
+
var<private> volOpticalDepthScale: f32;
|
|
456
|
+
|
|
457
|
+
fn volBuildOpticalDepths(tStart: f32, tEnd: f32) {
|
|
458
|
+
let stepSize = (tEnd - tStart) / f32(VOL_TRANSMITTANCE_SAMPLES);
|
|
459
|
+
|
|
460
|
+
volOpticalDepthStart = tStart;
|
|
461
|
+
volOpticalDepthScale = 1.0 / stepSize;
|
|
462
|
+
|
|
463
|
+
var previous = volExtinctionAt(uniforms.volCameraPosition.y + volRayDir.y * tStart, tStart);
|
|
464
|
+
var opticalDepth = previous * tStart;
|
|
465
|
+
|
|
466
|
+
volOpticalDepths[0] = opticalDepth;
|
|
467
|
+
|
|
468
|
+
for (var i: i32 = 1; i <= VOL_TRANSMITTANCE_SAMPLES; i++) {
|
|
469
|
+
let t = tStart + stepSize * f32(i);
|
|
470
|
+
let sigma = volExtinctionAt(uniforms.volCameraPosition.y + volRayDir.y * t, t);
|
|
471
|
+
|
|
472
|
+
opticalDepth += 0.5 * (previous + sigma) * stepSize;
|
|
473
|
+
volOpticalDepths[i] = opticalDepth;
|
|
474
|
+
previous = sigma;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
fn volOpticalDepth(t: f32) -> f32 {
|
|
479
|
+
let x = clamp((t - volOpticalDepthStart) * volOpticalDepthScale, 0.0, f32(VOL_TRANSMITTANCE_SAMPLES));
|
|
480
|
+
let i = min(i32(x), VOL_TRANSMITTANCE_SAMPLES - 1);
|
|
481
|
+
|
|
482
|
+
return mix(volOpticalDepths[i], volOpticalDepths[i + 1], x - f32(i));
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
fn volTransmittance(t: f32) -> f32 {
|
|
486
|
+
return exp(-volOpticalDepth(t));
|
|
487
|
+
}
|
|
488
|
+
#elif VOL_FOG_MODE == 2
|
|
489
|
+
fn volTransmittance(t: f32) -> f32 {
|
|
490
|
+
return clamp((uniforms.volFogInfos.z - t) / max(uniforms.volFogInfos.z - uniforms.volFogInfos.y, uniforms.volLinearFogEps), 0.0, 1.0);
|
|
491
|
+
}
|
|
492
|
+
#else
|
|
493
|
+
fn volOpticalDepth(t: f32) -> f32 {
|
|
494
|
+
#if VOL_FOG_MODE == 1
|
|
495
|
+
let x = t * uniforms.volFogInfos.w;
|
|
496
|
+
return x * x;
|
|
497
|
+
#else
|
|
498
|
+
return t * uniforms.volFogInfos.w;
|
|
499
|
+
#endif
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
fn volTransmittance(t: f32) -> f32 {
|
|
503
|
+
return exp(-volOpticalDepth(t));
|
|
504
|
+
}
|
|
505
|
+
#endif
|
|
506
|
+
|
|
507
|
+
// Transmittance of the medium to the point at the distance "t", combined with the attenuation of the light on
|
|
508
|
+
// its way to that point. @see the GLSL version.
|
|
509
|
+
fn volCombinedTransmittance(t: f32, sigmaT: f32, distanceToLight: f32) -> f32 {
|
|
510
|
+
#ifdef VOL_LIGHT_EXTINCTION
|
|
511
|
+
let lightOpticalDepth = sigmaT * min(distanceToLight, uniforms.volParams.z);
|
|
512
|
+
|
|
513
|
+
#ifdef VOL_OPTICAL_DEPTH
|
|
514
|
+
return exp(-(volOpticalDepth(t) + lightOpticalDepth));
|
|
515
|
+
#else
|
|
516
|
+
return volTransmittance(t) * exp(-lightOpticalDepth);
|
|
517
|
+
#endif
|
|
518
|
+
#else
|
|
519
|
+
return volTransmittance(t);
|
|
520
|
+
#endif
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
524
|
+
// Walks a segment going from a point of the medium towards a light through the depth buffer. The segment is
|
|
525
|
+
// given in clip space, where it is affine. @see the GLSL version.
|
|
526
|
+
fn volScreenShadow(clipStart: vec4f, clipDelta: vec4f, depthStart: f32, depthDelta: f32) -> f32 {
|
|
527
|
+
for (var i: i32 = 1; i <= VOL_SCREEN_SHADOW_STEPS; i++) {
|
|
528
|
+
let u = (f32(i) + volJitter) * (1.0 / f32(VOL_SCREEN_SHADOW_STEPS + 1));
|
|
529
|
+
|
|
530
|
+
let clip = clipStart + clipDelta * u;
|
|
531
|
+
if (clip.w <= 0.0) {
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
let uv = (clip.xy / clip.w) * 0.5 + 0.5;
|
|
536
|
+
if (uv.x < 0.0 || uv.x >= 1.0 || uv.y < 0.0 || uv.y >= 1.0) {
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
let sceneDepth = volReadLinearDepth(vec2i(uv * vec2f(volDepthSize)));
|
|
541
|
+
|
|
542
|
+
let depthDifference = depthStart + depthDelta * u - sceneDepth;
|
|
543
|
+
let bias = max(uniforms.volScreenShadowParams.y * sceneDepth, uniforms.volCameraMinMaxZ.x);
|
|
544
|
+
|
|
545
|
+
if (depthDifference > bias && depthDifference < uniforms.volScreenShadowParams.z * sceneDepth) {
|
|
546
|
+
return 0.0;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
return 1.0;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Occlusion of a point or a spot light, seen from the point of the view ray at the distance "t".
|
|
554
|
+
fn volScreenShadowToLight(t: f32, lightClip: vec4f, lightDepth: f32, distanceToLight: f32) -> f32 {
|
|
555
|
+
let clipStart = volClipOrigin + volClipDirection * t;
|
|
556
|
+
let depthStart = t * volCosForward;
|
|
557
|
+
let fraction = min(1.0, uniforms.volScreenShadowParams.x / max(distanceToLight, 1e-4));
|
|
558
|
+
|
|
559
|
+
return volScreenShadow(clipStart, (lightClip - clipStart) * fraction, depthStart, (lightDepth - depthStart) * fraction);
|
|
560
|
+
}
|
|
561
|
+
#endif
|
|
562
|
+
|
|
563
|
+
// Evaluates the in-scattered radiance coming from a directional light, without any shadowing.
|
|
564
|
+
fn volEvalDirectionalLight(data: vec4f, diffuse: vec4f) -> vec3f {
|
|
565
|
+
return diffuse.rgb * volPhaseHG(dot(volRayDir, data.xyz), diffuse.a);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Evaluates the in-scattered radiance coming from a point or a spot light at the given position, relative to
|
|
569
|
+
// the camera, without any shadowing nor extinction. Returns the radiance in "xyz" and the distance to the light in "w".
|
|
570
|
+
fn volEvalLocalLight(data: vec4f, diffuse: vec4f, direction: vec4f, falloff: vec4f, position: vec3f) -> vec4f {
|
|
571
|
+
let toLight = data.xyz - position;
|
|
572
|
+
let distanceToLight = max(length(toLight), 1e-4);
|
|
573
|
+
let lightVector = toLight / distanceToLight;
|
|
574
|
+
|
|
575
|
+
// Same linear attenuation as "computeLighting" in the "lightsFragmentFunctions" include.
|
|
576
|
+
var attenuation = max(0.0, 1.0 - distanceToLight / falloff.x);
|
|
577
|
+
|
|
578
|
+
if (data.w == 2.0) {
|
|
579
|
+
let cosAngle = max(0.0, dot(direction.xyz, -lightVector));
|
|
580
|
+
attenuation *= select(0.0, max(0.0, pow(cosAngle, falloff.y)), cosAngle >= direction.w);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (attenuation <= 0.0) {
|
|
584
|
+
return vec4f(0.0, 0.0, 0.0, distanceToLight);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return vec4f(diffuse.rgb * (attenuation * volPhaseHG(dot(volRayDir, lightVector), diffuse.a)), distanceToLight);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Returns the part of the view ray crossing the cone of a spot light, cut by the sphere of its range.
|
|
591
|
+
// @see the GLSL version.
|
|
592
|
+
fn volConeChord(apex: vec3f, axis: vec3f, cosAngle: f32, range: f32, sphere: vec2f) -> vec2f {
|
|
593
|
+
if (cosAngle <= 1e-3) {
|
|
594
|
+
return sphere;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
let origin = apex * (-1.0 / range);
|
|
598
|
+
let dv = dot(volRayDir, axis);
|
|
599
|
+
let ov = dot(origin, axis);
|
|
600
|
+
let cos2 = cosAngle * cosAngle;
|
|
601
|
+
|
|
602
|
+
let a = dv * dv - cos2;
|
|
603
|
+
let b = dv * ov - cos2 * dot(volRayDir, origin);
|
|
604
|
+
let c = ov * ov - cos2 * dot(origin, origin);
|
|
605
|
+
|
|
606
|
+
if (abs(a) < 1e-4) {
|
|
607
|
+
return sphere;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
let discriminant = b * b - a * c;
|
|
611
|
+
var cone = vec2f(0.0);
|
|
612
|
+
|
|
613
|
+
if (a < 0.0) {
|
|
614
|
+
if (discriminant <= 0.0) {
|
|
615
|
+
return vec2f(1.0, -1.0);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
let s = sqrt(discriminant);
|
|
619
|
+
cone = vec2f((-b + s) / a, (-b - s) / a);
|
|
620
|
+
|
|
621
|
+
if (dv * 0.5 * (cone.x + cone.y) + ov < 0.0) {
|
|
622
|
+
return vec2f(1.0, -1.0);
|
|
623
|
+
}
|
|
624
|
+
} else {
|
|
625
|
+
let s = sqrt(max(discriminant, 0.0));
|
|
626
|
+
cone = select(vec2f(-1e30, (-b - s) / a), vec2f((-b + s) / a, 1e30), dv > 0.0);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return vec2f(max(sphere.x, (cone.x - 0.005) * range), min(sphere.y, (cone.y + 0.005) * range));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Returns the part of the view ray, as distances to the camera, crossing the volume a point or a spot light
|
|
633
|
+
// reaches. @see the GLSL version.
|
|
634
|
+
fn volLightChord(data: vec4f, direction: vec4f, range: f32) -> vec2f {
|
|
635
|
+
let closest = dot(data.xyz, volRayDir);
|
|
636
|
+
let offset = data.xyz - volRayDir * closest;
|
|
637
|
+
let halfChord2 = range * range - dot(offset, offset);
|
|
638
|
+
|
|
639
|
+
if (halfChord2 <= 0.0) {
|
|
640
|
+
return vec2f(1.0, -1.0);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
let halfChord = sqrt(halfChord2);
|
|
644
|
+
var chord = vec2f(closest - halfChord, closest + halfChord);
|
|
645
|
+
|
|
646
|
+
if (data.w == 2.0) {
|
|
647
|
+
chord = volConeChord(data.xyz, direction.xyz, direction.w, range, chord);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return chord;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Returns the number of samples taken over the given chord of a light. @see the GLSL version.
|
|
654
|
+
fn volLocalSampleCount(chordLength: f32, range: f32, rayLength: f32) -> i32 {
|
|
655
|
+
let count = max(f32(VOL_LIGHT_STEPS) * chordLength / (2.0 * range), f32(VOL_STEPS) * chordLength / rayLength);
|
|
656
|
+
return clamp(i32(ceil(count)), 2, VOL_LOCAL_MAX_STEPS);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
${e.join(`
|
|
660
|
+
`)}
|
|
661
|
+
|
|
662
|
+
#ifdef VOL_CSM
|
|
663
|
+
// The parts of the view ray inside the box of each cascade, and the clip space position of the view ray in the
|
|
664
|
+
// current cascade. @see the GLSL version.
|
|
665
|
+
var<private> volCsmEntries: vec4f;
|
|
666
|
+
var<private> volCsmExits: vec4f;
|
|
667
|
+
var<private> volCsmCurrent: i32;
|
|
668
|
+
var<private> volCsmClipOrigin: vec4f;
|
|
669
|
+
var<private> volCsmClipDirection: vec4f;
|
|
670
|
+
|
|
671
|
+
// Returns the part of the view ray inside the box of a cascade. @see the GLSL version.
|
|
672
|
+
fn volCsmBoxInterval(origin: vec4f, direction: vec4f) -> vec2f {
|
|
673
|
+
#ifdef VOL_NDC_HALF_Z
|
|
674
|
+
let boxMin = vec3f(-0.96, -0.96, 0.0);
|
|
675
|
+
#else
|
|
676
|
+
let boxMin = vec3f(-0.96, -0.96, -1.0);
|
|
677
|
+
#endif
|
|
678
|
+
let boxMax = vec3f(0.96, 0.96, 1.0);
|
|
679
|
+
|
|
680
|
+
let safeDirection = select(vec3f(1e-9), direction.xyz, abs(direction.xyz) > vec3f(1e-9));
|
|
681
|
+
let inverseDirection = 1.0 / safeDirection;
|
|
682
|
+
let t0 = (boxMin - origin.xyz) * inverseDirection;
|
|
683
|
+
let t1 = (boxMax - origin.xyz) * inverseDirection;
|
|
684
|
+
let tMin = min(t0, t1);
|
|
685
|
+
let tMax = max(t0, t1);
|
|
686
|
+
|
|
687
|
+
return vec2f(max(max(tMin.x, tMin.y), tMin.z), min(min(tMax.x, tMax.y), tMax.z));
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
fn volPrepareCsm() {
|
|
691
|
+
volCsmEntries = vec4f(1e30);
|
|
692
|
+
volCsmExits = vec4f(-1e30);
|
|
693
|
+
|
|
694
|
+
for (var cascade: i32 = 0; cascade < VOL_CSM_CASCADES; cascade++) {
|
|
695
|
+
let interval = volCsmBoxInterval(uniforms.volCsmMatrices[cascade] * vec4f(uniforms.volCameraPosition, 1.0), uniforms.volCsmMatrices[cascade] * vec4f(volRayDir, 0.0));
|
|
696
|
+
volCsmEntries[cascade] = interval.x;
|
|
697
|
+
volCsmExits[cascade] = interval.y;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
volCsmCurrent = -1;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Returns the shadowing of the point of the view ray at the distance "t" from the camera.
|
|
704
|
+
fn volCsmShadow(t: f32) -> f32 {
|
|
705
|
+
// The first cascade containing the sample is the most detailed one.
|
|
706
|
+
var cascade: i32 = -1;
|
|
707
|
+
for (var i: i32 = VOL_CSM_CASCADES - 1; i >= 0; i--) {
|
|
708
|
+
if (t >= volCsmEntries[i] && t <= volCsmExits[i]) {
|
|
709
|
+
cascade = i;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
if (cascade < 0) {
|
|
714
|
+
return 1.0;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (cascade != volCsmCurrent) {
|
|
718
|
+
volCsmCurrent = cascade;
|
|
719
|
+
volCsmClipOrigin = uniforms.volCsmMatrices[cascade] * vec4f(uniforms.volCameraPosition, 1.0);
|
|
720
|
+
volCsmClipDirection = uniforms.volCsmMatrices[cascade] * vec4f(volRayDir, 0.0);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// The projection of a directional light is orthographic, "w" is always 1.
|
|
724
|
+
let clip = volCsmClipOrigin + volCsmClipDirection * t;
|
|
725
|
+
let clipSpace = clip.xyz;
|
|
726
|
+
|
|
727
|
+
#if VOL_CSM_KIND == 1
|
|
728
|
+
var uvDepth = 0.5 * clipSpace + vec3f(0.5);
|
|
729
|
+
#ifdef VOL_NDC_HALF_Z
|
|
730
|
+
uvDepth.z = clipSpace.z;
|
|
731
|
+
#endif
|
|
732
|
+
|
|
733
|
+
let shadow = textureSampleCompareLevel(volCsmSampler, volCsmSamplerSampler, uvDepth.xy, cascade, uvDepth.z);
|
|
734
|
+
return volFallOff(mix(uniforms.volCsmInfo.x, 1.0, shadow), clipSpace.xy, uniforms.volCsmLightFalloff.z);
|
|
735
|
+
#else
|
|
736
|
+
let uv = 0.5 * clipSpace.xy + vec2f(0.5);
|
|
737
|
+
let depthMetric = clamp(volDepthMetric(clip, uniforms.volCsmInfo.zw), 0.0, 1.0);
|
|
738
|
+
|
|
739
|
+
#ifdef VOL_CSM_PACKED
|
|
740
|
+
let shadowMapSample = volUnpack(textureSampleLevel(volCsmSampler, volCsmSamplerSampler, uv, cascade, 0.0));
|
|
741
|
+
#else
|
|
742
|
+
let shadowMapSample = textureSampleLevel(volCsmSampler, volCsmSamplerSampler, uv, cascade, 0.0).x;
|
|
743
|
+
#endif
|
|
744
|
+
|
|
745
|
+
return select(1.0, volFallOff(uniforms.volCsmInfo.x, clipSpace.xy, uniforms.volCsmLightFalloff.z), depthMetric > shadowMapSample);
|
|
746
|
+
#endif
|
|
747
|
+
}
|
|
748
|
+
#endif
|
|
749
|
+
|
|
750
|
+
#if VOL_GLOBAL_LIGHT_COUNT > 0
|
|
751
|
+
// Marches the whole view ray for the lights that reach all of it: the directional lights. Returns the
|
|
752
|
+
// in-scattered radiance in "xyz" and the number of lights evaluated in "w".
|
|
753
|
+
fn volMarchGlobalLights(tStart: f32, tEnd: f32) -> vec4f {
|
|
754
|
+
#if VOL_DIRECTIONAL_LIGHT_COUNT > 0
|
|
755
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
756
|
+
// The occlusion search of a directional light always walks the same direction over the same distance,
|
|
757
|
+
// only its starting point moves along the view ray.
|
|
758
|
+
var directionClip: array<vec4f, VOL_DIRECTIONAL_LIGHT_COUNT>;
|
|
759
|
+
var directionDepth: array<f32, VOL_DIRECTIONAL_LIGHT_COUNT>;
|
|
760
|
+
|
|
761
|
+
for (var li: i32 = 0; li < VOL_DIRECTIONAL_LIGHT_COUNT; li++) {
|
|
762
|
+
let traced = uniforms.volLightData[li].xyz * uniforms.volScreenShadowParams.x;
|
|
763
|
+
directionClip[li] = uniforms.volViewProjection * vec4f(traced, 0.0);
|
|
764
|
+
directionDepth[li] = dot(traced, uniforms.volCameraForward);
|
|
765
|
+
}
|
|
766
|
+
#endif
|
|
767
|
+
#endif
|
|
768
|
+
|
|
769
|
+
#if VOL_DISTRIBUTION == 1
|
|
770
|
+
let ratio = pow(tEnd / tStart, 1.0 / f32(VOL_STEPS));
|
|
771
|
+
#else
|
|
772
|
+
let uniformStep = (tEnd - tStart) / f32(VOL_STEPS);
|
|
773
|
+
#endif
|
|
774
|
+
|
|
775
|
+
var result = vec3f(0.0);
|
|
776
|
+
var evaluatedLights = 0.0;
|
|
777
|
+
var segmentStart = tStart;
|
|
778
|
+
|
|
779
|
+
for (var i: i32 = 0; i < VOL_STEPS; i++) {
|
|
780
|
+
#if VOL_DISTRIBUTION == 1
|
|
781
|
+
let segmentEnd = segmentStart * ratio;
|
|
782
|
+
#else
|
|
783
|
+
let segmentEnd = segmentStart + uniformStep;
|
|
784
|
+
#endif
|
|
785
|
+
|
|
786
|
+
let segmentBegin = segmentStart;
|
|
787
|
+
let dt = segmentEnd - segmentBegin;
|
|
788
|
+
|
|
789
|
+
// The jitter picks the sample inside its own segment, so the marched interval stays exactly
|
|
790
|
+
// [tStart, tEnd] whatever the dithering does.
|
|
791
|
+
let t = segmentBegin + dt * volJitter;
|
|
792
|
+
segmentStart = segmentEnd;
|
|
793
|
+
|
|
794
|
+
let position = volRayDir * t;
|
|
795
|
+
let sigmaT = volExtinctionAt(uniforms.volCameraPosition.y + position.y, t);
|
|
796
|
+
|
|
797
|
+
if (sigmaT <= 1e-6) {
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// The transmittance at the START of the segment: the factor below accounts for the extinction
|
|
802
|
+
// across the segment itself.
|
|
803
|
+
let viewTransmittance = volTransmittance(segmentBegin);
|
|
804
|
+
if (viewTransmittance < 0.003) {
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
var scattering = vec3f(0.0);
|
|
809
|
+
var stepLights = 0.0;
|
|
810
|
+
|
|
811
|
+
${i.join("")}
|
|
812
|
+
#ifdef VOL_CSM
|
|
813
|
+
{
|
|
814
|
+
scattering += volEvalDirectionalLight(uniforms.volCsmLightData, uniforms.volCsmLightDiffuse) * mix(1.0, volCsmShadow(t), uniforms.volCsmLightFalloff.w);
|
|
815
|
+
stepLights += 1.0;
|
|
816
|
+
}
|
|
817
|
+
#endif
|
|
818
|
+
|
|
819
|
+
#if VOL_DIRECTIONAL_LIGHT_COUNT > 0
|
|
820
|
+
for (var li: i32 = 0; li < VOL_DIRECTIONAL_LIGHT_COUNT; li++) {
|
|
821
|
+
var contribution = volEvalDirectionalLight(uniforms.volLightData[li], uniforms.volLightDiffuse[li]);
|
|
822
|
+
|
|
823
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
824
|
+
// "volLightFalloff[li].z" carries whether this light asked to be occluded by the geometry.
|
|
825
|
+
if (uniforms.volLightFalloff[li].z > 0.5) {
|
|
826
|
+
contribution *= volScreenShadow(volClipOrigin + volClipDirection * t, directionClip[li], t * volCosForward, directionDepth[li]);
|
|
827
|
+
}
|
|
828
|
+
#endif
|
|
829
|
+
|
|
830
|
+
scattering += contribution;
|
|
831
|
+
stepLights += 1.0;
|
|
832
|
+
}
|
|
833
|
+
#endif
|
|
834
|
+
|
|
835
|
+
evaluatedLights = max(evaluatedLights, stepLights);
|
|
836
|
+
|
|
837
|
+
// Analytic integral of the in-scattering over the segment. @see the GLSL version.
|
|
838
|
+
result += scattering * (viewTransmittance * (1.0 - exp(-sigmaT * dt)));
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
return vec4f(result, evaluatedLights);
|
|
842
|
+
}
|
|
843
|
+
#endif
|
|
844
|
+
|
|
845
|
+
#if VOL_LOCAL_ARRAY_LIGHTS == 1
|
|
846
|
+
// Integrates a point or a spot light of the arrays over the part of the view ray crossing its volume.
|
|
847
|
+
// Returns the in-scattered radiance in "xyz" and whether the light was evaluated in "w".
|
|
848
|
+
fn volIntegrateArrayLight(index: i32, tStart: f32, tEnd: f32) -> vec4f {
|
|
849
|
+
let data = uniforms.volLightData[index];
|
|
850
|
+
let direction = uniforms.volLightDirection[index];
|
|
851
|
+
let falloff = uniforms.volLightFalloff[index];
|
|
852
|
+
|
|
853
|
+
let chord = volLightChord(data, direction, falloff.x);
|
|
854
|
+
let t0 = max(chord.x, tStart);
|
|
855
|
+
let t1 = min(chord.y, tEnd);
|
|
856
|
+
|
|
857
|
+
if (t1 <= t0) {
|
|
858
|
+
return vec4f(0.0);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
let diffuse = uniforms.volLightDiffuse[index];
|
|
862
|
+
|
|
863
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
864
|
+
// "falloff.z" carries whether this light asked to be occluded by the geometry.
|
|
865
|
+
let occluded = falloff.z > 0.5;
|
|
866
|
+
let lightClip = volClipOrigin + uniforms.volViewProjection * vec4f(data.xyz, 0.0);
|
|
867
|
+
let lightDepth = dot(data.xyz, uniforms.volCameraForward);
|
|
868
|
+
#endif
|
|
869
|
+
|
|
870
|
+
${yo("f32(index)",`#ifdef VOL_SCREEN_SHADOWS
|
|
871
|
+
if (occluded) {
|
|
872
|
+
contribution *= volScreenShadowToLight(t, lightClip, lightDepth, distanceToLight);
|
|
873
|
+
}
|
|
874
|
+
#endif`)}
|
|
875
|
+
}
|
|
876
|
+
#endif
|
|
877
|
+
|
|
878
|
+
@fragment
|
|
879
|
+
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
880
|
+
// Reconstruct the world space direction of the view ray from the UV of the pixel.
|
|
881
|
+
let farPoint = uniforms.volInverseViewProjection * vec4f(input.vUV * 2.0 - 1.0, 1.0, 1.0);
|
|
882
|
+
volRayDir = normalize(farPoint.xyz / farPoint.w - uniforms.volCameraPosition);
|
|
883
|
+
|
|
884
|
+
// The depth map stores the distance along the view axis, the ray is not aligned with it.
|
|
885
|
+
volCosForward = max(dot(volRayDir, uniforms.volCameraForward), 1e-4);
|
|
886
|
+
let pixel = fragmentInputs.position.xy;
|
|
887
|
+
let depthSize = vec2i(textureDimensions(textureSampler));
|
|
888
|
+
let viewZ = volReadLinearDepth(volScatterToDepthTexel(vec2i(pixel), depthSize));
|
|
889
|
+
|
|
890
|
+
let tEnd = min(viewZ / volCosForward, uniforms.volParams.x);
|
|
891
|
+
let tStart = max(uniforms.volCameraMinMaxZ.x / volCosForward, 1e-3);
|
|
892
|
+
|
|
893
|
+
var result = vec3f(0.0);
|
|
894
|
+
var finalTransmittance = 1.0;
|
|
895
|
+
var evaluatedLights = 0.0;
|
|
896
|
+
|
|
897
|
+
// WGSL has no early return from the fragment entry point, the whole integration is guarded instead.
|
|
898
|
+
if (tEnd > tStart) {
|
|
899
|
+
// Offsets the samples inside their segments to trade the banding produced by a low sample count for noise.
|
|
900
|
+
volNoise = 0.0;
|
|
901
|
+
#if VOL_DITHER == 1
|
|
902
|
+
volNoise = volBayer4(pixel);
|
|
903
|
+
#elif VOL_DITHER == 2
|
|
904
|
+
var ditherPosition = pixel;
|
|
905
|
+
#ifdef VOL_TEMPORAL_JITTER
|
|
906
|
+
ditherPosition += uniforms.volFrameIndex * 5.588238;
|
|
907
|
+
#endif
|
|
908
|
+
volNoise = volInterleavedGradientNoise(ditherPosition);
|
|
909
|
+
#endif
|
|
910
|
+
volJitter = volNoise * uniforms.volParams.y;
|
|
911
|
+
|
|
912
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
913
|
+
volDepthSize = depthSize;
|
|
914
|
+
volClipOrigin = uniforms.volViewProjection * vec4f(uniforms.volCameraPosition, 1.0);
|
|
915
|
+
volClipDirection = uniforms.volViewProjection * vec4f(volRayDir, 0.0);
|
|
916
|
+
#endif
|
|
917
|
+
|
|
918
|
+
#if VOL_TRANSMITTANCE == 2
|
|
919
|
+
volBuildOpticalDepths(tStart, tEnd);
|
|
920
|
+
#endif
|
|
921
|
+
|
|
922
|
+
#ifdef VOL_CSM
|
|
923
|
+
volPrepareCsm();
|
|
924
|
+
#endif
|
|
925
|
+
|
|
926
|
+
// The in-scattering of the constant ambient light has a closed form whatever the medium. @see the GLSL version.
|
|
927
|
+
var accumulated = uniforms.volAmbient * (volTransmittance(tStart) - volTransmittance(tEnd));
|
|
928
|
+
var lightResult = vec4f(0.0);
|
|
929
|
+
|
|
930
|
+
#if VOL_GLOBAL_LIGHT_COUNT > 0
|
|
931
|
+
lightResult = volMarchGlobalLights(tStart, tEnd);
|
|
932
|
+
accumulated += lightResult.xyz;
|
|
933
|
+
evaluatedLights += lightResult.w;
|
|
934
|
+
#endif
|
|
935
|
+
|
|
936
|
+
${o.join("")}
|
|
937
|
+
|
|
938
|
+
#if VOL_LOCAL_ARRAY_LIGHTS == 1
|
|
939
|
+
let localEnd = VOL_DIRECTIONAL_LIGHT_COUNT + i32(uniforms.volParams.w + 0.5);
|
|
940
|
+
|
|
941
|
+
for (var i: i32 = VOL_DIRECTIONAL_LIGHT_COUNT; i < VOL_MAX_ARRAY_LIGHTS; i++) {
|
|
942
|
+
if (i >= localEnd) {
|
|
943
|
+
break;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
lightResult = volIntegrateArrayLight(i, tStart, tEnd);
|
|
947
|
+
accumulated += lightResult.xyz;
|
|
948
|
+
evaluatedLights += lightResult.w;
|
|
949
|
+
}
|
|
950
|
+
#endif
|
|
951
|
+
|
|
952
|
+
// The scattering coefficient is a fraction of the extinction, which guarantees energy conservation.
|
|
953
|
+
result = accumulated * uniforms.volMedium.x * uniforms.volFogColor;
|
|
954
|
+
finalTransmittance = volTransmittance(tEnd);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
#if VOL_DEBUG == 3
|
|
958
|
+
// From blue for no light to red for 16 lights or more evaluated by the pixel.
|
|
959
|
+
let ratioOfBudget = clamp(evaluatedLights / 16.0, 0.0, 1.0);
|
|
960
|
+
result = vec3f(ratioOfBudget, 1.0 - abs(ratioOfBudget * 2.0 - 1.0), 1.0 - ratioOfBudget);
|
|
961
|
+
#endif
|
|
962
|
+
|
|
963
|
+
#ifdef VOL_LDR_ENCODE
|
|
964
|
+
result = result / (1.0 + result);
|
|
965
|
+
#endif
|
|
966
|
+
|
|
967
|
+
fragmentOutputs.color = vec4f(result, finalTransmittance);
|
|
968
|
+
}
|
|
969
|
+
`}n(Gn,"buildVolumetricLightingScatteringShaderWGSL");function Bn(){return`
|
|
970
|
+
varying vUV: vec2f;
|
|
971
|
+
|
|
972
|
+
var textureSampler: texture_2d<f32>;
|
|
973
|
+
var volLinearDepthSampler: texture_2d<f32>;
|
|
974
|
+
|
|
975
|
+
uniform volCameraMinMaxZ: vec2f;
|
|
976
|
+
uniform volDepthRatio: vec2f;
|
|
977
|
+
uniform volBlurDirection: vec2f;
|
|
978
|
+
uniform volBlurParams: vec2f;
|
|
979
|
+
|
|
980
|
+
${Qe}
|
|
981
|
+
${li("volLinearDepthSampler")}
|
|
982
|
+
|
|
983
|
+
@fragment
|
|
984
|
+
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
985
|
+
// Every tap is an exact texel compared using the depth the raymarching used for it. @see the GLSL version.
|
|
986
|
+
let size = vec2i(textureDimensions(textureSampler));
|
|
987
|
+
let depthSize = vec2i(textureDimensions(volLinearDepthSampler));
|
|
988
|
+
let center = vec2i(fragmentInputs.position.xy);
|
|
989
|
+
let direction = vec2i(uniforms.volBlurDirection);
|
|
990
|
+
|
|
991
|
+
let centerDepth = volReadLinearDepth(volScatterToDepthTexel(center, depthSize));
|
|
992
|
+
let inverseDepthThreshold = 1.0 / max(uniforms.volBlurParams.y * max(centerDepth, uniforms.volCameraMinMaxZ.x), 1e-4);
|
|
993
|
+
let sigma = max(uniforms.volBlurParams.x, 1e-4);
|
|
994
|
+
let inverseTwoSigma2 = 1.0 / (2.0 * sigma * sigma);
|
|
995
|
+
|
|
996
|
+
var result = textureLoad(textureSampler, center, 0);
|
|
997
|
+
var totalWeight = 1.0;
|
|
998
|
+
|
|
999
|
+
for (var i: i32 = 1; i <= VOL_BLUR_RADIUS; i++) {
|
|
1000
|
+
let spatialWeight = exp(-f32(i * i) * inverseTwoSigma2);
|
|
1001
|
+
|
|
1002
|
+
let positive = center + direction * i;
|
|
1003
|
+
let negative = center - direction * i;
|
|
1004
|
+
|
|
1005
|
+
if (positive.x < size.x && positive.y < size.y) {
|
|
1006
|
+
let weight = spatialWeight * exp(-abs(volReadLinearDepth(volScatterToDepthTexel(positive, depthSize)) - centerDepth) * inverseDepthThreshold);
|
|
1007
|
+
result += textureLoad(textureSampler, positive, 0) * weight;
|
|
1008
|
+
totalWeight += weight;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
if (negative.x >= 0 && negative.y >= 0) {
|
|
1012
|
+
let weight = spatialWeight * exp(-abs(volReadLinearDepth(volScatterToDepthTexel(negative, depthSize)) - centerDepth) * inverseDepthThreshold);
|
|
1013
|
+
result += textureLoad(textureSampler, negative, 0) * weight;
|
|
1014
|
+
totalWeight += weight;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
fragmentOutputs.color = result / totalWeight;
|
|
1019
|
+
}
|
|
1020
|
+
`}n(Bn,"buildVolumetricLightingBlurShaderWGSL");function zn(){return`
|
|
1021
|
+
varying vUV: vec2f;
|
|
1022
|
+
|
|
1023
|
+
var textureSampler: texture_2d<f32>;
|
|
1024
|
+
var volSceneSamplerSampler: sampler;
|
|
1025
|
+
var volSceneSampler: texture_2d<f32>;
|
|
1026
|
+
var volLinearDepthSampler: texture_2d<f32>;
|
|
1027
|
+
|
|
1028
|
+
uniform volCameraMinMaxZ: vec2f;
|
|
1029
|
+
uniform volDepthRatio: vec2f;
|
|
1030
|
+
uniform volComposeParams: vec4f;
|
|
1031
|
+
|
|
1032
|
+
${Qe}
|
|
1033
|
+
${li("volLinearDepthSampler")}
|
|
1034
|
+
|
|
1035
|
+
fn volMod(x: f32, y: f32) -> f32 {
|
|
1036
|
+
return x - y * floor(x / y);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
fn volBayer8(p: vec2f) -> f32 {
|
|
1040
|
+
let p1 = vec2f(volMod(floor(p.x), 2.0), volMod(floor(p.y), 2.0));
|
|
1041
|
+
let p2 = vec2f(volMod(floor(p.x * 0.5), 2.0), volMod(floor(p.y * 0.5), 2.0));
|
|
1042
|
+
let p3 = vec2f(volMod(floor(p.x * 0.25), 2.0), volMod(floor(p.y * 0.25), 2.0));
|
|
1043
|
+
|
|
1044
|
+
let b1 = 2.0 * p1.x + 3.0 * p1.y - 4.0 * p1.x * p1.y;
|
|
1045
|
+
let b2 = 2.0 * p2.x + 3.0 * p2.y - 4.0 * p2.x * p2.y;
|
|
1046
|
+
let b3 = 2.0 * p3.x + 3.0 * p3.y - 4.0 * p3.x * p3.y;
|
|
1047
|
+
|
|
1048
|
+
return (b1 * 16.0 + b2 * 4.0 + b3) / 64.0;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// Nearest depth upsampling. @see the GLSL version.
|
|
1052
|
+
fn volUpsample(uv0: vec2f, centerDepth: f32, depthSize: vec2i) -> vec4f {
|
|
1053
|
+
let size = vec2i(textureDimensions(textureSampler));
|
|
1054
|
+
let texelCoordinate = uv0 * vec2f(size) - 0.5;
|
|
1055
|
+
let baseCoordinate = floor(texelCoordinate);
|
|
1056
|
+
let fraction = texelCoordinate - baseCoordinate;
|
|
1057
|
+
|
|
1058
|
+
let base = vec2i(baseCoordinate);
|
|
1059
|
+
let maximum = size - vec2i(1);
|
|
1060
|
+
|
|
1061
|
+
let inverseDepthThreshold = 1.0 / max(uniforms.volComposeParams.z * max(centerDepth, uniforms.volCameraMinMaxZ.x), 1e-4);
|
|
1062
|
+
|
|
1063
|
+
var result = vec4f(0.0);
|
|
1064
|
+
var totalWeight = 0.0;
|
|
1065
|
+
|
|
1066
|
+
var nearestSample = vec4f(0.0);
|
|
1067
|
+
var nearestDistance = 1e20;
|
|
1068
|
+
|
|
1069
|
+
for (var y: i32 = 0; y < 2; y++) {
|
|
1070
|
+
for (var x: i32 = 0; x < 2; x++) {
|
|
1071
|
+
let coordinates = clamp(base + vec2i(x, y), vec2i(0), maximum);
|
|
1072
|
+
|
|
1073
|
+
let bilinearWeight = select(fraction.x, 1.0 - fraction.x, x == 0) * select(fraction.y, 1.0 - fraction.y, y == 0);
|
|
1074
|
+
let depthDistance = abs(volReadLinearDepth(volScatterToDepthTexel(coordinates, depthSize)) - centerDepth);
|
|
1075
|
+
|
|
1076
|
+
let tap = textureLoad(textureSampler, coordinates, 0);
|
|
1077
|
+
|
|
1078
|
+
if (depthDistance < nearestDistance) {
|
|
1079
|
+
nearestDistance = depthDistance;
|
|
1080
|
+
nearestSample = tap;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
let weight = bilinearWeight / (1e-4 + depthDistance * inverseDepthThreshold);
|
|
1084
|
+
result += tap * weight;
|
|
1085
|
+
totalWeight += weight;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Every tap sits on the other side of a silhouette, fall back to the closest one instead of averaging.
|
|
1090
|
+
return select(nearestSample, result / totalWeight, totalWeight > 1e-4);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
@fragment
|
|
1094
|
+
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
1095
|
+
// The linear depth has the full resolution of the canvas. @see the GLSL version.
|
|
1096
|
+
let depthSize = vec2i(textureDimensions(volLinearDepthSampler));
|
|
1097
|
+
let centerDepth = volReadLinearDepth(min(vec2i(input.vUV * vec2f(depthSize)), depthSize - 1));
|
|
1098
|
+
|
|
1099
|
+
var volumetric = volUpsample(input.vUV, centerDepth, depthSize);
|
|
1100
|
+
|
|
1101
|
+
#ifdef VOL_LDR_ENCODE
|
|
1102
|
+
volumetric = vec4f(volumetric.rgb / max(vec3f(1e-4), 1.0 - volumetric.rgb), volumetric.a);
|
|
1103
|
+
#endif
|
|
1104
|
+
|
|
1105
|
+
// WGSL has no early return from the fragment entry point, so the debug outputs are branches instead.
|
|
1106
|
+
#if VOL_DEBUG == 1 || VOL_DEBUG == 3
|
|
1107
|
+
fragmentOutputs.color = vec4f(volumetric.rgb * uniforms.volComposeParams.x, 1.0);
|
|
1108
|
+
#elif VOL_DEBUG == 2
|
|
1109
|
+
fragmentOutputs.color = vec4f(vec3f(volumetric.a), 1.0);
|
|
1110
|
+
#else
|
|
1111
|
+
var sceneColor = textureSampleLevel(volSceneSampler, volSceneSamplerSampler, input.vUV, 0.0).rgb;
|
|
1112
|
+
|
|
1113
|
+
sceneColor *= mix(1.0, volumetric.a, uniforms.volComposeParams.y);
|
|
1114
|
+
|
|
1115
|
+
var result = sceneColor + volumetric.rgb * uniforms.volComposeParams.x;
|
|
1116
|
+
|
|
1117
|
+
// Breaks up the banding an 8 bits output would otherwise show on the smooth gradients of the shafts.
|
|
1118
|
+
result += (volBayer8(fragmentInputs.position.xy) - 0.5) * uniforms.volComposeParams.w;
|
|
1119
|
+
|
|
1120
|
+
fragmentOutputs.color = vec4f(result, 1.0);
|
|
1121
|
+
#endif
|
|
1122
|
+
}
|
|
1123
|
+
`}n(zn,"buildVolumetricLightingComposeShaderWGSL");function bo(){return{linearDepth:Nn(),scattering:Gn(A),blur:Bn(),compose:zn()}}n(bo,"getVolumetricLightingShadersWGSL");var j=require("babylonjs"),Co=require("babylonjs"),et="volumetricLightingLinearDepth",tt="volumetricLightingScattering",it="volumetricLightingBlur",ot="volumetricLightingCompose",Je=`
|
|
1124
|
+
float volUnpack(vec4 color) {
|
|
1125
|
+
const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
|
|
1126
|
+
return dot(color, bitShift);
|
|
1127
|
+
}
|
|
1128
|
+
`,Hn=`
|
|
1129
|
+
float volSampleDepth(sampler2D s, vec2 uv) {
|
|
1130
|
+
#ifdef VOL_DEPTH_PACKED
|
|
1131
|
+
return volUnpack(texture2D(s, uv));
|
|
1132
|
+
#else
|
|
1133
|
+
return texture2D(s, uv).r;
|
|
1134
|
+
#endif
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// Converts the raw value stored in the depth map into a distance along the view axis, in scene units.
|
|
1138
|
+
float volLinearDepth(float d) {
|
|
1139
|
+
#ifdef VOL_DEPTH_VIEWZ
|
|
1140
|
+
// The depth renderer stores the view space Z directly. The sky is cleared to 0.
|
|
1141
|
+
return (d <= 0.0) ? volCameraMinMaxZ.y : d;
|
|
1142
|
+
#else
|
|
1143
|
+
// The depth renderer stores "(clipZ + minZ) / (minZ + maxZ)", which is affine in the view space Z
|
|
1144
|
+
// for both the perspective and the orthographic projections. "volDepthUnpack" holds the two
|
|
1145
|
+
// coefficients of the exact inverse, computed on the CPU from the projection matrix of the scene.
|
|
1146
|
+
// The sky is cleared to 1, which maps back to the far plane.
|
|
1147
|
+
return volDepthUnpack.x * d + volDepthUnpack.y;
|
|
1148
|
+
#endif
|
|
1149
|
+
}
|
|
1150
|
+
`,ci=`
|
|
1151
|
+
// Returns the distance along the view axis, in scene units, of the texel at the given coordinates.
|
|
1152
|
+
float volReadLinearDepth(sampler2D s, ivec2 coordinates) {
|
|
1153
|
+
#ifdef VOL_LINEAR_DEPTH_PACKED
|
|
1154
|
+
return volUnpack(texelFetch(s, coordinates, 0)) * volCameraMinMaxZ.y;
|
|
1155
|
+
#else
|
|
1156
|
+
return texelFetch(s, coordinates, 0).r;
|
|
1157
|
+
#endif
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// Returns the texel of the linear depth under the center of the given texel of the scattering buffer, which
|
|
1161
|
+
// is the depth the raymarching used for it. At half resolution the center of a texel lies exactly on the corner
|
|
1162
|
+
// of four texels of the depth: "volDepthRatio", the ratio between the two resolutions, is computed on the CPU
|
|
1163
|
+
// so every pass rounds exactly the same way and picks the same one.
|
|
1164
|
+
ivec2 volScatterToDepthTexel(ivec2 scatterTexel, ivec2 depthSize) {
|
|
1165
|
+
return min(ivec2((vec2(scatterTexel) + 0.5) * volDepthRatio), depthSize - 1);
|
|
1166
|
+
}
|
|
1167
|
+
`;function kn(){return`precision highp float;
|
|
1168
|
+
|
|
1169
|
+
varying vec2 vUV;
|
|
1170
|
+
|
|
1171
|
+
uniform sampler2D textureSampler;
|
|
1172
|
+
uniform sampler2D depthSampler;
|
|
1173
|
+
|
|
1174
|
+
uniform vec2 volCameraMinMaxZ;
|
|
1175
|
+
uniform vec2 volDepthUnpack;
|
|
1176
|
+
|
|
1177
|
+
${Je}
|
|
1178
|
+
${Hn}
|
|
1179
|
+
|
|
1180
|
+
vec4 volPack(float depth) {
|
|
1181
|
+
const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);
|
|
1182
|
+
const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
|
|
1183
|
+
|
|
1184
|
+
vec4 result = fract(depth * bitShift);
|
|
1185
|
+
result -= result.xxyz * bitMask;
|
|
1186
|
+
|
|
1187
|
+
return result;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
void main(void) {
|
|
1191
|
+
float viewZ = volLinearDepth(volSampleDepth(depthSampler, vUV));
|
|
1192
|
+
|
|
1193
|
+
#ifdef VOL_LINEAR_DEPTH_PACKED
|
|
1194
|
+
gl_FragColor = volPack(clamp(viewZ / volCameraMinMaxZ.y, 0.0, 0.9999999));
|
|
1195
|
+
#else
|
|
1196
|
+
gl_FragColor = vec4(viewZ, 0.0, 0.0, 1.0);
|
|
1197
|
+
#endif
|
|
1198
|
+
}
|
|
1199
|
+
`}n(kn,"buildVolumetricLightingLinearDepthShader");function xo(t,e){return`
|
|
1200
|
+
float chordLength = t1 - t0;
|
|
1201
|
+
|
|
1202
|
+
// The point of the view ray closest to the light splits the chord in two halves over which both the
|
|
1203
|
+
// attenuation and the phase function are monotonic, which is where stratified samples do best.
|
|
1204
|
+
float closest = clamp(dot(data.xyz, volRayDir), t0, t1);
|
|
1205
|
+
if (closest - t0 < 0.02 * chordLength) {
|
|
1206
|
+
closest = t0;
|
|
1207
|
+
} else if (t1 - closest < 0.02 * chordLength) {
|
|
1208
|
+
closest = t1;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
int count = volLocalSampleCount(chordLength, falloff.x, tEnd - tStart);
|
|
1212
|
+
int firstCount = closest <= t0 ? 0 : (closest >= t1 ? count : clamp(int(float(count) * (closest - t0) / chordLength + 0.5), 1, count - 1));
|
|
1213
|
+
|
|
1214
|
+
float firstWidth = (closest - t0) / float(max(firstCount, 1));
|
|
1215
|
+
float secondWidth = (t1 - closest) / float(max(count - firstCount, 1));
|
|
1216
|
+
float stratum = volStratumOffset(${t});
|
|
1217
|
+
|
|
1218
|
+
vec3 result = vec3(0.0);
|
|
1219
|
+
|
|
1220
|
+
for (int k = 0; k < VOL_LOCAL_MAX_STEPS; ++k) {
|
|
1221
|
+
if (k >= count) {
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
bool inFirstHalf = k < firstCount;
|
|
1226
|
+
float width = inFirstHalf ? firstWidth : secondWidth;
|
|
1227
|
+
float t = inFirstHalf ? t0 + width * (float(k) + stratum) : closest + width * (float(k - firstCount) + stratum);
|
|
1228
|
+
|
|
1229
|
+
vec3 position = volRayDir * t;
|
|
1230
|
+
float sigmaT = volExtinctionAt(volCameraPosition.y + position.y, t);
|
|
1231
|
+
|
|
1232
|
+
float distanceToLight;
|
|
1233
|
+
vec3 contribution = volEvalLocalLight(data, diffuse, direction, falloff, position, distanceToLight);
|
|
1234
|
+
|
|
1235
|
+
if (contribution.r + contribution.g + contribution.b > 0.0) {
|
|
1236
|
+
${e}
|
|
1237
|
+
result += contribution * (volCombinedTransmittance(t, sigmaT, distanceToLight) * sigmaT * width);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
return vec4(result, 1.0);
|
|
1242
|
+
`}n(xo,"buildLocalLightIntegration");function Un(t){let e=[],i=[],o=[];for(let r=0;r<t;++r)e.push(`
|
|
1243
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
1244
|
+
#if VOL_SHADOW_KIND{X} == 2
|
|
1245
|
+
uniform samplerCube volShadowSampler{X};
|
|
1246
|
+
#elif VOL_SHADOW_KIND{X} == 1
|
|
1247
|
+
uniform highp sampler2DShadow volShadowSampler{X};
|
|
1248
|
+
#else
|
|
1249
|
+
uniform sampler2D volShadowSampler{X};
|
|
1250
|
+
#endif
|
|
1251
|
+
|
|
1252
|
+
// Returns the shadowing of a point given its position relative to the camera and, for the 2d shadow maps, its
|
|
1253
|
+
// position in the clip space of the light, which the callers compute the cheapest way they can.
|
|
1254
|
+
float volShadow{X}(vec3 position, vec4 clip) {
|
|
1255
|
+
vec4 info = volShadowInfo[{X}];
|
|
1256
|
+
float edge = volShadowLightFalloff[{X}].z;
|
|
1257
|
+
|
|
1258
|
+
#if VOL_SHADOW_KIND{X} == 2
|
|
1259
|
+
// Cube shadow map of a point light. It stores the radial distance to the light.
|
|
1260
|
+
vec3 toFragment = position - volShadowLightData[{X}].xyz;
|
|
1261
|
+
float depth = clamp((length(toFragment) + info.z) / info.w, 0.0, 1.0);
|
|
1262
|
+
|
|
1263
|
+
toFragment = normalize(toFragment);
|
|
1264
|
+
toFragment.y = -toFragment.y;
|
|
1265
|
+
|
|
1266
|
+
#ifdef VOL_SHADOW_PACKED{X}
|
|
1267
|
+
float shadowMapSample = volUnpack(textureCube(volShadowSampler{X}, toFragment));
|
|
1268
|
+
#else
|
|
1269
|
+
float shadowMapSample = textureCube(volShadowSampler{X}, toFragment).x;
|
|
1270
|
+
#endif
|
|
1271
|
+
|
|
1272
|
+
#if VOL_SHADOW_MODE{X} == 1
|
|
1273
|
+
// Exponential shadow map, same encoding as the 2d case. "info.y" holds the depth scale.
|
|
1274
|
+
return 1.0 - clamp(exp(min(87.0, info.y * depth)) * shadowMapSample, 0.0, 1.0 - info.x);
|
|
1275
|
+
#elif VOL_SHADOW_MODE{X} == 2
|
|
1276
|
+
return clamp(exp(min(87.0, -info.y * (depth - shadowMapSample))), info.x, 1.0);
|
|
1277
|
+
#else
|
|
1278
|
+
return depth > shadowMapSample ? info.x : 1.0;
|
|
1279
|
+
#endif
|
|
1280
|
+
#else
|
|
1281
|
+
vec3 clipSpace = clip.xyz / clip.w;
|
|
1282
|
+
|
|
1283
|
+
// "getTransformMatrix" gives the world to light clip space matrix without the [-1, 1] -> [0, 1] bias.
|
|
1284
|
+
#if VOL_SHADOW_KIND{X} == 1
|
|
1285
|
+
vec3 uvDepth = vec3(0.5 * clipSpace + vec3(0.5));
|
|
1286
|
+
#ifdef VOL_NDC_HALF_Z
|
|
1287
|
+
uvDepth.z = clipSpace.z;
|
|
1288
|
+
#endif
|
|
1289
|
+
|
|
1290
|
+
// Same guard as "computeShadowWithPCF1": past the far plane of the shadow map the hardware
|
|
1291
|
+
// comparison would fail against every texel a caster wrote, reporting the sample as occluded
|
|
1292
|
+
// while the surfaces at the same distance are lit by the material path.
|
|
1293
|
+
float pcfDepthMetric = volDepthMetric(clip, info.zw);
|
|
1294
|
+
if (pcfDepthMetric < 0.0 || pcfDepthMetric > 1.0 || uvDepth.x < 0.0 || uvDepth.x > 1.0 || uvDepth.y < 0.0 || uvDepth.y > 1.0) {
|
|
1295
|
+
return 1.0;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// Hardware comparison sampling. "info.y" holds the inverse of the size of the shadow map.
|
|
1299
|
+
#if VOL_PCF_TAPS == 4
|
|
1300
|
+
float shadow = 0.25 * (
|
|
1301
|
+
texture2DLodEXT(volShadowSampler{X}, uvDepth + vec3(-0.5 * info.y, -0.5 * info.y, 0.0), 0.) +
|
|
1302
|
+
texture2DLodEXT(volShadowSampler{X}, uvDepth + vec3( 0.5 * info.y, -0.5 * info.y, 0.0), 0.) +
|
|
1303
|
+
texture2DLodEXT(volShadowSampler{X}, uvDepth + vec3(-0.5 * info.y, 0.5 * info.y, 0.0), 0.) +
|
|
1304
|
+
texture2DLodEXT(volShadowSampler{X}, uvDepth + vec3( 0.5 * info.y, 0.5 * info.y, 0.0), 0.)
|
|
1305
|
+
);
|
|
1306
|
+
#else
|
|
1307
|
+
float shadow = texture2DLodEXT(volShadowSampler{X}, uvDepth, 0.);
|
|
1308
|
+
#endif
|
|
1309
|
+
|
|
1310
|
+
return volFallOff(mix(info.x, 1.0, shadow), clipSpace.xy, edge);
|
|
1311
|
+
#else
|
|
1312
|
+
vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
|
|
1313
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
1314
|
+
return 1.0;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
float depthMetric = clamp(volDepthMetric(clip, info.zw), 0.0, 1.0);
|
|
1318
|
+
|
|
1319
|
+
#ifdef VOL_SHADOW_PACKED{X}
|
|
1320
|
+
float shadowMapSample = volUnpack(texture2DLodEXT(volShadowSampler{X}, uv, 0.));
|
|
1321
|
+
#else
|
|
1322
|
+
float shadowMapSample = texture2DLodEXT(volShadowSampler{X}, uv, 0.).x;
|
|
1323
|
+
#endif
|
|
1324
|
+
|
|
1325
|
+
#if VOL_SHADOW_MODE{X} == 1
|
|
1326
|
+
// Exponential shadow map. "info.y" holds the depth scale of the generator.
|
|
1327
|
+
return volFallOff(1.0 - clamp(exp(min(87.0, info.y * depthMetric)) * shadowMapSample, 0.0, 1.0 - info.x), clipSpace.xy, edge);
|
|
1328
|
+
#elif VOL_SHADOW_MODE{X} == 2
|
|
1329
|
+
// Close exponential shadow map.
|
|
1330
|
+
return volFallOff(clamp(exp(min(87.0, -info.y * (depthMetric - shadowMapSample))), info.x, 1.0), clipSpace.xy, edge);
|
|
1331
|
+
#else
|
|
1332
|
+
return depthMetric > shadowMapSample ? volFallOff(info.x, clipSpace.xy, edge) : 1.0;
|
|
1333
|
+
#endif
|
|
1334
|
+
#endif
|
|
1335
|
+
#endif
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
#if VOL_SHADOW_LOCAL{X} == 1
|
|
1339
|
+
// Point or spot light casting volumetric shadows: integrated over its own volume, like the others.
|
|
1340
|
+
vec4 volIntegrateShadowSlot{X}(float tStart, float tEnd) {
|
|
1341
|
+
vec4 data = volShadowLightData[{X}];
|
|
1342
|
+
vec4 direction = volShadowLightDirection[{X}];
|
|
1343
|
+
vec4 falloff = volShadowLightFalloff[{X}];
|
|
1344
|
+
|
|
1345
|
+
vec2 chord = volLightChord(data, direction, falloff.x);
|
|
1346
|
+
float t0 = max(chord.x, tStart);
|
|
1347
|
+
float t1 = min(chord.y, tEnd);
|
|
1348
|
+
|
|
1349
|
+
if (t1 <= t0) {
|
|
1350
|
+
return vec4(0.0);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
vec4 diffuse = volShadowLightDiffuse[{X}];
|
|
1354
|
+
|
|
1355
|
+
// The light clip space position of the points of the view ray is affine in their distance to the camera,
|
|
1356
|
+
// so each sample only costs a multiply-add instead of a matrix product.
|
|
1357
|
+
vec4 clipOrigin = volShadowMatrix[{X}] * vec4(volCameraPosition, 1.0);
|
|
1358
|
+
vec4 clipDirection = volShadowMatrix[{X}] * vec4(volRayDir, 0.0);
|
|
1359
|
+
${xo("float({X}) + 0.5","contribution *= mix(1.0, volShadow{X}(position, clipOrigin + clipDirection * t), falloff.w);")}
|
|
1360
|
+
}
|
|
1361
|
+
#endif
|
|
1362
|
+
#endif
|
|
1363
|
+
`.replace(/\{X\}/g,r.toString())),i.push(`
|
|
1364
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
1365
|
+
#if VOL_SHADOW_LOCAL{X} == 0
|
|
1366
|
+
{
|
|
1367
|
+
// The matrix product is recomputed rather than kept affine: the march already holds many values
|
|
1368
|
+
// alive across its steps, and fewer live registers means more pixels processed in parallel.
|
|
1369
|
+
float shadow = volShadow{X}(position, volShadowMatrix[{X}] * vec4(volCameraPosition + position, 1.0));
|
|
1370
|
+
scattering += volEvalDirectionalLight(volShadowLightData[{X}], volShadowLightDiffuse[{X}]) * mix(1.0, shadow, volShadowLightFalloff[{X}].w);
|
|
1371
|
+
stepLights += 1.0;
|
|
1372
|
+
}
|
|
1373
|
+
#endif
|
|
1374
|
+
#endif
|
|
1375
|
+
`.replace(/\{X\}/g,r.toString())),o.push(`
|
|
1376
|
+
#if VOL_SHADOW_SLOT_COUNT > {X}
|
|
1377
|
+
#if VOL_SHADOW_LOCAL{X} == 1
|
|
1378
|
+
lightResult = volIntegrateShadowSlot{X}(tStart, tEnd);
|
|
1379
|
+
accumulated += lightResult.rgb;
|
|
1380
|
+
evaluatedLights += lightResult.a;
|
|
1381
|
+
#endif
|
|
1382
|
+
#endif
|
|
1383
|
+
`.replace(/\{X\}/g,r.toString()));return`precision highp float;
|
|
1384
|
+
precision highp int;
|
|
1385
|
+
|
|
1386
|
+
varying vec2 vUV;
|
|
1387
|
+
|
|
1388
|
+
// Full resolution linear depth of the scene, written by the linear depth pass.
|
|
1389
|
+
uniform highp sampler2D textureSampler;
|
|
1390
|
+
|
|
1391
|
+
// Ratio between the resolution of the linear depth and the resolution of the scattering buffer.
|
|
1392
|
+
uniform vec2 volDepthRatio;
|
|
1393
|
+
|
|
1394
|
+
uniform mat4 volInverseViewProjection;
|
|
1395
|
+
uniform vec3 volCameraPosition;
|
|
1396
|
+
uniform vec3 volCameraForward;
|
|
1397
|
+
uniform vec2 volCameraMinMaxZ;
|
|
1398
|
+
uniform float volFrameIndex;
|
|
1399
|
+
|
|
1400
|
+
uniform vec4 volFogInfos;
|
|
1401
|
+
uniform vec3 volFogColor;
|
|
1402
|
+
uniform float volLinearFogEps;
|
|
1403
|
+
uniform vec4 volMedium;
|
|
1404
|
+
|
|
1405
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
1406
|
+
uniform mat4 volViewProjection;
|
|
1407
|
+
uniform vec4 volScreenShadowParams;
|
|
1408
|
+
#endif
|
|
1409
|
+
uniform vec3 volAmbient;
|
|
1410
|
+
|
|
1411
|
+
// (maximum distance, dithering strength, light extinction clamp, number of point and spot lights in the arrays)
|
|
1412
|
+
uniform vec4 volParams;
|
|
1413
|
+
|
|
1414
|
+
#if VOL_MAX_ARRAY_LIGHTS > 0
|
|
1415
|
+
uniform vec4 volLightData[VOL_MAX_ARRAY_LIGHTS];
|
|
1416
|
+
uniform vec4 volLightDiffuse[VOL_MAX_ARRAY_LIGHTS];
|
|
1417
|
+
uniform vec4 volLightDirection[VOL_MAX_ARRAY_LIGHTS];
|
|
1418
|
+
uniform vec4 volLightFalloff[VOL_MAX_ARRAY_LIGHTS];
|
|
1419
|
+
#endif
|
|
1420
|
+
|
|
1421
|
+
#if VOL_SHADOW_SLOT_COUNT > 0
|
|
1422
|
+
uniform vec4 volShadowLightData[VOL_SHADOW_SLOT_COUNT];
|
|
1423
|
+
uniform vec4 volShadowLightDiffuse[VOL_SHADOW_SLOT_COUNT];
|
|
1424
|
+
uniform vec4 volShadowLightDirection[VOL_SHADOW_SLOT_COUNT];
|
|
1425
|
+
uniform vec4 volShadowLightFalloff[VOL_SHADOW_SLOT_COUNT];
|
|
1426
|
+
uniform vec4 volShadowInfo[VOL_SHADOW_SLOT_COUNT];
|
|
1427
|
+
uniform mat4 volShadowMatrix[VOL_SHADOW_SLOT_COUNT];
|
|
1428
|
+
#endif
|
|
1429
|
+
|
|
1430
|
+
#ifdef VOL_CSM
|
|
1431
|
+
uniform vec4 volCsmLightData;
|
|
1432
|
+
uniform vec4 volCsmLightDiffuse;
|
|
1433
|
+
uniform vec4 volCsmLightDirection;
|
|
1434
|
+
uniform vec4 volCsmLightFalloff;
|
|
1435
|
+
uniform vec4 volCsmInfo;
|
|
1436
|
+
uniform mat4 volCsmMatrices[VOL_CSM_CASCADES];
|
|
1437
|
+
|
|
1438
|
+
#if VOL_CSM_KIND == 1
|
|
1439
|
+
uniform highp sampler2DArrayShadow volCsmSampler;
|
|
1440
|
+
#else
|
|
1441
|
+
uniform highp sampler2DArray volCsmSampler;
|
|
1442
|
+
#endif
|
|
1443
|
+
#endif
|
|
1444
|
+
|
|
1445
|
+
// Values shared by every function of the pass, computed once per pixel. Every position the raymarching
|
|
1446
|
+
// manipulates is relative to the camera, which keeps the precision of the lights far from the origin.
|
|
1447
|
+
vec3 volRayDir;
|
|
1448
|
+
float volCosForward;
|
|
1449
|
+
float volNoise;
|
|
1450
|
+
float volJitter;
|
|
1451
|
+
|
|
1452
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
1453
|
+
ivec2 volDepthSize;
|
|
1454
|
+
vec4 volClipOrigin;
|
|
1455
|
+
vec4 volClipDirection;
|
|
1456
|
+
#endif
|
|
1457
|
+
|
|
1458
|
+
${Je}
|
|
1459
|
+
${ci}
|
|
1460
|
+
|
|
1461
|
+
float volFallOff(float value, vec2 clipSpaceXY, float frustumEdgeFalloff) {
|
|
1462
|
+
float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.00000012, clamp(dot(clipSpaceXY, clipSpaceXY), 0.0, 1.0));
|
|
1463
|
+
return mix(value, 1.0, mask);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
// Reproduces the depth metric computed by the "shadowsVertex" include of Babylon.js: the raw clip space
|
|
1467
|
+
// Z is used, without the perspective divide, so the comparison matches what the shadow map stores.
|
|
1468
|
+
float volDepthMetric(vec4 clip, vec2 depthValues) {
|
|
1469
|
+
#ifdef VOL_REVERSE_DEPTH
|
|
1470
|
+
return (-clip.z + depthValues.x) / depthValues.y;
|
|
1471
|
+
#else
|
|
1472
|
+
return (clip.z + depthValues.x) / depthValues.y;
|
|
1473
|
+
#endif
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
// Henyey-Greenstein phase function. "c" is the cosine of the angle between the direction the light
|
|
1477
|
+
// travels and the direction the ray travels, "g" the anisotropy of the medium.
|
|
1478
|
+
//
|
|
1479
|
+
// Normalised to 1 for an isotropic medium rather than to an integral of 1 over the sphere: the lighting of
|
|
1480
|
+
// the surfaces in Babylon.js doesn't divide by PI either, so an intensity of 1 means the same thing for the
|
|
1481
|
+
// light shafts as it does for the surfaces the same light hits.
|
|
1482
|
+
float volPhaseHG(float c, float g) {
|
|
1483
|
+
float g2 = g * g;
|
|
1484
|
+
float d = max(1.0 + g2 - 2.0 * g * c, 1e-4);
|
|
1485
|
+
return (1.0 - g2) / (d * sqrt(d));
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
float volBayer4(vec2 p) {
|
|
1489
|
+
vec2 p1 = mod(floor(p), 2.0);
|
|
1490
|
+
vec2 p2 = mod(floor(p * 0.5), 2.0);
|
|
1491
|
+
|
|
1492
|
+
float b1 = 2.0 * p1.x + 3.0 * p1.y - 4.0 * p1.x * p1.y;
|
|
1493
|
+
float b2 = 2.0 * p2.x + 3.0 * p2.y - 4.0 * p2.x * p2.y;
|
|
1494
|
+
|
|
1495
|
+
return (b1 * 4.0 + b2) / 16.0;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
float volInterleavedGradientNoise(vec2 p) {
|
|
1499
|
+
return fract(52.9829189 * fract(dot(p, vec2(0.06711056, 0.00583715))));
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
// Returns the offset of the samples of a light inside their strata. Each light gets its own offset, a golden
|
|
1503
|
+
// ratio sequence seeded by the noise of the pixel, so the lights don't all show the same pattern.
|
|
1504
|
+
float volStratumOffset(float seed) {
|
|
1505
|
+
#if VOL_DITHER == 0
|
|
1506
|
+
return 0.5;
|
|
1507
|
+
#else
|
|
1508
|
+
return mix(0.5, fract(volNoise + seed * 0.618034), volParams.y);
|
|
1509
|
+
#endif
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// Extinction coefficient of the medium, the exact analytic derivative of its optical depth:
|
|
1513
|
+
// sigma(t) = -d/dt ln(T(t)). Keeping the two in sync is what makes the result independent from the number
|
|
1514
|
+
// of samples the medium is integrated with. "volFogInfos" is (mode, start, end, density).
|
|
1515
|
+
float volFogExtinction(float t) {
|
|
1516
|
+
#if VOL_FOG_MODE == 2
|
|
1517
|
+
// T = (end - t) / (end - start) -> sigma = 1 / (end - t), clamped to avoid the pole at t = end.
|
|
1518
|
+
return t < volFogInfos.y ? 0.0 : 1.0 / max(volFogInfos.z - t, volLinearFogEps);
|
|
1519
|
+
#elif VOL_FOG_MODE == 1
|
|
1520
|
+
// T = e^(-(t * density)^2) -> sigma = 2 * density^2 * t.
|
|
1521
|
+
return 2.0 * volFogInfos.w * volFogInfos.w * t;
|
|
1522
|
+
#else
|
|
1523
|
+
// T = e^(-t * density) -> sigma = density (the medium is uniform).
|
|
1524
|
+
return volFogInfos.w;
|
|
1525
|
+
#endif
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
// "height" is the absolute altitude of the sample, "t" its distance to the camera.
|
|
1529
|
+
float volExtinctionAt(float height, float t) {
|
|
1530
|
+
float sigma = volFogExtinction(t);
|
|
1531
|
+
|
|
1532
|
+
#ifdef VOL_HEIGHT_FOG
|
|
1533
|
+
sigma *= exp(-max(0.0, height - volMedium.y) * volMedium.z);
|
|
1534
|
+
#endif
|
|
1535
|
+
|
|
1536
|
+
return sigma;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
// Transmittance of the medium between the camera and the point of the view ray at the distance "t". The
|
|
1540
|
+
// three models match the ones the fog of Babylon.js uses, but every value comes from the configuration of
|
|
1541
|
+
// this pipeline: the medium the shafts are computed in is independent from the fog applied on the surfaces.
|
|
1542
|
+
#if VOL_TRANSMITTANCE == 1
|
|
1543
|
+
// Length of medium at full density equivalent to the part [s1, s2] of the view ray, which lies entirely on
|
|
1544
|
+
// one side of the base altitude of the height falloff.
|
|
1545
|
+
float volHeightSegment(float s1, float s2) {
|
|
1546
|
+
float y0 = volCameraPosition.y - volMedium.y;
|
|
1547
|
+
float h1 = y0 + s1 * volRayDir.y;
|
|
1548
|
+
float h2 = y0 + s2 * volRayDir.y;
|
|
1549
|
+
|
|
1550
|
+
// Under the base altitude the medium has its full density.
|
|
1551
|
+
if (h1 + h2 <= 0.0) {
|
|
1552
|
+
return s2 - s1;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
// Over it, the integral of e^(-falloff * height) along the ray, falling back on the midpoint rule
|
|
1556
|
+
// when the altitude barely changes along the segment, where the closed form would cancel out.
|
|
1557
|
+
float e1 = exp(-volMedium.z * max(h1, 0.0));
|
|
1558
|
+
float e2 = exp(-volMedium.z * max(h2, 0.0));
|
|
1559
|
+
float slope = volMedium.z * volRayDir.y;
|
|
1560
|
+
|
|
1561
|
+
return abs(slope * (s2 - s1)) < 1e-4 ? 0.5 * (e1 + e2) * (s2 - s1) : (e1 - e2) / slope;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
// Exponential medium whose density decreases with the altitude: exact, split where the ray crosses the base altitude.
|
|
1565
|
+
float volOpticalDepth(float t) {
|
|
1566
|
+
float crossing = abs(volRayDir.y) > 1e-6 ? (volMedium.y - volCameraPosition.y) / volRayDir.y : -1.0;
|
|
1567
|
+
float opticalLength = (crossing > 0.0 && crossing < t) ? volHeightSegment(0.0, crossing) + volHeightSegment(crossing, t) : volHeightSegment(0.0, t);
|
|
1568
|
+
|
|
1569
|
+
return volFogInfos.w * opticalLength;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
float volTransmittance(float t) {
|
|
1573
|
+
return exp(-volOpticalDepth(t));
|
|
1574
|
+
}
|
|
1575
|
+
#elif VOL_TRANSMITTANCE == 2
|
|
1576
|
+
// The other fog modes combined with the height falloff have no closed form: their optical depth is
|
|
1577
|
+
// integrated once per pixel along the view ray, and interpolated from there.
|
|
1578
|
+
float volOpticalDepths[VOL_TRANSMITTANCE_SAMPLES + 1];
|
|
1579
|
+
float volOpticalDepthStart;
|
|
1580
|
+
float volOpticalDepthScale;
|
|
1581
|
+
|
|
1582
|
+
void volBuildOpticalDepths(float tStart, float tEnd) {
|
|
1583
|
+
float stepSize = (tEnd - tStart) / float(VOL_TRANSMITTANCE_SAMPLES);
|
|
1584
|
+
|
|
1585
|
+
volOpticalDepthStart = tStart;
|
|
1586
|
+
volOpticalDepthScale = 1.0 / stepSize;
|
|
1587
|
+
|
|
1588
|
+
// The medium between the camera and the near plane is too thin to be worth integrating.
|
|
1589
|
+
float previous = volExtinctionAt(volCameraPosition.y + volRayDir.y * tStart, tStart);
|
|
1590
|
+
float opticalDepth = previous * tStart;
|
|
1591
|
+
|
|
1592
|
+
volOpticalDepths[0] = opticalDepth;
|
|
1593
|
+
|
|
1594
|
+
for (int i = 1; i <= VOL_TRANSMITTANCE_SAMPLES; ++i) {
|
|
1595
|
+
float t = tStart + stepSize * float(i);
|
|
1596
|
+
float sigma = volExtinctionAt(volCameraPosition.y + volRayDir.y * t, t);
|
|
1597
|
+
|
|
1598
|
+
opticalDepth += 0.5 * (previous + sigma) * stepSize;
|
|
1599
|
+
volOpticalDepths[i] = opticalDepth;
|
|
1600
|
+
previous = sigma;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
float volOpticalDepth(float t) {
|
|
1605
|
+
float x = clamp((t - volOpticalDepthStart) * volOpticalDepthScale, 0.0, float(VOL_TRANSMITTANCE_SAMPLES));
|
|
1606
|
+
int i = min(int(x), VOL_TRANSMITTANCE_SAMPLES - 1);
|
|
1607
|
+
|
|
1608
|
+
return mix(volOpticalDepths[i], volOpticalDepths[i + 1], x - float(i));
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
float volTransmittance(float t) {
|
|
1612
|
+
return exp(-volOpticalDepth(t));
|
|
1613
|
+
}
|
|
1614
|
+
#elif VOL_FOG_MODE == 2
|
|
1615
|
+
// The linear mode is the only one whose transmittance, rather than its optical depth, is simple.
|
|
1616
|
+
float volTransmittance(float t) {
|
|
1617
|
+
return clamp((volFogInfos.z - t) / max(volFogInfos.z - volFogInfos.y, volLinearFogEps), 0.0, 1.0);
|
|
1618
|
+
}
|
|
1619
|
+
#else
|
|
1620
|
+
float volOpticalDepth(float t) {
|
|
1621
|
+
#if VOL_FOG_MODE == 1
|
|
1622
|
+
float x = t * volFogInfos.w;
|
|
1623
|
+
return x * x;
|
|
1624
|
+
#else
|
|
1625
|
+
return t * volFogInfos.w;
|
|
1626
|
+
#endif
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
float volTransmittance(float t) {
|
|
1630
|
+
return exp(-volOpticalDepth(t));
|
|
1631
|
+
}
|
|
1632
|
+
#endif
|
|
1633
|
+
|
|
1634
|
+
// Transmittance of the medium between the camera and the point of the view ray at the distance "t", combined
|
|
1635
|
+
// with the attenuation of the light on its way from the light to that point. Both are exponentials of optical
|
|
1636
|
+
// depths whenever the fog mode allows it, which saves one exponential per sample.
|
|
1637
|
+
float volCombinedTransmittance(float t, float sigmaT, float distanceToLight) {
|
|
1638
|
+
#ifdef VOL_LIGHT_EXTINCTION
|
|
1639
|
+
// Exact for an exponential fog, which describes a homogeneous medium, and a faithful approximation for
|
|
1640
|
+
// the other modes.
|
|
1641
|
+
float lightOpticalDepth = sigmaT * min(distanceToLight, volParams.z);
|
|
1642
|
+
|
|
1643
|
+
#ifdef VOL_OPTICAL_DEPTH
|
|
1644
|
+
return exp(-(volOpticalDepth(t) + lightOpticalDepth));
|
|
1645
|
+
#else
|
|
1646
|
+
return volTransmittance(t) * exp(-lightOpticalDepth);
|
|
1647
|
+
#endif
|
|
1648
|
+
#else
|
|
1649
|
+
return volTransmittance(t);
|
|
1650
|
+
#endif
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
1654
|
+
// Walks a segment going from a point of the medium towards a light through the depth buffer, and reports the
|
|
1655
|
+
// point as occluded as soon as one of the samples sits behind what the depth buffer holds. This is what stops
|
|
1656
|
+
// the shafts of a light that has no shadow map from showing through the walls between it and the camera.
|
|
1657
|
+
//
|
|
1658
|
+
// The segment is given in clip space: the sample at the fraction "u" of the segment is "clipStart + u * clipDelta".
|
|
1659
|
+
// The clip space position is affine in the world position, and so is the distance along the view axis, so
|
|
1660
|
+
// interpolating both is exact and replaces the matrix product each sample would cost with multiply-adds.
|
|
1661
|
+
// "volScreenShadowParams" is (maximum traced distance, relative depth bias, relative surface thickness, unused).
|
|
1662
|
+
float volScreenShadow(vec4 clipStart, vec4 clipDelta, float depthStart, float depthDelta) {
|
|
1663
|
+
for (int i = 1; i <= VOL_SCREEN_SHADOW_STEPS; ++i) {
|
|
1664
|
+
// The samples are spread strictly between the shaded point and the end of the segment: the point
|
|
1665
|
+
// itself is on the view ray, so it always sits in front of the depth buffer.
|
|
1666
|
+
float u = (float(i) + volJitter) * (1.0 / float(VOL_SCREEN_SHADOW_STEPS + 1));
|
|
1667
|
+
|
|
1668
|
+
vec4 clip = clipStart + clipDelta * u;
|
|
1669
|
+
if (clip.w <= 0.0) {
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
vec2 uv = (clip.xy / clip.w) * 0.5 + 0.5;
|
|
1674
|
+
if (uv.x < 0.0 || uv.x >= 1.0 || uv.y < 0.0 || uv.y >= 1.0) {
|
|
1675
|
+
continue;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
float sceneDepth = volReadLinearDepth(textureSampler, ivec2(uv * vec2(volDepthSize)));
|
|
1679
|
+
|
|
1680
|
+
// Bounded by the assumed thickness of the surface: a sample much further away than the surface it is
|
|
1681
|
+
// hidden behind has passed it rather than been stopped by it, and counting it as occluded would
|
|
1682
|
+
// stamp the silhouette of everything in the foreground into the shafts behind it.
|
|
1683
|
+
float depthDifference = depthStart + depthDelta * u - sceneDepth;
|
|
1684
|
+
float bias = max(volScreenShadowParams.y * sceneDepth, volCameraMinMaxZ.x);
|
|
1685
|
+
|
|
1686
|
+
if (depthDifference > bias && depthDifference < volScreenShadowParams.z * sceneDepth) {
|
|
1687
|
+
return 0.0;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
return 1.0;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// Occlusion of a point or a spot light, seen from the point of the view ray at the distance "t". The
|
|
1695
|
+
// search stops at the light, or after the maximum traced distance when the light is further than that.
|
|
1696
|
+
float volScreenShadowToLight(float t, vec4 lightClip, float lightDepth, float distanceToLight) {
|
|
1697
|
+
vec4 clipStart = volClipOrigin + volClipDirection * t;
|
|
1698
|
+
float depthStart = t * volCosForward;
|
|
1699
|
+
float fraction = min(1.0, volScreenShadowParams.x / max(distanceToLight, 1e-4));
|
|
1700
|
+
|
|
1701
|
+
return volScreenShadow(clipStart, (lightClip - clipStart) * fraction, depthStart, (lightDepth - depthStart) * fraction);
|
|
1702
|
+
}
|
|
1703
|
+
#endif
|
|
1704
|
+
|
|
1705
|
+
// Evaluates the in-scattered radiance coming from a directional light, without any shadowing. "data.xyz"
|
|
1706
|
+
// already holds the direction pointing to the light, and the scattering angle is the angle between the
|
|
1707
|
+
// direction the light travels (-data.xyz) and the direction the ray travels (-volRayDir).
|
|
1708
|
+
vec3 volEvalDirectionalLight(vec4 data, vec4 diffuse) {
|
|
1709
|
+
return diffuse.rgb * volPhaseHG(dot(volRayDir, data.xyz), diffuse.a);
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
// Evaluates the in-scattered radiance coming from a point or a spot light at the given position, relative to
|
|
1713
|
+
// the camera, without any shadowing nor extinction.
|
|
1714
|
+
vec3 volEvalLocalLight(vec4 data, vec4 diffuse, vec4 direction, vec4 falloff, vec3 position, out float distanceToLight) {
|
|
1715
|
+
vec3 toLight = data.xyz - position;
|
|
1716
|
+
distanceToLight = max(length(toLight), 1e-4);
|
|
1717
|
+
|
|
1718
|
+
vec3 lightVector = toLight / distanceToLight;
|
|
1719
|
+
|
|
1720
|
+
// Same linear attenuation as "computeLighting" in the "lightsFragmentFunctions" include.
|
|
1721
|
+
float attenuation = max(0.0, 1.0 - distanceToLight / falloff.x);
|
|
1722
|
+
|
|
1723
|
+
if (data.w == 2.0) {
|
|
1724
|
+
float cosAngle = max(0.0, dot(direction.xyz, -lightVector));
|
|
1725
|
+
attenuation *= (cosAngle >= direction.w) ? max(0.0, pow(cosAngle, falloff.y)) : 0.0;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
if (attenuation <= 0.0) {
|
|
1729
|
+
return vec3(0.0);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
return diffuse.rgb * (attenuation * volPhaseHG(dot(volRayDir, lightVector), diffuse.a));
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// Returns the part of the view ray crossing the cone of a spot light, cut by the sphere of its range.
|
|
1736
|
+
// "apex" is relative to the camera and "sphere" is the part of the ray crossing the sphere of the range.
|
|
1737
|
+
vec2 volConeChord(vec3 apex, vec3 axis, float cosAngle, float range, vec2 sphere) {
|
|
1738
|
+
// Only a convex cone can be intersected exactly, anything wider keeps the sphere of the range.
|
|
1739
|
+
if (cosAngle <= 1e-3) {
|
|
1740
|
+
return sphere;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// Expressed in units of the range of the light, which keeps the quadratic well conditioned. A point of the
|
|
1744
|
+
// view ray is inside the cone when "dot(p - apex, axis) >= |p - apex| * cos(angle)".
|
|
1745
|
+
vec3 origin = apex * (-1.0 / range);
|
|
1746
|
+
float dv = dot(volRayDir, axis);
|
|
1747
|
+
float ov = dot(origin, axis);
|
|
1748
|
+
float cos2 = cosAngle * cosAngle;
|
|
1749
|
+
|
|
1750
|
+
float a = dv * dv - cos2;
|
|
1751
|
+
float b = dv * ov - cos2 * dot(volRayDir, origin);
|
|
1752
|
+
float c = ov * ov - cos2 * dot(origin, origin);
|
|
1753
|
+
|
|
1754
|
+
// The ray is parallel to the surface of the cone, the sphere is a conservative bound.
|
|
1755
|
+
if (abs(a) < 1e-4) {
|
|
1756
|
+
return sphere;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
float discriminant = b * b - a * c;
|
|
1760
|
+
vec2 cone;
|
|
1761
|
+
|
|
1762
|
+
if (a < 0.0) {
|
|
1763
|
+
// Less aligned with the axis than the surface of the cone: the ray crosses it along a single segment.
|
|
1764
|
+
if (discriminant <= 0.0) {
|
|
1765
|
+
return vec2(1.0, -1.0);
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
float s = sqrt(discriminant);
|
|
1769
|
+
cone = vec2((-b + s) / a, (-b - s) / a);
|
|
1770
|
+
|
|
1771
|
+
// The segment must belong to the cone of the light, not to its mirror image behind the apex.
|
|
1772
|
+
if (dv * 0.5 * (cone.x + cone.y) + ov < 0.0) {
|
|
1773
|
+
return vec2(1.0, -1.0);
|
|
1774
|
+
}
|
|
1775
|
+
} else {
|
|
1776
|
+
// More aligned with the axis than the surface: the line crosses both the cone and its mirror image, and
|
|
1777
|
+
// only the half line going in the direction of the axis belongs to the cone of the light.
|
|
1778
|
+
float s = sqrt(max(discriminant, 0.0));
|
|
1779
|
+
cone = dv > 0.0 ? vec2((-b + s) / a, 1e30) : vec2(-1e30, (-b - s) / a);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
// Slightly widened: the samples outside of the cone are rejected by the lighting itself, while an interval
|
|
1783
|
+
// cut too short by the rounding errors would clip the edges of the cone.
|
|
1784
|
+
return vec2(max(sphere.x, (cone.x - 0.005) * range), min(sphere.y, (cone.y + 0.005) * range));
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// Returns the part of the view ray, as distances to the camera, crossing the volume a point or a spot light
|
|
1788
|
+
// reaches. An empty part is returned as an interval that ends before it starts.
|
|
1789
|
+
vec2 volLightChord(vec4 data, vec4 direction, float range) {
|
|
1790
|
+
// Computed from the point of the ray closest to the light rather than with the textbook discriminant,
|
|
1791
|
+
// which cancels out catastrophically for the small lights far from the camera.
|
|
1792
|
+
float closest = dot(data.xyz, volRayDir);
|
|
1793
|
+
vec3 offset = data.xyz - volRayDir * closest;
|
|
1794
|
+
float halfChord2 = range * range - dot(offset, offset);
|
|
1795
|
+
|
|
1796
|
+
if (halfChord2 <= 0.0) {
|
|
1797
|
+
return vec2(1.0, -1.0);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
float halfChord = sqrt(halfChord2);
|
|
1801
|
+
vec2 chord = vec2(closest - halfChord, closest + halfChord);
|
|
1802
|
+
|
|
1803
|
+
if (data.w == 2.0) {
|
|
1804
|
+
chord = volConeChord(data.xyz, direction.xyz, direction.w, range, chord);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
return chord;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
// Returns the number of samples taken over the given chord of a light: at least "VOL_LIGHT_STEPS" across the
|
|
1811
|
+
// diameter of the light, and at least the density the directional lights are marched with, so a light covering
|
|
1812
|
+
// most of the view ray is never sampled more coarsely than by a march of the whole ray.
|
|
1813
|
+
int volLocalSampleCount(float chordLength, float range, float rayLength) {
|
|
1814
|
+
float count = max(float(VOL_LIGHT_STEPS) * chordLength / (2.0 * range), float(VOL_STEPS) * chordLength / rayLength);
|
|
1815
|
+
return clamp(int(ceil(count)), 2, VOL_LOCAL_MAX_STEPS);
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
${e.join(`
|
|
1819
|
+
`)}
|
|
1820
|
+
|
|
1821
|
+
#ifdef VOL_CSM
|
|
1822
|
+
// A cascade is an orthographic box in the clip space of the light, where the view ray is a straight line
|
|
1823
|
+
// "origin + t * direction". The parts of the view ray inside each box are computed once per pixel, so finding
|
|
1824
|
+
// the cascade of a sample only costs a few comparisons, and the clip space position of the view ray is only
|
|
1825
|
+
// recomputed when the march enters another cascade, which happens a handful of times per ray.
|
|
1826
|
+
vec4 volCsmEntries;
|
|
1827
|
+
vec4 volCsmExits;
|
|
1828
|
+
int volCsmCurrent;
|
|
1829
|
+
vec4 volCsmClipOrigin;
|
|
1830
|
+
vec4 volCsmClipDirection;
|
|
1831
|
+
|
|
1832
|
+
// Returns the part of the view ray inside the box of a cascade, keeping the same 2% margin on its sides as
|
|
1833
|
+
// the lookup: a point outside every cascade must stay lit, exactly like the material path does past the
|
|
1834
|
+
// last cascade, and falling back on another cascade would sample its clamped border texel.
|
|
1835
|
+
vec2 volCsmBoxInterval(vec4 origin, vec4 direction) {
|
|
1836
|
+
#ifdef VOL_NDC_HALF_Z
|
|
1837
|
+
vec3 boxMin = vec3(-0.96, -0.96, 0.0);
|
|
1838
|
+
#else
|
|
1839
|
+
vec3 boxMin = vec3(-0.96, -0.96, -1.0);
|
|
1840
|
+
#endif
|
|
1841
|
+
vec3 boxMax = vec3(0.96, 0.96, 1.0);
|
|
1842
|
+
|
|
1843
|
+
// A direction parallel to an axis gives huge bounds of the same sign when the ray is outside of the slab,
|
|
1844
|
+
// and huge bounds of opposite signs when it is inside, which is exactly what the slab test expects.
|
|
1845
|
+
vec3 safeDirection = mix(vec3(1e-9), direction.xyz, greaterThan(abs(direction.xyz), vec3(1e-9)));
|
|
1846
|
+
vec3 inverseDirection = 1.0 / safeDirection;
|
|
1847
|
+
vec3 t0 = (boxMin - origin.xyz) * inverseDirection;
|
|
1848
|
+
vec3 t1 = (boxMax - origin.xyz) * inverseDirection;
|
|
1849
|
+
vec3 tMin = min(t0, t1);
|
|
1850
|
+
vec3 tMax = max(t0, t1);
|
|
1851
|
+
|
|
1852
|
+
return vec2(max(max(tMin.x, tMin.y), tMin.z), min(min(tMax.x, tMax.y), tMax.z));
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
void volPrepareCsm() {
|
|
1856
|
+
volCsmEntries = vec4(1e30);
|
|
1857
|
+
volCsmExits = vec4(-1e30);
|
|
1858
|
+
|
|
1859
|
+
for (int cascade = 0; cascade < VOL_CSM_CASCADES; ++cascade) {
|
|
1860
|
+
vec2 interval = volCsmBoxInterval(volCsmMatrices[cascade] * vec4(volCameraPosition, 1.0), volCsmMatrices[cascade] * vec4(volRayDir, 0.0));
|
|
1861
|
+
volCsmEntries[cascade] = interval.x;
|
|
1862
|
+
volCsmExits[cascade] = interval.y;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
volCsmCurrent = -1;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// Returns the shadowing of the point of the view ray at the distance "t" from the camera.
|
|
1869
|
+
float volCsmShadow(float t) {
|
|
1870
|
+
// The first cascade containing the sample is the most detailed one.
|
|
1871
|
+
int cascade = -1;
|
|
1872
|
+
for (int i = VOL_CSM_CASCADES - 1; i >= 0; --i) {
|
|
1873
|
+
if (t >= volCsmEntries[i] && t <= volCsmExits[i]) {
|
|
1874
|
+
cascade = i;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
if (cascade < 0) {
|
|
1879
|
+
return 1.0;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
if (cascade != volCsmCurrent) {
|
|
1883
|
+
volCsmCurrent = cascade;
|
|
1884
|
+
volCsmClipOrigin = volCsmMatrices[cascade] * vec4(volCameraPosition, 1.0);
|
|
1885
|
+
volCsmClipDirection = volCsmMatrices[cascade] * vec4(volRayDir, 0.0);
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
// The projection of a directional light is orthographic, "w" is always 1.
|
|
1889
|
+
vec4 clip = volCsmClipOrigin + volCsmClipDirection * t;
|
|
1890
|
+
vec3 clipSpace = clip.xyz;
|
|
1891
|
+
|
|
1892
|
+
#if VOL_CSM_KIND == 1
|
|
1893
|
+
vec3 uvDepth = vec3(0.5 * clipSpace + vec3(0.5));
|
|
1894
|
+
#ifdef VOL_NDC_HALF_Z
|
|
1895
|
+
uvDepth.z = clipSpace.z;
|
|
1896
|
+
#endif
|
|
1897
|
+
|
|
1898
|
+
float shadow = texture2D(volCsmSampler, vec4(uvDepth.x, uvDepth.y, float(cascade), uvDepth.z));
|
|
1899
|
+
return volFallOff(mix(volCsmInfo.x, 1.0, shadow), clipSpace.xy, volCsmLightFalloff.z);
|
|
1900
|
+
#else
|
|
1901
|
+
vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
|
|
1902
|
+
float depthMetric = clamp(volDepthMetric(clip, volCsmInfo.zw), 0.0, 1.0);
|
|
1903
|
+
|
|
1904
|
+
#ifdef VOL_CSM_PACKED
|
|
1905
|
+
float shadowMapSample = volUnpack(texture2D(volCsmSampler, vec3(uv, float(cascade))));
|
|
1906
|
+
#else
|
|
1907
|
+
float shadowMapSample = texture2D(volCsmSampler, vec3(uv, float(cascade))).x;
|
|
1908
|
+
#endif
|
|
1909
|
+
|
|
1910
|
+
return depthMetric > shadowMapSample ? volFallOff(volCsmInfo.x, clipSpace.xy, volCsmLightFalloff.z) : 1.0;
|
|
1911
|
+
#endif
|
|
1912
|
+
}
|
|
1913
|
+
#endif
|
|
1914
|
+
|
|
1915
|
+
#if VOL_GLOBAL_LIGHT_COUNT > 0
|
|
1916
|
+
// Marches the whole view ray for the lights that reach all of it: the directional lights. Returns the
|
|
1917
|
+
// in-scattered radiance in "rgb" and the number of lights evaluated in "a".
|
|
1918
|
+
vec4 volMarchGlobalLights(float tStart, float tEnd) {
|
|
1919
|
+
#if VOL_DIRECTIONAL_LIGHT_COUNT > 0
|
|
1920
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
1921
|
+
// The occlusion search of a directional light always walks the same direction over the same distance,
|
|
1922
|
+
// only its starting point moves along the view ray.
|
|
1923
|
+
vec4 directionClip[VOL_DIRECTIONAL_LIGHT_COUNT];
|
|
1924
|
+
float directionDepth[VOL_DIRECTIONAL_LIGHT_COUNT];
|
|
1925
|
+
|
|
1926
|
+
for (int li = 0; li < VOL_DIRECTIONAL_LIGHT_COUNT; ++li) {
|
|
1927
|
+
vec3 traced = volLightData[li].xyz * volScreenShadowParams.x;
|
|
1928
|
+
directionClip[li] = volViewProjection * vec4(traced, 0.0);
|
|
1929
|
+
directionDepth[li] = dot(traced, volCameraForward);
|
|
1930
|
+
}
|
|
1931
|
+
#endif
|
|
1932
|
+
#endif
|
|
1933
|
+
|
|
1934
|
+
#if VOL_DISTRIBUTION == 1
|
|
1935
|
+
float ratio = pow(tEnd / tStart, 1.0 / float(VOL_STEPS));
|
|
1936
|
+
#else
|
|
1937
|
+
float uniformStep = (tEnd - tStart) / float(VOL_STEPS);
|
|
1938
|
+
#endif
|
|
1939
|
+
|
|
1940
|
+
vec3 result = vec3(0.0);
|
|
1941
|
+
float evaluatedLights = 0.0;
|
|
1942
|
+
float segmentStart = tStart;
|
|
1943
|
+
|
|
1944
|
+
for (int i = 0; i < VOL_STEPS; ++i) {
|
|
1945
|
+
#if VOL_DISTRIBUTION == 1
|
|
1946
|
+
float segmentEnd = segmentStart * ratio;
|
|
1947
|
+
#else
|
|
1948
|
+
float segmentEnd = segmentStart + uniformStep;
|
|
1949
|
+
#endif
|
|
1950
|
+
|
|
1951
|
+
float segmentBegin = segmentStart;
|
|
1952
|
+
float dt = segmentEnd - segmentBegin;
|
|
1953
|
+
|
|
1954
|
+
// The jitter picks the sample inside its own segment, so the marched interval stays exactly
|
|
1955
|
+
// [tStart, tEnd]. Shifting the whole sequence instead would scale the length of the integrated
|
|
1956
|
+
// path by the jitter and turn the dithering into multiplicative noise.
|
|
1957
|
+
float t = segmentBegin + dt * volJitter;
|
|
1958
|
+
segmentStart = segmentEnd;
|
|
1959
|
+
|
|
1960
|
+
vec3 position = volRayDir * t;
|
|
1961
|
+
float sigmaT = volExtinctionAt(volCameraPosition.y + position.y, t);
|
|
1962
|
+
|
|
1963
|
+
if (sigmaT <= 1e-6) {
|
|
1964
|
+
continue;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// The transmittance at the START of the segment: the factor below accounts for the extinction
|
|
1968
|
+
// across the segment itself.
|
|
1969
|
+
float viewTransmittance = volTransmittance(segmentBegin);
|
|
1970
|
+
if (viewTransmittance < 0.003) {
|
|
1971
|
+
break;
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
vec3 scattering = vec3(0.0);
|
|
1975
|
+
float stepLights = 0.0;
|
|
1976
|
+
|
|
1977
|
+
${i.join("")}
|
|
1978
|
+
#ifdef VOL_CSM
|
|
1979
|
+
{
|
|
1980
|
+
scattering += volEvalDirectionalLight(volCsmLightData, volCsmLightDiffuse) * mix(1.0, volCsmShadow(t), volCsmLightFalloff.w);
|
|
1981
|
+
stepLights += 1.0;
|
|
1982
|
+
}
|
|
1983
|
+
#endif
|
|
1984
|
+
|
|
1985
|
+
#if VOL_DIRECTIONAL_LIGHT_COUNT > 0
|
|
1986
|
+
for (int li = 0; li < VOL_DIRECTIONAL_LIGHT_COUNT; ++li) {
|
|
1987
|
+
vec3 contribution = volEvalDirectionalLight(volLightData[li], volLightDiffuse[li]);
|
|
1988
|
+
|
|
1989
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
1990
|
+
// "volLightFalloff[li].z" carries whether this light asked to be occluded by the geometry.
|
|
1991
|
+
if (volLightFalloff[li].z > 0.5) {
|
|
1992
|
+
contribution *= volScreenShadow(volClipOrigin + volClipDirection * t, directionClip[li], t * volCosForward, directionDepth[li]);
|
|
1993
|
+
}
|
|
1994
|
+
#endif
|
|
1995
|
+
|
|
1996
|
+
scattering += contribution;
|
|
1997
|
+
stepLights += 1.0;
|
|
1998
|
+
}
|
|
1999
|
+
#endif
|
|
2000
|
+
|
|
2001
|
+
evaluatedLights = max(evaluatedLights, stepLights);
|
|
2002
|
+
|
|
2003
|
+
// Analytic integral of the in-scattering over the segment, "sigma" times "(1 - e^(-sigma * dt)) / sigma".
|
|
2004
|
+
// This is what makes the result independent from the number of steps instead of merely converging to it.
|
|
2005
|
+
result += scattering * (viewTransmittance * (1.0 - exp(-sigmaT * dt)));
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
return vec4(result, evaluatedLights);
|
|
2009
|
+
}
|
|
2010
|
+
#endif
|
|
2011
|
+
|
|
2012
|
+
#if VOL_LOCAL_ARRAY_LIGHTS == 1
|
|
2013
|
+
// Integrates a point or a spot light of the arrays over the part of the view ray crossing its volume.
|
|
2014
|
+
// Returns the in-scattered radiance in "rgb" and whether the light was evaluated in "a".
|
|
2015
|
+
vec4 volIntegrateArrayLight(int index, float tStart, float tEnd) {
|
|
2016
|
+
vec4 data = volLightData[index];
|
|
2017
|
+
vec4 direction = volLightDirection[index];
|
|
2018
|
+
vec4 falloff = volLightFalloff[index];
|
|
2019
|
+
|
|
2020
|
+
vec2 chord = volLightChord(data, direction, falloff.x);
|
|
2021
|
+
float t0 = max(chord.x, tStart);
|
|
2022
|
+
float t1 = min(chord.y, tEnd);
|
|
2023
|
+
|
|
2024
|
+
if (t1 <= t0) {
|
|
2025
|
+
return vec4(0.0);
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
vec4 diffuse = volLightDiffuse[index];
|
|
2029
|
+
|
|
2030
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
2031
|
+
// "falloff.z" carries whether this light asked to be occluded by the geometry.
|
|
2032
|
+
bool occluded = falloff.z > 0.5;
|
|
2033
|
+
vec4 lightClip = volClipOrigin + volViewProjection * vec4(data.xyz, 0.0);
|
|
2034
|
+
float lightDepth = dot(data.xyz, volCameraForward);
|
|
2035
|
+
#endif
|
|
2036
|
+
|
|
2037
|
+
${xo("float(index)",`#ifdef VOL_SCREEN_SHADOWS
|
|
2038
|
+
if (occluded) {
|
|
2039
|
+
contribution *= volScreenShadowToLight(t, lightClip, lightDepth, distanceToLight);
|
|
2040
|
+
}
|
|
2041
|
+
#endif`)}
|
|
2042
|
+
}
|
|
2043
|
+
#endif
|
|
2044
|
+
|
|
2045
|
+
void main(void) {
|
|
2046
|
+
// Reconstruct the world space direction of the view ray from the UV of the pixel.
|
|
2047
|
+
vec4 farPoint = volInverseViewProjection * vec4(vUV * 2.0 - 1.0, 1.0, 1.0);
|
|
2048
|
+
volRayDir = normalize(farPoint.xyz / farPoint.w - volCameraPosition);
|
|
2049
|
+
|
|
2050
|
+
// The depth map stores the distance along the view axis, the ray is not aligned with it.
|
|
2051
|
+
volCosForward = max(dot(volRayDir, volCameraForward), 1e-4);
|
|
2052
|
+
|
|
2053
|
+
ivec2 depthSize = textureSize(textureSampler, 0);
|
|
2054
|
+
float viewZ = volReadLinearDepth(textureSampler, volScatterToDepthTexel(ivec2(gl_FragCoord.xy), depthSize));
|
|
2055
|
+
|
|
2056
|
+
float tEnd = min(viewZ / volCosForward, volParams.x);
|
|
2057
|
+
float tStart = max(volCameraMinMaxZ.x / volCosForward, 1e-3);
|
|
2058
|
+
|
|
2059
|
+
if (tEnd <= tStart) {
|
|
2060
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
// Offsets the samples inside their segments to trade the banding produced by a low sample count for noise.
|
|
2065
|
+
volNoise = 0.0;
|
|
2066
|
+
#if VOL_DITHER == 1
|
|
2067
|
+
volNoise = volBayer4(gl_FragCoord.xy);
|
|
2068
|
+
#elif VOL_DITHER == 2
|
|
2069
|
+
vec2 ditherPosition = gl_FragCoord.xy;
|
|
2070
|
+
#ifdef VOL_TEMPORAL_JITTER
|
|
2071
|
+
ditherPosition += volFrameIndex * 5.588238;
|
|
2072
|
+
#endif
|
|
2073
|
+
volNoise = volInterleavedGradientNoise(ditherPosition);
|
|
2074
|
+
#endif
|
|
2075
|
+
volJitter = volNoise * volParams.y;
|
|
2076
|
+
|
|
2077
|
+
#ifdef VOL_SCREEN_SHADOWS
|
|
2078
|
+
volDepthSize = depthSize;
|
|
2079
|
+
volClipOrigin = volViewProjection * vec4(volCameraPosition, 1.0);
|
|
2080
|
+
volClipDirection = volViewProjection * vec4(volRayDir, 0.0);
|
|
2081
|
+
#endif
|
|
2082
|
+
|
|
2083
|
+
#if VOL_TRANSMITTANCE == 2
|
|
2084
|
+
volBuildOpticalDepths(tStart, tEnd);
|
|
2085
|
+
#endif
|
|
2086
|
+
|
|
2087
|
+
#ifdef VOL_CSM
|
|
2088
|
+
volPrepareCsm();
|
|
2089
|
+
#endif
|
|
2090
|
+
|
|
2091
|
+
float evaluatedLights = 0.0;
|
|
2092
|
+
|
|
2093
|
+
// The in-scattering of the constant ambient light has a closed form whatever the medium: the extinction is
|
|
2094
|
+
// the derivative of the optical depth, so the integral of "sigma * T" along the ray is "T(start) - T(end)".
|
|
2095
|
+
vec3 accumulated = volAmbient * (volTransmittance(tStart) - volTransmittance(tEnd));
|
|
2096
|
+
vec4 lightResult = vec4(0.0);
|
|
2097
|
+
|
|
2098
|
+
#if VOL_GLOBAL_LIGHT_COUNT > 0
|
|
2099
|
+
lightResult = volMarchGlobalLights(tStart, tEnd);
|
|
2100
|
+
accumulated += lightResult.rgb;
|
|
2101
|
+
evaluatedLights += lightResult.a;
|
|
2102
|
+
#endif
|
|
2103
|
+
|
|
2104
|
+
${o.join("")}
|
|
2105
|
+
|
|
2106
|
+
#if VOL_LOCAL_ARRAY_LIGHTS == 1
|
|
2107
|
+
int localEnd = VOL_DIRECTIONAL_LIGHT_COUNT + int(volParams.w + 0.5);
|
|
2108
|
+
|
|
2109
|
+
for (int i = VOL_DIRECTIONAL_LIGHT_COUNT; i < VOL_MAX_ARRAY_LIGHTS; ++i) {
|
|
2110
|
+
if (i >= localEnd) {
|
|
2111
|
+
break;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
lightResult = volIntegrateArrayLight(i, tStart, tEnd);
|
|
2115
|
+
accumulated += lightResult.rgb;
|
|
2116
|
+
evaluatedLights += lightResult.a;
|
|
2117
|
+
}
|
|
2118
|
+
#endif
|
|
2119
|
+
|
|
2120
|
+
// The scattering coefficient is a fraction of the extinction, which guarantees energy conservation.
|
|
2121
|
+
vec3 result = accumulated * volMedium.x * volFogColor;
|
|
2122
|
+
float finalTransmittance = volTransmittance(tEnd);
|
|
2123
|
+
|
|
2124
|
+
#if VOL_DEBUG == 3
|
|
2125
|
+
// From blue for no light to red for 16 lights or more evaluated by the pixel.
|
|
2126
|
+
float ratioOfBudget = clamp(evaluatedLights / 16.0, 0.0, 1.0);
|
|
2127
|
+
result = vec3(ratioOfBudget, 1.0 - abs(ratioOfBudget * 2.0 - 1.0), 1.0 - ratioOfBudget);
|
|
2128
|
+
#endif
|
|
2129
|
+
|
|
2130
|
+
#ifdef VOL_LDR_ENCODE
|
|
2131
|
+
result = result / (1.0 + result);
|
|
2132
|
+
#endif
|
|
2133
|
+
|
|
2134
|
+
gl_FragColor = vec4(result, finalTransmittance);
|
|
2135
|
+
}
|
|
2136
|
+
`}n(Un,"buildVolumetricLightingScatteringShader");function Wn(){return`precision highp float;
|
|
2137
|
+
precision highp int;
|
|
2138
|
+
|
|
2139
|
+
varying vec2 vUV;
|
|
2140
|
+
|
|
2141
|
+
uniform sampler2D textureSampler;
|
|
2142
|
+
uniform highp sampler2D volLinearDepthSampler;
|
|
2143
|
+
|
|
2144
|
+
uniform vec2 volCameraMinMaxZ;
|
|
2145
|
+
uniform vec2 volDepthRatio;
|
|
2146
|
+
uniform vec2 volBlurDirection;
|
|
2147
|
+
uniform vec2 volBlurParams;
|
|
2148
|
+
|
|
2149
|
+
${Je}
|
|
2150
|
+
${ci}
|
|
2151
|
+
|
|
2152
|
+
void main(void) {
|
|
2153
|
+
// The blur runs at the resolution of the scattering buffer and every tap is an exact texel, compared using
|
|
2154
|
+
// the depth the raymarching used for it: no filtering is needed, no depth has to be unpacked nor linearized.
|
|
2155
|
+
ivec2 size = textureSize(textureSampler, 0);
|
|
2156
|
+
ivec2 depthSize = textureSize(volLinearDepthSampler, 0);
|
|
2157
|
+
ivec2 center = ivec2(gl_FragCoord.xy);
|
|
2158
|
+
ivec2 direction = ivec2(volBlurDirection);
|
|
2159
|
+
|
|
2160
|
+
float centerDepth = volReadLinearDepth(volLinearDepthSampler, volScatterToDepthTexel(center, depthSize));
|
|
2161
|
+
float inverseDepthThreshold = 1.0 / max(volBlurParams.y * max(centerDepth, volCameraMinMaxZ.x), 1e-4);
|
|
2162
|
+
float sigma = max(volBlurParams.x, 1e-4);
|
|
2163
|
+
float inverseTwoSigma2 = 1.0 / (2.0 * sigma * sigma);
|
|
2164
|
+
|
|
2165
|
+
vec4 result = texelFetch(textureSampler, center, 0);
|
|
2166
|
+
float totalWeight = 1.0;
|
|
2167
|
+
|
|
2168
|
+
for (int i = 1; i <= VOL_BLUR_RADIUS; ++i) {
|
|
2169
|
+
float spatialWeight = exp(-float(i * i) * inverseTwoSigma2);
|
|
2170
|
+
|
|
2171
|
+
ivec2 positive = center + direction * i;
|
|
2172
|
+
ivec2 negative = center - direction * i;
|
|
2173
|
+
|
|
2174
|
+
if (positive.x < size.x && positive.y < size.y) {
|
|
2175
|
+
float weight = spatialWeight * exp(-abs(volReadLinearDepth(volLinearDepthSampler, volScatterToDepthTexel(positive, depthSize)) - centerDepth) * inverseDepthThreshold);
|
|
2176
|
+
result += texelFetch(textureSampler, positive, 0) * weight;
|
|
2177
|
+
totalWeight += weight;
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
if (negative.x >= 0 && negative.y >= 0) {
|
|
2181
|
+
float weight = spatialWeight * exp(-abs(volReadLinearDepth(volLinearDepthSampler, volScatterToDepthTexel(negative, depthSize)) - centerDepth) * inverseDepthThreshold);
|
|
2182
|
+
result += texelFetch(textureSampler, negative, 0) * weight;
|
|
2183
|
+
totalWeight += weight;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
gl_FragColor = result / totalWeight;
|
|
2188
|
+
}
|
|
2189
|
+
`}n(Wn,"buildVolumetricLightingBlurShader");function Xn(){return`precision highp float;
|
|
2190
|
+
precision highp int;
|
|
2191
|
+
|
|
2192
|
+
varying vec2 vUV;
|
|
2193
|
+
|
|
2194
|
+
uniform sampler2D textureSampler;
|
|
2195
|
+
uniform sampler2D volSceneSampler;
|
|
2196
|
+
uniform highp sampler2D volLinearDepthSampler;
|
|
2197
|
+
|
|
2198
|
+
uniform vec2 volCameraMinMaxZ;
|
|
2199
|
+
uniform vec2 volDepthRatio;
|
|
2200
|
+
uniform vec4 volComposeParams;
|
|
2201
|
+
|
|
2202
|
+
${Je}
|
|
2203
|
+
${ci}
|
|
2204
|
+
|
|
2205
|
+
float volBayer8(vec2 p) {
|
|
2206
|
+
vec2 p1 = mod(floor(p), 2.0);
|
|
2207
|
+
vec2 p2 = mod(floor(p * 0.5), 2.0);
|
|
2208
|
+
vec2 p3 = mod(floor(p * 0.25), 2.0);
|
|
2209
|
+
|
|
2210
|
+
float b1 = 2.0 * p1.x + 3.0 * p1.y - 4.0 * p1.x * p1.y;
|
|
2211
|
+
float b2 = 2.0 * p2.x + 3.0 * p2.y - 4.0 * p2.x * p2.y;
|
|
2212
|
+
float b3 = 2.0 * p3.x + 3.0 * p3.y - 4.0 * p3.x * p3.y;
|
|
2213
|
+
|
|
2214
|
+
return (b1 * 16.0 + b2 * 4.0 + b3) / 64.0;
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
// Nearest depth upsampling: the four low resolution taps around the pixel are weighted by both their
|
|
2218
|
+
// bilinear weight and how close the depth the raymarching used for them is to the depth of the pixel.
|
|
2219
|
+
vec4 volUpsample(float centerDepth, ivec2 depthSize) {
|
|
2220
|
+
ivec2 size = textureSize(textureSampler, 0);
|
|
2221
|
+
vec2 texelCoordinate = vUV * vec2(size) - 0.5;
|
|
2222
|
+
vec2 baseCoordinate = floor(texelCoordinate);
|
|
2223
|
+
vec2 fraction = texelCoordinate - baseCoordinate;
|
|
2224
|
+
|
|
2225
|
+
ivec2 base = ivec2(baseCoordinate);
|
|
2226
|
+
ivec2 maximum = size - 1;
|
|
2227
|
+
|
|
2228
|
+
float inverseDepthThreshold = 1.0 / max(volComposeParams.z * max(centerDepth, volCameraMinMaxZ.x), 1e-4);
|
|
2229
|
+
|
|
2230
|
+
vec4 result = vec4(0.0);
|
|
2231
|
+
float totalWeight = 0.0;
|
|
2232
|
+
|
|
2233
|
+
vec4 nearestSample = vec4(0.0);
|
|
2234
|
+
float nearestDistance = 1e20;
|
|
2235
|
+
|
|
2236
|
+
for (int y = 0; y < 2; ++y) {
|
|
2237
|
+
for (int x = 0; x < 2; ++x) {
|
|
2238
|
+
ivec2 coordinates = clamp(base + ivec2(x, y), ivec2(0), maximum);
|
|
2239
|
+
|
|
2240
|
+
float bilinearWeight = (x == 0 ? 1.0 - fraction.x : fraction.x) * (y == 0 ? 1.0 - fraction.y : fraction.y);
|
|
2241
|
+
float depthDistance = abs(volReadLinearDepth(volLinearDepthSampler, volScatterToDepthTexel(coordinates, depthSize)) - centerDepth);
|
|
2242
|
+
|
|
2243
|
+
vec4 tap = texelFetch(textureSampler, coordinates, 0);
|
|
2244
|
+
|
|
2245
|
+
if (depthDistance < nearestDistance) {
|
|
2246
|
+
nearestDistance = depthDistance;
|
|
2247
|
+
nearestSample = tap;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
float weight = bilinearWeight / (1e-4 + depthDistance * inverseDepthThreshold);
|
|
2251
|
+
result += tap * weight;
|
|
2252
|
+
totalWeight += weight;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
// Every tap sits on the other side of a silhouette, fall back to the closest one instead of averaging.
|
|
2257
|
+
return totalWeight > 1e-4 ? result / totalWeight : nearestSample;
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
void main(void) {
|
|
2261
|
+
// The linear depth has the full resolution of the canvas: same texel the depth map would give with a nearest filter.
|
|
2262
|
+
ivec2 depthSize = textureSize(volLinearDepthSampler, 0);
|
|
2263
|
+
float centerDepth = volReadLinearDepth(volLinearDepthSampler, min(ivec2(vUV * vec2(depthSize)), depthSize - 1));
|
|
2264
|
+
|
|
2265
|
+
vec4 volumetric = volUpsample(centerDepth, depthSize);
|
|
2266
|
+
|
|
2267
|
+
#ifdef VOL_LDR_ENCODE
|
|
2268
|
+
volumetric.rgb = volumetric.rgb / max(vec3(1e-4), 1.0 - volumetric.rgb);
|
|
2269
|
+
#endif
|
|
2270
|
+
|
|
2271
|
+
#if VOL_DEBUG == 1 || VOL_DEBUG == 3
|
|
2272
|
+
gl_FragColor = vec4(volumetric.rgb * volComposeParams.x, 1.0);
|
|
2273
|
+
return;
|
|
2274
|
+
#elif VOL_DEBUG == 2
|
|
2275
|
+
gl_FragColor = vec4(vec3(volumetric.a), 1.0);
|
|
2276
|
+
return;
|
|
2277
|
+
#endif
|
|
2278
|
+
|
|
2279
|
+
vec3 sceneColor = texture2D(volSceneSampler, vUV).rgb;
|
|
2280
|
+
|
|
2281
|
+
// The materials of the scene already attenuated their color with the fog, so this is left at 0 by
|
|
2282
|
+
// default and only becomes useful when the medium is driven by the pipeline instead of the scene fog.
|
|
2283
|
+
sceneColor *= mix(1.0, volumetric.a, volComposeParams.y);
|
|
2284
|
+
|
|
2285
|
+
vec3 result = sceneColor + volumetric.rgb * volComposeParams.x;
|
|
2286
|
+
|
|
2287
|
+
// Breaks up the banding an 8 bits output would otherwise show on the smooth gradients of the shafts.
|
|
2288
|
+
result += (volBayer8(gl_FragCoord.xy) - 0.5) * volComposeParams.w;
|
|
2289
|
+
|
|
2290
|
+
gl_FragColor = vec4(result, 1.0);
|
|
2291
|
+
}
|
|
2292
|
+
`}n(Xn,"buildVolumetricLightingComposeShader");var Lo={};function Do(t){if(!Lo[t]){if(Lo[t]=!0,t===Co.ShaderLanguage.WGSL){let e=bo();j.ShaderStore.ShadersStoreWGSL[`${et}PixelShader`]=e.linearDepth,j.ShaderStore.ShadersStoreWGSL[`${tt}PixelShader`]=e.scattering,j.ShaderStore.ShadersStoreWGSL[`${it}PixelShader`]=e.blur,j.ShaderStore.ShadersStoreWGSL[`${ot}PixelShader`]=e.compose;return}j.ShaderStore.ShadersStore[`${et}PixelShader`]=kn(),j.ShaderStore.ShadersStore[`${tt}PixelShader`]=Un(A),j.ShaderStore.ShadersStore[`${it}PixelShader`]=Wn(),j.ShaderStore.ShadersStore[`${ot}PixelShader`]=Xn()}}n(Do,"registerVolumetricLightingShaders");var Po=require("babylonjs"),Oo=require("babylonjs"),Z=require("babylonjs"),ve=require("babylonjs"),Ie=require("babylonjs"),Eo=require("babylonjs"),pi=require("babylonjs"),Me=require("babylonjs"),Ao=require("babylonjs"),$n=new ve.Vector3(0,0,1),Kn=new ve.Vector3(0,0,-1),_o=["resolutionScale","blurPasses"],jn=32,Zn=["volInverseViewProjection","volViewProjection","volCameraPosition","volCameraForward","volCameraMinMaxZ","volDepthRatio","volFrameIndex","volFogInfos","volFogColor","volLinearFogEps","volMedium","volScreenShadowParams","volAmbient","volParams","volLightData","volLightDiffuse","volLightDirection","volLightFalloff","volShadowLightData","volShadowLightDiffuse","volShadowLightDirection","volShadowLightFalloff","volShadowInfo","volShadowMatrix","volCsmLightData","volCsmLightDiffuse","volCsmLightDirection","volCsmLightFalloff","volCsmInfo","volCsmMatrices"],wo=["volCsmSampler"];for(let t=0;t<A;++t)wo.push(`volShadowSampler${t}`);var Y=class t extends Ao.PostProcessRenderPipeline{static{n(this,"VolumetricLightingRenderingPipeline")}static SceneColorEffectName="VolumetricLightingSceneColorEffect";static ScatteringEffectName="VolumetricLightingScatteringEffect";static BlurEffectName="VolumetricLightingBlurEffect";static ComposeEffectName="VolumetricLightingComposeEffect";static GetDefaultFogEnd(e,i){return 1/t.GetDefaultFogDensity(e,i)}static GetDefaultFogDensity(e,i){let o=0;if(e.meshes.length){let r=e.getWorldExtends(),a=r.max.subtract(r.min).length();isFinite(a)&&(o=a)}return o<.001&&(o=Math.max(i.globalPosition.length(),i.maxZ*.001,1)),Math.min(1,Math.max(1e-5,1/Math.max(.001,o)))}static IsSupported(e){return e.isWebGPU?!0:(e.webGLVersion??0)>=2}static GetShaderLanguage(e){return e.isWebGPU?pi.ShaderLanguage.WGSL:pi.ShaderLanguage.GLSL}_scene;_camera;_configuration;_configurationProxy;_textureType;_shaderLanguage;_ldrEncode;_linearDepthPacked;_depthRenderer=null;_ownsDepthRenderer=!1;_depthMode=0;_linearDepthPostProcess=null;_scatteringPostProcess=null;_blurPostProcesses=[];_composePostProcess=null;_selection=null;_budget;_linearDepthDefines="";_scatteringDefines="";_blurDefines="";_composeDefines="";_frameCount=0;_lightsDirty=!0;_disposed=!1;_beforeCameraRenderObserver=null;_lightAddedObserver=null;_lightRemovedObserver=null;_inverseViewProjection=ve.Matrix.Identity();_temporaryVector=new ve.Vector3;_temporaryColor=new Oo.Color3;_lightData=new Float32Array($*4);_lightDiffuse=new Float32Array($*4);_lightDirection=new Float32Array($*4);_lightFalloff=new Float32Array($*4);_shadowLightData=new Float32Array(A*4);_shadowLightDiffuse=new Float32Array(A*4);_shadowLightDirection=new Float32Array(A*4);_shadowLightFalloff=new Float32Array(A*4);_shadowInfo=new Float32Array(A*4);_shadowMatrices=new Float32Array(A*16);_csmLightData=new Float32Array(4);_csmLightDiffuse=new Float32Array(4);_csmLightDirection=new Float32Array(4);_csmLightFalloff=new Float32Array(4);_csmMatrices=new Float32Array(64);constructor(e,i,o,r){super(i.getEngine(),e),this._shaderLanguage=t.GetShaderLanguage(i.getEngine()),Do(this._shaderLanguage),this._scene=i,this._camera=o,this._configuration=ge({...je(),fogDensity:r?.fogDensity??t.GetDefaultFogDensity(i,o),fogEnd:r?.fogEnd??t.GetDefaultFogEnd(i,o),screenSpaceShadowMaxDistance:r?.screenSpaceShadowMaxDistance??t.GetDefaultFogEnd(i,o),...r}),this._configurationProxy=new Proxy(this._configuration,{set:n((s,c,m)=>{let h=c;return s[h]===m||(s[h]=m,this._onConfigurationChanged(h)),!0},"set")});let a=i.getEngine(),l=a.getCaps(),p=l.textureHalfFloatRender&&l.textureHalfFloatLinearFiltering;this._textureType=p?Z.Constants.TEXTURETYPE_HALF_FLOAT:Z.Constants.TEXTURETYPE_UNSIGNED_BYTE,this._ldrEncode=!p,this._linearDepthPacked=!l.textureFloatRender,this._budget=Ae(a,this._configuration),this._setupDepthRenderer(),this._buildRenderEffects(),i.postProcessRenderPipelineManager.addPipeline(this),i.postProcessRenderPipelineManager.attachCamerasToRenderPipeline(this.name,o),this._beforeCameraRenderObserver=i.onBeforeCameraRenderObservable.add(s=>{s===this._camera&&this._updateSelection()}),this._lightAddedObserver=i.onNewLightAddedObservable.add(()=>this.markLightsDirty()),this._lightRemovedObserver=i.onLightRemovedObservable.add(()=>this.markLightsDirty())}get isDisposed(){return this._disposed}get scene(){return this._scene}get camera(){return this._camera}get configuration(){return this._configurationProxy}getStats(){return this._selection?.stats??null}getBudget(){return this._budget}getClassName(){return"VolumetricLightingRenderingPipeline"}markLightsDirty(){this._lightsDirty=!0}applyConfiguration(e){let i=ge({...this._configuration,...e}),o=_o.some(r=>i[r]!==this._configuration[r]);Object.assign(this._configuration,i),this._budget=Ae(this._scene.getEngine(),this._configuration),this._lightsDirty=!0,o&&this._rebuildRenderEffects()}serializeConfiguration(){return{...this._configuration,fogColor:this._configuration.fogColor.slice(),ambientColor:this._configuration.ambientColor.slice()}}dispose(){if(this._disposed)return;this._disposed=!0,this._scene.onBeforeCameraRenderObservable.remove(this._beforeCameraRenderObserver),this._scene.onNewLightAddedObservable.remove(this._lightAddedObserver),this._scene.onLightRemovedObservable.remove(this._lightRemovedObserver),this._beforeCameraRenderObserver=null,this._lightAddedObserver=null,this._lightRemovedObserver=null;let e=this._cameras.slice();this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this.name,e),this._disposePostProcesses(e),this._ownsDepthRenderer&&this._scene.disableDepthRenderer(this._camera),this._depthRenderer=null,this._selection=null,this._scene.postProcessRenderPipelineManager.removePipeline(this.name),super.dispose()}_onConfigurationChanged(e){(e==="maxLights"||e==="maxShadowedLights")&&(this._budget=Ae(this._scene.getEngine(),this._configuration)),this._lightsDirty=!0,_o.includes(e)&&this._rebuildRenderEffects()}_setupDepthRenderer(){let e=this._scene._depthRenderer?.[this._camera.uniqueId];this._ownsDepthRenderer=!e,this._depthRenderer=e??this._scene.enableDepthRenderer(this._camera,!1,!1,Z.Constants.TEXTURE_NEAREST_SAMPLINGMODE,!1),this._depthRenderer.isPacked?this._depthMode=2:this._depthRenderer.clearColor.r===0?this._depthMode=1:this._depthMode=0}_bindDepthUniforms(e){let i=this._camera,o=this._scene.getEngine();if(e.setFloat2("volCameraMinMaxZ",i.minZ,i.maxZ),this._depthMode===1){e.setFloat2("volDepthUnpack",1,0);return}let r=i.mode===Po.Camera.ORTHOGRAPHIC_CAMERA,a=r?!o.useReverseDepthBuffer&&o.isNDCHalfZRange?0:1:o.useReverseDepthBuffer&&o.isNDCHalfZRange?i.minZ:o.isNDCHalfZRange?0:i.minZ,l=r?o.useReverseDepthBuffer&&o.isNDCHalfZRange?0:1:o.useReverseDepthBuffer&&o.isNDCHalfZRange?0:i.maxZ,p=this._scene.getProjectionMatrix().m,s=p[10],c=p[14];if(!s){e.setFloat2("volDepthUnpack",i.maxZ,0);return}let m=o.useReverseDepthBuffer?-1:1;e.setFloat2("volDepthUnpack",m*(a+l)/s,(-m*a-c)/s)}_getEnvironment(){let e=this._configuration,i=0;return e.heightFogEnabled&&(i=e.fogMode===0?1:2),{depthMode:this._depthMode,ldrEncode:this._ldrEncode,reverseDepth:this._scene.getEngine().useReverseDepthBuffer,ndcHalfZ:this._scene.getEngine().isNDCHalfZRange,fogMode:e.fogMode,transmittance:i,linearDepthPacked:this._linearDepthPacked,arrayLightCapacity:this._budget.maxArrayLights,lightSteps:ti(e)}}_buildLinearDepthReadDefines(e){return e.linearDepthPacked?`#define VOL_LINEAR_DEPTH_PACKED
|
|
2293
|
+
`:""}_buildLinearDepthDefines(e){let i=this._buildLinearDepthReadDefines(e);return e.depthMode===2?i+=`#define VOL_DEPTH_PACKED
|
|
2294
|
+
`:e.depthMode===1&&(i+=`#define VOL_DEPTH_VIEWZ
|
|
2295
|
+
`),i}_buildScatteringDefines(e,i){let o=this._configuration,r=e?.shadowed??[],a=e?.directionalCount??0,l=e?.csm??null,p=r.filter(c=>!c.shadow.local).length,s=this._buildLinearDepthReadDefines(i);return s+=`#define VOL_STEPS ${o.steps}
|
|
2296
|
+
`,s+=`#define VOL_LIGHT_STEPS ${i.lightSteps}
|
|
2297
|
+
`,s+=`#define VOL_LOCAL_MAX_STEPS ${Math.max(i.lightSteps,o.steps)}
|
|
2298
|
+
`,s+=`#define VOL_DISTRIBUTION ${o.stepDistribution}
|
|
2299
|
+
`,s+=`#define VOL_DITHER ${o.ditherMode}
|
|
2300
|
+
`,s+=`#define VOL_PCF_TAPS ${o.pcfTaps}
|
|
2301
|
+
`,s+=`#define VOL_FOG_MODE ${i.fogMode}
|
|
2302
|
+
`,s+=`#define VOL_TRANSMITTANCE ${i.transmittance}
|
|
2303
|
+
`,(i.transmittance!==0||i.fogMode!==2)&&(s+=`#define VOL_OPTICAL_DEPTH
|
|
2304
|
+
`),s+=`#define VOL_TRANSMITTANCE_SAMPLES ${jn}
|
|
2305
|
+
`,s+=`#define VOL_DEBUG ${o.debugMode}
|
|
2306
|
+
`,s+=`#define VOL_MAX_ARRAY_LIGHTS ${i.arrayLightCapacity}
|
|
2307
|
+
`,s+=`#define VOL_DIRECTIONAL_LIGHT_COUNT ${a}
|
|
2308
|
+
`,s+=`#define VOL_LOCAL_ARRAY_LIGHTS ${i.arrayLightCapacity>a?1:0}
|
|
2309
|
+
`,s+=`#define VOL_SHADOW_SLOT_COUNT ${r.length}
|
|
2310
|
+
`,s+=`#define VOL_GLOBAL_LIGHT_COUNT ${a+p+(l?1:0)}
|
|
2311
|
+
`,o.ditherMode!==0&&o.temporalJitter&&(s+=`#define VOL_TEMPORAL_JITTER
|
|
2312
|
+
`),o.heightFogEnabled&&(s+=`#define VOL_HEIGHT_FOG
|
|
2313
|
+
`),o.lightExtinctionEnabled&&(s+=`#define VOL_LIGHT_EXTINCTION
|
|
2314
|
+
`),o.screenSpaceShadows&&(s+=`#define VOL_SCREEN_SHADOWS
|
|
2315
|
+
`,s+=`#define VOL_SCREEN_SHADOW_STEPS ${o.screenSpaceShadowSteps}
|
|
2316
|
+
`),i.ldrEncode&&(s+=`#define VOL_LDR_ENCODE
|
|
2317
|
+
`),i.reverseDepth&&(s+=`#define VOL_REVERSE_DEPTH
|
|
2318
|
+
`),i.ndcHalfZ&&(s+=`#define VOL_NDC_HALF_Z
|
|
2319
|
+
`),r.forEach((c,m)=>{s+=`#define VOL_SHADOW_KIND${m} ${c.shadow.kind}
|
|
2320
|
+
`,s+=`#define VOL_SHADOW_MODE${m} ${c.shadow.mode}
|
|
2321
|
+
`,s+=`#define VOL_SHADOW_LOCAL${m} ${c.shadow.local?1:0}
|
|
2322
|
+
`,c.shadow.packed&&(s+=`#define VOL_SHADOW_PACKED${m}
|
|
2323
|
+
`)}),l&&(s+=`#define VOL_CSM
|
|
2324
|
+
`,s+=`#define VOL_CSM_CASCADES ${l.cascades}
|
|
2325
|
+
`,s+=`#define VOL_CSM_KIND ${l.kind===1?1:0}
|
|
2326
|
+
`,l.packed&&(s+=`#define VOL_CSM_PACKED
|
|
2327
|
+
`)),s}_buildBlurDefines(e){return`${this._buildLinearDepthReadDefines(e)}#define VOL_BLUR_RADIUS ${this._configuration.blurRadius}
|
|
2328
|
+
`}_buildComposeDefines(e){let i=this._buildLinearDepthReadDefines(e);return i+=`#define VOL_DEBUG ${this._configuration.debugMode}
|
|
2329
|
+
`,e.ldrEncode&&(i+=`#define VOL_LDR_ENCODE
|
|
2330
|
+
`),i}_createPostProcess(e){let i=new Eo.PostProcess(e.name,e.shaderName,e.uniforms,e.samplers,e.ratio,null,e.samplingMode,this._scene.getEngine(),!1,e.defines,e.textureType,void 0,void 0,!1,e.textureFormat,this._shaderLanguage);return i.autoClear=!1,i.alphaMode=Z.Constants.ALPHA_DISABLE,i}_buildRenderEffects(){let e=this._scene.getEngine(),i=this._configuration,o=this._getEnvironment();this._linearDepthDefines=this._buildLinearDepthDefines(o),this._scatteringDefines=this._buildScatteringDefines(this._selection,o),this._blurDefines=this._buildBlurDefines(o),this._composeDefines=this._buildComposeDefines(o),this._linearDepthPostProcess=this._createPostProcess({name:"VolumetricLightingLinearDepth",shaderName:et,uniforms:["volCameraMinMaxZ","volDepthUnpack"],samplers:["depthSampler"],ratio:1,samplingMode:Ie.Texture.BILINEAR_SAMPLINGMODE,textureType:this._textureType,defines:this._linearDepthDefines}),this._linearDepthPostProcess.onApplyObservable.add(r=>this._bindLinearDepth(r)),this._scatteringPostProcess=this._createPostProcess({name:"VolumetricLightingScattering",shaderName:tt,uniforms:Zn,samplers:wo,ratio:1,samplingMode:Ie.Texture.NEAREST_SAMPLINGMODE,textureType:this._linearDepthPacked?Z.Constants.TEXTURETYPE_UNSIGNED_BYTE:Z.Constants.TEXTURETYPE_FLOAT,textureFormat:this._linearDepthPacked?Z.Constants.TEXTUREFORMAT_RGBA:Z.Constants.TEXTUREFORMAT_R,defines:this._scatteringDefines}),this._scatteringPostProcess.onApplyObservable.add(r=>this._bindScattering(r)),this._blurPostProcesses=[];for(let r=0;r<i.blurPasses;++r){let a=this._createPostProcess({name:`VolumetricLightingBlur${r}`,shaderName:it,uniforms:["volCameraMinMaxZ","volDepthRatio","volBlurDirection","volBlurParams"],samplers:["volLinearDepthSampler"],ratio:i.resolutionScale,samplingMode:Ie.Texture.BILINEAR_SAMPLINGMODE,textureType:this._textureType,defines:this._blurDefines});a.onApplyObservable.add(l=>this._bindBlur(l,r)),this._blurPostProcesses.push(a)}this._composePostProcess=this._createPostProcess({name:"VolumetricLightingCompose",shaderName:ot,uniforms:["volCameraMinMaxZ","volDepthRatio","volComposeParams"],samplers:["volSceneSampler","volLinearDepthSampler"],ratio:i.resolutionScale,samplingMode:Ie.Texture.BILINEAR_SAMPLINGMODE,textureType:this._textureType,defines:this._composeDefines}),this._composePostProcess.onApplyObservable.add(r=>this._bindCompose(r)),this.addEffect(new Me.PostProcessRenderEffect(e,t.SceneColorEffectName,()=>this._linearDepthPostProcess,!0)),this.addEffect(new Me.PostProcessRenderEffect(e,t.ScatteringEffectName,()=>this._scatteringPostProcess,!0)),this._blurPostProcesses.length&&this.addEffect(new Me.PostProcessRenderEffect(e,t.BlurEffectName,()=>this._blurPostProcesses,!0)),this.addEffect(new Me.PostProcessRenderEffect(e,t.ComposeEffectName,()=>this._composePostProcess,!0))}_disposePostProcesses(e){[this._linearDepthPostProcess,this._scatteringPostProcess,...this._blurPostProcesses,this._composePostProcess].forEach(o=>{o&&(e.forEach(r=>o.dispose(r)),o.dispose())}),this._linearDepthPostProcess=null,this._scatteringPostProcess=null,this._blurPostProcesses=[],this._composePostProcess=null}_rebuildRenderEffects(){if(this._disposed)return;let e=this._scene.postProcessRenderPipelineManager,i=this._cameras.slice();try{e.detachCamerasFromRenderPipeline(this.name,i),this._disposePostProcesses(i),Object.keys(this._renderEffects).forEach(o=>{delete this._renderEffects[o]}),this._buildRenderEffects()}catch(o){console.error("Failed to rebuild the volumetric lighting rendering pipeline.",o)}finally{try{e.attachCamerasToRenderPipeline(this.name,i)}catch(o){console.error("Failed to re-attach the cameras to the volumetric lighting rendering pipeline.",o)}}this._lightsDirty=!0}_updateSelection(){if(this._disposed||!this._scatteringPostProcess||(++this._frameCount,!(this._lightsDirty||!this._selection||this._frameCount%this._configuration.selectionRefreshRate===0)))return;this._lightsDirty=!1;let i=this._getEnvironment(),o=si(this._scene,this._camera,this._configuration,this._budget,this._selection);this._selection=o;let r=this._buildScatteringDefines(o,i);r!==this._scatteringDefines&&(this._scatteringDefines=r,this._scatteringPostProcess.updateEffect(r));let a=this._buildLinearDepthDefines(i);a!==this._linearDepthDefines&&(this._linearDepthDefines=a,this._linearDepthPostProcess?.updateEffect(a));let l=this._buildBlurDefines(i);l!==this._blurDefines&&(this._blurDefines=l,this._blurPostProcesses.forEach(s=>s.updateEffect(l)));let p=this._buildComposeDefines(i);p!==this._composeDefines&&(this._composeDefines=p,this._composePostProcess?.updateEffect(p))}_writeLight(e,i,o,r,a,l){let{light:p,config:s}=e,c=i*4;ee(p)?(Te(p,this._temporaryVector),o[c]=-this._temporaryVector.x,o[c+1]=-this._temporaryVector.y,o[c+2]=-this._temporaryVector.z,o[c+3]=1):(Ye(p,this._temporaryVector).subtractInPlace(this._camera.globalPosition),o[c]=this._temporaryVector.x,o[c+1]=this._temporaryVector.y,o[c+2]=this._temporaryVector.z,o[c+3]=oe(p)?2:0),s.useCustomColor?this._temporaryColor.set(s.color[0],s.color[1],s.color[2]):this._temporaryColor.copyFrom(p.diffuse);let m=p.getScaledIntensity()*s.volumeIntensity*1e-5;r[c]=this._temporaryColor.r*m,r[c+1]=this._temporaryColor.g*m,r[c+2]=this._temporaryColor.b*m,r[c+3]=s.anisotropy,oe(p)?(Te(p,this._temporaryVector),a[c]=this._temporaryVector.x,a[c+1]=this._temporaryVector.y,a[c+2]=this._temporaryVector.z,a[c+3]=Math.cos(p.angle*.5),l[c+1]=p.exponent):(a[c]=0,a[c+1]=0,a[c+2]=1,a[c+3]=-1,l[c+1]=1),l[c]=qe(p,s,this._configuration),l[c+2]=s.castVolumetricShadows?1:0,l[c+3]=s.shadowDarkness}_bindLinearDepth(e){this._depthRenderer&&(e.setTexture("depthSampler",this._depthRenderer.getDepthMap()),this._bindDepthUniforms(e))}_bindScattering(e){let i=this._scene,o=this._camera,r=this._configuration,a=this._selection;if(!a)return;this._inverseViewProjection.copyFrom(i.getTransformMatrix()),this._inverseViewProjection.invert(),e.setMatrix("volInverseViewProjection",this._inverseViewProjection),e.setVector3("volCameraPosition",o.globalPosition),o.getDirectionToRef(i.useRightHandedSystem?Kn:$n,this._temporaryVector),e.setVector3("volCameraForward",this._temporaryVector.normalize()),e.setFloat2("volCameraMinMaxZ",o.minZ,o.maxZ),e.setFloat("volFrameIndex",i.getRenderId()%64),this._bindDepthRatio(e),e.setFloat4("volFogInfos",r.fogMode,r.fogStart,r.fogEnd,r.fogDensity),this._temporaryColor.set(r.fogColor[0],r.fogColor[1],r.fogColor[2]),e.setColor3("volFogColor",this._temporaryColor),e.setFloat("volLinearFogEps",Math.max((r.fogEnd-r.fogStart)*.02,1e-4)),e.setFloat4("volMedium",r.albedo,r.heightFogBaseHeight,r.heightFogFalloff,0),r.screenSpaceShadows&&(e.setMatrix("volViewProjection",i.getTransformMatrix()),e.setFloat4("volScreenShadowParams",r.screenSpaceShadowMaxDistance,r.screenSpaceShadowBias,r.screenSpaceShadowThickness,0)),this._temporaryColor.set(r.ambientColor[0],r.ambientColor[1],r.ambientColor[2]).scaleInPlace(r.ambientIntensity),e.setColor3("volAmbient",this._temporaryColor);let l=a.unshadowed.length,p=l-a.directionalCount;e.setFloat4("volParams",r.maxDistance,r.ditherStrength,r.lightExtinctionClamp,p);for(let s=0;s<l;++s)this._writeLight(a.unshadowed[s],s,this._lightData,this._lightDiffuse,this._lightDirection,this._lightFalloff);if(l){let s=l*4;e.setFloatArray4("volLightData",this._lightData.subarray(0,s)),e.setFloatArray4("volLightDiffuse",this._lightDiffuse.subarray(0,s)),e.setFloatArray4("volLightDirection",this._lightDirection.subarray(0,s)),e.setFloatArray4("volLightFalloff",this._lightFalloff.subarray(0,s))}if(a.shadowed.forEach((s,c)=>{this._writeLight(s.candidate,c,this._shadowLightData,this._shadowLightDiffuse,this._shadowLightDirection,this._shadowLightFalloff);let{generator:m,kind:h,mode:d,mapSize:f}=s.shadow,S=s.candidate.light,g=c*4;this._shadowLightFalloff[g+2]=m.frustumEdgeFalloff;let b=S.getDepthMinZ?.(i.activeCamera)??0,C=S.getDepthMaxZ?.(i.activeCamera)??1;this._shadowInfo[g]=m.getDarkness(),this._shadowInfo[g+1]=h===1?1/f:d===0?0:m.depthScale,this._shadowInfo[g+2]=b,this._shadowInfo[g+3]=b+C,m.getTransformMatrix().copyToArray(this._shadowMatrices,c*16);let _=m.getShadowMapForRendering();h===1?e.setDepthStencilTexture(`volShadowSampler${c}`,_):e.setTexture(`volShadowSampler${c}`,_)}),a.shadowed.length){let s=a.shadowed.length*4;e.setFloatArray4("volShadowLightData",this._shadowLightData.subarray(0,s)),e.setFloatArray4("volShadowLightDiffuse",this._shadowLightDiffuse.subarray(0,s)),e.setFloatArray4("volShadowLightDirection",this._shadowLightDirection.subarray(0,s)),e.setFloatArray4("volShadowLightFalloff",this._shadowLightFalloff.subarray(0,s)),e.setFloatArray4("volShadowInfo",this._shadowInfo.subarray(0,s)),e.setMatrices("volShadowMatrix",this._shadowMatrices.subarray(0,a.shadowed.length*16))}if(a.csm){let{candidate:s,generator:c,cascades:m,kind:h}=a.csm,d=s.light;this._writeLight(s,0,this._csmLightData,this._csmLightDiffuse,this._csmLightDirection,this._csmLightFalloff),e.setFloat4("volCsmLightData",this._csmLightData[0],this._csmLightData[1],this._csmLightData[2],this._csmLightData[3]),e.setFloat4("volCsmLightDiffuse",this._csmLightDiffuse[0],this._csmLightDiffuse[1],this._csmLightDiffuse[2],this._csmLightDiffuse[3]),e.setFloat4("volCsmLightDirection",this._csmLightDirection[0],this._csmLightDirection[1],this._csmLightDirection[2],this._csmLightDirection[3]),e.setFloat4("volCsmLightFalloff",this._csmLightFalloff[0],this._csmLightFalloff[1],c.frustumEdgeFalloff,s.config.shadowDarkness);let f=d.getDepthMinZ?.(i.activeCamera)??1,S=d.getDepthMaxZ?.(i.activeCamera)??1,g=c.getShadowMap()?.getSize().width??1024;e.setFloat4("volCsmInfo",c.getDarkness(),1/g,f,f+S);for(let C=0;C<m;++C)c.getCascadeTransformMatrix(C)?.copyToArray(this._csmMatrices,C*16);e.setMatrices("volCsmMatrices",this._csmMatrices.subarray(0,m*16));let b=c.getShadowMapForRendering();h===1?e.setDepthStencilTexture("volCsmSampler",b):e.setTexture("volCsmSampler",b)}}_bindDepthRatio(e){let i=this._scatteringPostProcess,o=this._blurPostProcesses[0]??this._composePostProcess,r=i&&i.width>0?i.width:1,a=i&&i.height>0?i.height:1,l=o&&o.width>0?o.width:r,p=o&&o.height>0?o.height:a;e.setFloat2("volDepthRatio",r/l,a/p)}_bindBlur(e,i){this._scatteringPostProcess&&(e.setTextureFromPostProcess("volLinearDepthSampler",this._scatteringPostProcess),e.setFloat2("volCameraMinMaxZ",this._camera.minZ,this._camera.maxZ),this._bindDepthRatio(e),e.setFloat2("volBlurDirection",i%2===0?1:0,i%2===0?0:1),e.setFloat2("volBlurParams",Math.max(this._configuration.blurRadius*.5,.5),this._configuration.blurDepthThreshold))}_bindCompose(e){if(!this._linearDepthPostProcess||!this._scatteringPostProcess)return;let i=this._configuration;e.setTextureFromPostProcess("volSceneSampler",this._linearDepthPostProcess),e.setTextureFromPostProcess("volLinearDepthSampler",this._scatteringPostProcess),e.setFloat2("volCameraMinMaxZ",this._camera.minZ,this._camera.maxZ),this._bindDepthRatio(e);let o=this._ldrEncode?1/255:0;e.setFloat4("volComposeParams",i.intensity,i.extinctionAmount,i.upsampleDepthThreshold,o)}};var N=null,Se=new Map;function To(){return N?.isDisposed&&(N=null),N}n(To,"getVolumetricLightingRenderingPipeline");function Yn(t){N=t}n(Yn,"setVolumetricLightingRenderingPipelineRef");function qn(t){let e=t?.getEngine();return e?Y.IsSupported(e):!1}n(qn,"isVolumetricLightingSupported");function mi(){N&&(N.dispose(),N=null)}n(mi,"disposeVolumetricLightingRenderingPipeline");function Io(t,e){return N=new Y("VolumetricLightingRenderingPipeline",t,e),N}n(Io,"createVolumetricLightingRenderingPipeline");function hi(){return N?N.serializeConfiguration():null}n(hi,"serializeVolumetricLightingRenderingPipeline");function di(t,e,i){let o=To()??Io(t,e),r={...i};return r.fogDensity===void 0&&(r.fogDensity=Y.GetDefaultFogDensity(o.scene,o.camera)),r.fogEnd===void 0&&(r.fogEnd=Y.GetDefaultFogEnd(o.scene,o.camera)),r.screenSpaceShadowMaxDistance===void 0&&(r.screenSpaceShadowMaxDistance=Y.GetDefaultFogEnd(o.scene,o.camera)),o.applyConfiguration(ge(r)),o}n(di,"parseVolumetricLightingRenderingPipeline");function Qn(){N?.markLightsDirty()}n(Qn,"markVolumetricLightsDirty");function Jn(t){de.set(t,Bt()),pe.set(t,At()),me.set(t,Mt()),fe.set(t,Ut()),Se.set(t,hi()),ue.set(t,Kt()),he.set(t,Ft())}n(Jn,"saveRenderingConfigurationForCamera");function fi(t,e,i){Gt(),Et(t.getScene()),It(),kt(),mi(),$t(),Vt();let o=de.get(t);o&&!i?.ssao2Disabled&&zt(t.getScene(),t,o);let r=Se.get(t);r&&!i?.volumetricLightingDisabled&&di(t.getScene(),t,r);let a=pe.get(t);a&&!i?.vlsDisabled&&Tt(t.getScene(),a);let l=me.get(t);l&&!i?.ssrDisabled&&Rt(t.getScene(),t,l);let p=fe.get(t);p&&!i?.motionBlurDisabled&&Wt(t.getScene(),t,p);let s=ue.get(t);s&&!i?.defaultPipelineDisabled&&jt(t.getScene(),t,s,e);let c=he.get(t);c&&!i?.taaDisabled&&Nt(t.getScene(),t,c)}n(fi,"applyRenderingConfigurationForCamera");var Re=require("babylonjs"),Mo=require("babylonjs");function Ro(t){let e=t.metadata?.physicsAggregate;if(!e)return;let i;V(t)?i=t:Pe(t)&&(i=t.sourceMesh);let o=new Mo.PhysicsAggregate(t,e.shape.type,{mesh:i,mass:e.massProperties.mass});o.body.setMassProperties({mass:e.massProperties.mass,inertia:e.massProperties.inertia?Re.Vector3.FromArray(e.massProperties.inertia):void 0,centerOfMass:e.massProperties.centerOfMass?Re.Vector3.FromArray(e.massProperties.centerOfMass):void 0,inertiaOrientation:e.massProperties.inertiaOrientation?Re.Quaternion.FromArray(e.massProperties.inertiaOrientation):void 0}),o.shape.density=e.shape.density,o.body.setMotionType(e.body.motionType),o.shape.material=e.material,t.physicsAggregate=o,t.metadata.physicsAggregate=void 0}n(Ro,"configurePhysicsAggregate");function Vo(t,e){(Array.isArray(e)?e:[]).forEach(o=>{let r=t.getCameraById(o.cameraId);r&&(o.ssao2RenderingPipeline&&de.set(r,o.ssao2RenderingPipeline),o.vlsPostProcess&&pe.set(r,o.vlsPostProcess),o.ssrRenderingPipeline&&me.set(r,o.ssrRenderingPipeline),o.motionBlurPostProcess&&fe.set(r,o.motionBlurPostProcess),o.volumetricLightingRenderingPipeline&&Se.set(r,o.volumetricLightingRenderingPipeline),o.defaultRenderingPipeline&&ue.set(r,o.defaultRenderingPipeline),o.taaRenderingPipeline&&he.set(r,o.taaRenderingPipeline))})}n(Vo,"applyRenderingConfigurations");var Fo=require("babylonjs");function ye(t,e,i){return new Promise((o,r)=>{let a=new Fo.WebRequest;a.open("GET",t),a.responseType=e,a.send(),a.addEventListener("progress",l=>{i?.({total:l.total,loaded:l.loaded})}),a.addEventListener("load",()=>{o(e==="text"?a.responseText:a.response)}),a.addEventListener("error",l=>r(l))})}n(ye,"loadFile");async function z(t,e){let i=await ye(t,"text",e);return JSON.parse(i)}n(z,"loadJsonFile");function ui(t,e){let i=e.getNodeByName(t);if(i)return i;let o=e.lights.filter(r=>le(r));for(let r of o){let a=r.lights.find(l=>l.name===t);if(a)return a}return null}n(ui,"getNodeByName");function be(t,e){let i=e.getNodeById(t);if(i)return i;let o=e.lights.filter(r=>le(r));for(let r of o){let a=r.lights.find(l=>l.id===t);if(a)return a}return null}n(be,"getNodeById");var ae=require("babylonjs"),No=require("babylonjs");function gi(t){let e=No.Vector3.FromArray(t);return e.equals(ae.Axis.X)?ae.Axis.X:e.equals(ae.Axis.Y)?ae.Axis.Y:e.equals(ae.Axis.Z)?ae.Axis.Z:e}n(gi,"parseAxis");function Go(t){return t.runtimeConfiguration.forEach(e=>{e.rotationAxis&&(e.rotationAxis=gi(e.rotationAxis)),e.boneOffsetAxis&&(e.boneOffsetAxis=gi(e.boneOffsetAxis))}),t}n(Go,"parseRagdollConfiguration");function vi(t){let e={rootNodeId:t.rootNodeId,skeletonName:t.skeletonName,scalingFactor:t.scalingFactor,runtimeConfiguration:t.runtimeConfiguration.map(i=>({name:i.name,bones:i.bones,width:i.width,depth:i.depth,height:i.height,size:i.size,joint:i.joint,min:i.min,max:i.max,boxOffset:i.boxOffset,rotationAxis:i.rotationAxis?.slice(),boneOffsetAxis:i.boneOffsetAxis?.slice()}))};return Go(e)}n(vi,"copyAndParseRagdollConfiguration");function ea(t){return new Promise(e=>{setTimeout(()=>e(),t)})}n(ea,"waitMs");async function Si(t){for(;!t();)await ea(150)}n(Si,"waitUntil");function yi(t){return t&&JSON.parse(JSON.stringify(t))}n(yi,"cloneJSObject");var xi=require("babylonjs"),Wo=require("babylonjs"),rt=require("babylonjs"),Xo=require("babylonjs"),$o=require("babylonjs"),Ko=require("babylonjs"),te=require("babylonjs"),Bo=!1,zo=null,xe=[],bi=new Map;function ta(t,e){let i=(0,te._GetAudioEngine)(null);return new Ko._WebAudioStaticSound(t,i,e)}n(ta,"createSoundInstance");function Ho(t){if(zo?.remove(),!xe.length)return;let e=xi.Vector3.Zero();zo=t.onBeforeRenderObservable.add(()=>{let i=(0,te._GetAudioEngine)(null).listener.attachedNode;i&&(i.getWorldMatrix().getTranslationToRef(e),xe.forEach(o=>{o.isEnabled(!1)&&o.autoUpdateSpatial&&o.sound?._isSpatial&&o.isPlaying()&&t.activeCamera&&xi.Vector3.Distance(e,o.getAbsolutePosition())<=o.sound.spatial.maxDistance&&o.sound.spatial.update()}))})}n(Ho,"registerUpdateSoundsObserver");function ko(t){t.sound?.onDisposeObservable.addOnce(()=>{let e=xe.indexOf(t);e!==-1&&xe.splice(e,1)}),t.onDisposeObservable.addOnce(()=>{t.sound?.dispose()})}n(ko,"registerSoundNodeEvents");function ia(t,e){return new Promise(async(i,o)=>{if(!t.offlineProvider||!Wo.Database.IDBStorageEnabled)return(0,te.CreateSoundBufferAsync)(e).then(r=>i(r)).catch(r=>o(r));t.offlineProvider.loadFile(e,r=>{(0,te.CreateSoundBufferAsync)(r).then(a=>i(a)).catch(a=>o(a))},void 0,()=>{o(null)},!0)})}n(ia,"loadSoundBuffer");function Li(t,e){if(!t.soundRelativePath||!t.sound)return;e.onSoundLoadedObservable=new Xo.Observable;let i=ta(t.soundRelativePath,{spatialAutoUpdate:!1});i._initAsync(t.sound.buffer,{spatialAutoUpdate:!0}).then(()=>{i.volume=t.volume,i._isSpatial=t.sound._isSpatial,i._isSpatial&&(i.spatial.attach(e),i.spatial.maxDistance=t.sound.spatial.maxDistance,i.spatial.panningModel=t.sound.spatial.panningModel,i.spatial.distanceModel=t.sound.spatial.distanceModel),e.sound=i,e.soundRelativePath=t.soundRelativePath,e.autoUpdateSpatial=t.autoUpdateSpatial,xe.push(e),Ho(e.getScene()),e.onSoundLoadedObservable.notifyObservers(e)}),ko(e),Uo(e,i)}n(Li,"configureSourceNodeFrom");function Uo(t,e){Object.defineProperty(t,"volume",{get:n(()=>e.volume,"get"),set:n(i=>{e.volume=i},"set")}),Object.defineProperty(t,"playbackRate",{get:n(()=>e.playbackRate,"get"),set:n(i=>{e.playbackRate=i},"set")}),t.isPaused=()=>e.state===rt.SoundState.Paused,t.isPlaying=()=>e.state===rt.SoundState.Started,t.isStopped=()=>e.state===rt.SoundState.Stopped,t.pause=()=>e.pause(),t.resume=()=>e.resume(),t.stop=i=>e.stop(i),t.play=i=>e.play(i),t.setVolume=(i,o)=>e.setVolume(i,o),t.getClassName=()=>"SoundNode",t.setSoundSpatial=i=>new Promise(o=>{e._isSpatial=i,setTimeout(()=>{i&&e.spatial.attach(t),o()})}),t.cloneAsync=async(i,o,r)=>new Promise(a=>{let l=t.clone(i,o,r);Li(t,l),l.onSoundLoadedObservable.addOnce(()=>{setTimeout(()=>a(l))})})}n(Uo,"configureSoundNodePrototype");function jo(){Bo||(Bo=!0,(0,$o.AddParser)("SoundNode",(t,e,i,o)=>{t.transformNodes?.forEach(r=>{if(!r.isSoundNode)return;let a=i.transformNodes?.find(l=>l.id===r.id);if(a&&r.soundRelativePath){let l=`${o}${r.soundRelativePath}`;e.addPendingData(l),bi.has(l)||bi.set(l,ia(e,l)),bi.get(l).then(s=>{(0,te.CreateSoundAsync)(r.soundRelativePath,s,{spatialAutoUpdate:!1}).then(c=>{if(e.removePendingData(l),a.isDisposed())return c.dispose();c.volume=r.volume,c._isSpatial=r.isSpatial,r.isSpatial&&(c.spatial.attach(a),c.spatial.maxDistance=r.maxDistance,c.spatial.panningModel=r.panningModel,c.spatial.distanceModel=r.distanceModel),a.sound=c,a.soundRelativePath=r.soundRelativePath,a.autoUpdateSpatial=r.autoUpdateSpatial,xe.push(a),ko(a),Uo(a,c),Ho(e)})})}})}))}n(jo,"registerAudioParser");var Zo=require("babylonjs");function Le(t){let e=new Set;[...t.transformNodes,...t.meshes].forEach(o=>{if(o.metadata?.isStaticGroup){let r=o.getDescendants(!1);r.push(o),r.forEach(a=>{if((ie(a)||J(a)&&!a.isWorldMatrixFrozen)&&a.billboardMode===Zo.AbstractMesh.BILLBOARDMODE_NONE&&a.freezeWorldMatrix(),ie(a)){let l=a.material;l&&!l.isFrozen&&!e.has(l)&&(e.add(l),l.onBindObservable.addOnce(()=>{l.freeze()}))}})}})}n(Le,"configureTransformNodes");var Ve=class{constructor(e,i){this.entries=e;this.namingId=i}entries;namingId;static{n(this,"AdvancedAssetContainerInstantiatedEntries")}get rootNodes(){return this.entries.rootNodes}get skeletons(){return this.entries.skeletons}get animationGroups(){return this.entries.animationGroups}dispose(){this.entries.dispose()}getRootNodeByName(e){let i=`${e}-${this.namingId}`;return this.entries.rootNodes.find(o=>o.name===i)??null}getNodeByName(e){let i=`${e}-${this.namingId}`;for(let o of this.entries.rootNodes){let r=this._recursivelyGetNodeByName(i,o);if(r)return r}return null}_recursivelyGetNodeByName(e,i){if(i.name===e)return i;for(let o of i.getDescendants(!0)){let r=this._recursivelyGetNodeByName(e,o);if(r)return r}return null}getScriptByClassByObjectName(e,i){let o=this.getNodeByName(e);if(o){let r=Ce(o,i);if(r?.length===1)return r[0]}return null}};var Ci=require("babylonjs"),Fe=class{static{n(this,"AdvancedAssetContainer")}container;_rootUrl;_scriptsMap;_originalDescendants=[];_nodesMap=new Map;_animationGroupsMap=new Map;constructor(e,i,o){this.container=e,this._rootUrl=i,this._scriptsMap=o,e.populateRootNodes(),e.rootNodes.forEach(r=>{this._originalDescendants.push(r,...r.getDescendants(!1))}),e.animationGroups.forEach(r=>{this._animationGroupsMap.set(r.name,r)}),this._originalDescendants.forEach(r=>{this._nodesMap.set(r,{node:r,metadata:yi(r.metadata)})})}removeDefault(){this.container.getNodes().forEach(e=>{H.get(e)?.forEach(o=>{nt(e,o)})}),this.container.removeAllFromScene()}getRootNodeByName(e){return this.container.rootNodes.find(i=>i.name===e)??null}getScriptByClassByObjectName(e,i){let o=this.container.getNodes();for(let r of o)if(r.name===e){let a=Ce(r,i);if(a?.length===1)return a[0]}return null}instantiate(e){let i=Ci.Tools.RandomId(),o=n(s=>s,"nameFunction"),r=this.container.instantiateModelsToScene(o,!1,{...e,predicate:n(s=>(s.name=`${s.name}@editor-tools@${i}_${s.id}`,e?.predicate?.(s)??!0),"predicate")}),a=new Ve(r,i);[...this.container.transformNodes,...this.container.meshes,...this.container.lights,...this.container.cameras,...this.container.animationGroups,...this.container.skeletons].forEach(s=>{let c=s.name.split("@editor-tools@");s.name=c[0]}),r.animationGroups.forEach(s=>{let c=s.name.split("@editor-tools@");s.name=`${c[0]}-${i}`});let p=[];return r.rootNodes.forEach(s=>{p.push(s,...s.getDescendants(!1))}),p.forEach(s=>{let c=s.name.split("@editor-tools@"),m=c[1].split("_").pop();s.name=`${c[0]}-${i}`;let h=this._originalDescendants.find(d=>d.id===m);re(h)&&J(s)&&Li(h,s),s.id=Ci.Tools.RandomId(),s.metadata=yi(this._nodesMap.get(h).metadata),s.metadata??={},s.metadata.originalId=m,p.forEach(d=>{d.metadata.scripts?.forEach(f=>{Object.keys(f.values||{}).forEach(g=>{let b=f.values[g];if(b.type==="entity"){b.value===m&&(b.value=s.id),b.value===h.name&&(b.value=s.name);let C=this._animationGroupsMap.get(b.value);C&&(b.value=`${C.name}-${i}`)}})})})}),p.forEach(s=>{B(this.container.scene,s,this._scriptsMap,this._rootUrl)}),Le(this.container.scene),a}};var Yo=require("babylonjs"),qo=require("babylonjs");async function Qo(t,e,i){let o=i.iblIntensity,r=i.environmentIntensity,l=t.split("/").pop().replace(".scene",".babylon"),p=await(0,qo.LoadAssetContainerAsync)(l,i,{rootUrl:e,pluginExtension:".babylon"});return Yo.SceneLoaderFlags.ForceFullSceneLoadingForIncremental&&i.meshes.forEach(s=>V(s)&&s._checkDelayState()),p.addAllToScene(),i.iblIntensity=o,i.environmentIntensity=r,Le(i),p}n(Qo,"preloadSceneScriptAsset");async function Jo(t,e){return z(`${e}${t}`)}n(Jo,"preloadCommonScriptAsset");var I=new Map,Ne=new Map;function oa(t,e){Ne.has(t)&&console.warn(`A parser for the extension '${t}' was already registered. It will be overwritten.`),Ne.set(t,e)}n(oa,"registerScriptAssetParser");async function Di(t,e,i){[e,...e.transformNodes,...e.meshes,...e.lights,...e.cameras].filter(p=>p.metadata?.scripts?.length).map(p=>p.metadata.scripts).flat().forEach(p=>{if(i[p.key]?.default?._SceneAssets?.forEach(c=>{I.get(c.sceneName)||I.set(c.sceneName,null)}),p.values)for(let c in p.values){if(!p.values.hasOwnProperty(c))continue;let m=p.values[c];m.type==="asset"&&m.value&&!I.get(m.value)&&I.set(m.value,null)}});let a=0;for(let p of I.values())p===null&&++a;if(a===0)return a;let l=[];return I.forEach((p,s)=>{I.get(s)||l.push(new Promise(async c=>{try{let m=s.split(".").pop();switch(m){case"scene":let h=await Qo(s,t,e);e.onDisposeObservable.addOnce(()=>{h.dispose(),I.delete(s)}),I.set(s,new Fe(h,t,i));break;default:if(Ne.has(m)){let d=Ne.get(m);I.set(s,await d({key:s,rootUrl:t,scene:e}));break}else I.set(s,await Jo(s,t));break}}catch(m){console.error(m)}c()}))}),await Promise.all(l),a}n(Di,"_preloadScriptsAssets");var er=require("babylonjs"),at=require("babylonjs"),tr=require("babylonjs"),st=require("babylonjs"),ir=require("babylonjs"),or=require("babylonjs-gui");function _i(t,e,i,o,r){let a=o.constructor;if(!a)return;a._NodesFromScene?.forEach(s=>{o[s.propertyKey.toString()]=ui(s.nodeName,t)}),a._ComponentsFromScene?.length&&t.getEngine().onBeginFrameObservable.addOnce(()=>{a._ComponentsFromScene?.forEach(s=>{let c=[];if([t,...t.transformNodes,...t.meshes,...t.lights,...t.cameras].forEach(h=>{let d=wi(h,s.componentConstructor);d&&c.push(d)}),c.length>1)throw new Error(`Multiple components of type ${a._ComponentsFromScene[0].componentConstructor.name} found in scene for property "${a._ComponentsFromScene[0].propertyKey.toString()}".`);o[s.propertyKey.toString()]=c[0]??null})}),a._NodesFromDescendants?.forEach(s=>{let c=e.getDescendants?.(s.directDescendantsOnly,m=>m.name===s.nodeName)[0];o[s.propertyKey.toString()]=c??null}),a._AnimationGroups?.forEach(s=>{o[s.propertyKey.toString()]=t.getAnimationGroupByName(s.animationGroupName)}),a._SoundsFromScene?.forEach(s=>{let c=ui(s.soundName,t);c&&re(c)&&(o[s.propertyKey.toString()]=c??null)}),(a._GuiFromAsset??[]).map(async s=>{let c=`${r}assets/${s.pathInAssets}`;try{let m=await z(c),h=or.AdvancedDynamicTexture.CreateFullscreenUI(m.name,!0,t);h.parseSerializedObject(m.content,!1),o[s.propertyKey.toString()]=h,s.onGuiCreated?.(o,h)}catch(m){throw console.error(`Failed to load GUI from asset: ${c}`),m}}),a._ParticleSystemsFromScene?.forEach(s=>{let c=t.particleSystems?.find(m=>m.name!==s.particleSystemName?!1:s.directDescendantsOnly?m.emitter===e:m);o[s.propertyKey.toString()]=c}),(a._VisibleInInspector??[]).forEach(s=>{let c=s.propertyKey.toString(),m=i.values;if(!m)throw new Error(`No values found for script with key "${i.key}".`);if(m.hasOwnProperty(c)&&m[c].hasOwnProperty("value")){let h=m[c].value;switch(s.configuration.type){case"number":case"boolean":case"keymap":case"string":o[c]=h;break;case"vector2":o[c]=st.Vector2.FromArray(h);break;case"vector3":o[c]=st.Vector3.FromArray(h);break;case"color3":o[c]=at.Color3.FromArray(h);break;case"color4":o[c]=at.Color4.FromArray(h);break;case"entity":switch(s.configuration.entityType){case"node":case"sound":o[c]=be(h,t)??null;break;case"animationGroup":o[c]=t.getAnimationGroupByName(h)??null;break;case"particleSystem":o[c]=t.particleSystems?.find(f=>f.id===h)??null;break}break;case"texture":h&&(o[c]=tr.Texture.Parse(h,t,r));break;case"asset":if(h){let f=s.configuration.assetType,S=I.get(h);switch(f){case"json":case"gui":case"scene":case"navmesh":case"cinematic":o[c]=S;break;case"ragdoll":o[c]=vi(S);break;case"nodeParticleSystemSet":let g=ir.NodeParticleSystemSet.Parse(S);o[c]=g;break;case"material":o[c]=er.Material.Parse(S,t,r);break}}}}});let l=null,p=null;if(a._PointerEvents?.length){if(a._PointerEvents.find(m=>m.options.mode==="attachedMeshOnly")&&!ie(e))throw new Error('@onPointerEvent with mode "attachedMeshOnly" can only be used on scripts attached to meshes (extends AbstractMesh).');if(a._PointerEvents.find(m=>m.options.mode!=="global")&&!ce(e))throw new Error('@onPointerEvent with mode different from "global" can be used only on scripts attached to Node: Mesh, Light, Camera, TransformNode.');l=t.onPointerObservable.add(m=>{let h=null;a._PointerEvents.forEach(d=>{if(!d.eventTypes.includes(m.type))return;let f=d.propertyKey.toString();if(d.options.mode==="global")return o[f]?.(m);h=m.pickInfo,h||(h=t.pick(t.pointerX,t.pointerY,g=>g.isVisible&&g.isPickable&&g.isEnabled(!0)&&!g._masterMesh,!1));let S=h.pickedMesh;if(S&&(d.options.mode==="attachedMeshOnly"&&S===e||d.options.mode==="includeDescendants"&&ce(e)&&[e,...e.getDescendants(!1)].find(C=>C===S)))return o[f]?.(m)})})}if(a._KeyboardEvents?.length&&(p=t.onKeyboardObservable.add(s=>{a._KeyboardEvents.forEach(c=>{c.eventTypes.includes(s.type)&&o[c.propertyKey.toString()]?.(s)})})),a._SpritesFromSpriteManager?.length){let s=e;if(!J(s)||!s.isSpriteManager)return console.error("@spriteFromSpriteManager decorator can only be used on SpriteManagerNode.");if(!s.spriteManager)return console.error(`SpriteManagerNode "${s.name}" has no sprite manager assigned.`);a._SpritesFromSpriteManager?.forEach(c=>{let m=s.spriteManager?.sprites.find(h=>h.name===c.spriteName)||null;o[c.propertyKey.toString()]=m})}if(a._AnimationsFromSprite?.length){if(!Lt(e))return console.error("@animationFromSprite decorator can only be used in scripts attached on Sprite.");let s=e.metadata?.spriteAnimations;if(!s?.length)return console.error(`Sprite "${e.name}" has no sprite animations assigned.`);a._AnimationsFromSprite.forEach(c=>{let m=s.find(h=>h.name===c.animationName);m?o[c.propertyKey.toString()]=m??null:console.warn(`Sprite animation named "${c.animationName}" not found on sprite "${e.name}".`)})}return a._SceneAssets?.forEach(s=>{o[s.propertyKey.toString()]=I.get(s.sceneName)}),{observers:{pointerObserver:l,keyboardObserver:p}}}n(_i,"applyDecorators");function B(t,e,i,o){e.metadata?.scripts&&(e.metadata.scripts?.forEach(r=>{if(!r.enabled)return;let a=i[r.key];if(!a)return;let l=a,p={};if(a.default){l=new a.default(e);let s=_i(t,e,r,l,o);Object.assign(p,s?.observers??{})}l.onStart&&(p.onStartObserver=t.onBeforeRenderObservable.addOnce(()=>l.onStart(e))),l.onUpdate&&(p.onUpdateObserver=t.onBeforeRenderObservable.add(()=>l.onUpdate(e))),Pi(e,l,r.key,p)}),e.metadata.scripts=void 0)}n(B,"_applyScriptsForObject");function ra(t,e,i){if(i??=t.getScene?.(),!i)throw new Error("Cannot apply script on object: no scene available.");let o=new e(t),r={};return _i(i,t,{values:{}},o,""),o.onStart&&(r.onStartObserver=i.onBeforeRenderObservable.addOnce(()=>o.onStart())),o.onUpdate&&i.onBeforeRenderObservable.add(()=>o.onUpdate()),Pi(t,o,"runtime",r),o}n(ra,"applyScriptOnObject");var H=new Map;function Pi(t,e,i,o){let r={key:i,observers:o,instance:e};H.has(t)?H.get(t).push(r):H.set(t,[r]),(ce(t)||xt(t)||yt(t)||re(t))&&t.onDisposeObservable.addOnce((()=>{H.get(t)?.slice()?.forEach(l=>{nt(t,l)}),H.delete(t)}))}n(Pi,"_registerScriptInstance");function nt(t,e){e.observers.onStartObserver?.remove(),e.observers.onUpdateObserver?.remove(),e.observers.pointerObserver?.remove(),e.observers.keyboardObserver?.remove();try{e.instance.onStop?.(t)}catch(r){console.error(`Failed to call onStop for script ${e.key} on object ${t}`,r)}let i=H.get(t),o=i?.indexOf(e)??-1;o!==-1&&i?.splice(o,1)}n(nt,"_removeRegisteredScriptInstance");function Ce(t,e){return H.get(t)?.filter(r=>r.instance.constructor===e)?.map(r=>r.instance)??null}n(Ce,"getAllScriptsByClassForObject");function wi(t,e){return Ce(t,e)?.[0]??null}n(wi,"getScriptByClassForObject");var nr=require("babylonjs"),rr=!1;function ar(){rr||(rr=!0,(0,nr.AddParser)("MeshEditorPlugin",(t,e,i,o)=>{t.meshes?.forEach(r=>{r.instances?.forEach(a=>{let l=i.meshes?.find(p=>p.id===a.id);l&&a.billboardMode!==void 0&&(l.billboardMode=a.billboardMode)})})}))}n(ar,"registerMeshParser");var sr=!1;function na(t){sr=t}n(na,"setUseKtx2CompressedTextures");function Ge(){return sr}n(Ge,"isUsingKtx2CompressedTextures");function lt(t){return`${t.substring(0,t.lastIndexOf("."))}.ktx2`}n(lt,"_getKtx2TextureName");function aa(t){t.setCompressedTextureExclusions([".env",".hdr",".dds"]),t.setTextureFormatToUse(["-dxt.ktx","-astc.ktx","-pvrtc.ktx","-etc1.ktx","-etc2.ktx"])}n(aa,"configureEngineToUseCompressedTextures");function ct(t,e){t._excludedCompressedTextures&&!t._excludedCompressedTextures?.includes(e)&&t._excludedCompressedTextures?.push(e)}n(ct,"addExcludedCompressedTexture");function sa(t,e,i){e.loadingTexturesQuality!==t&&(e.loadingTexturesQuality=t,e.textures.forEach(o=>{if(!Oe(o)||!o.url)return;let r=pt(o,e);!r||o.url.includes(r)||o.updateURL(i+r)}))}n(sa,"applyTexturesQuality");function pt(t,e){if(e.loadingTexturesQuality==="high"||!t.metadata?.baseSize)return t.name;let i=t.metadata.baseSize.width,o=t.metadata.baseSize.height,r=i===F(i)||o===F(o),a="";switch(e.loadingTexturesQuality){case"medium":let d=i*.66>>0,f=o*.66>>0;r&&(d=F(d),f=F(f)),a=`_${d}_${f}`;break;case"low":case"very-low":let S=i*.33>>0,g=o*.33>>0;r&&(S=F(S),g=F(g)),a=`_${S}_${g}`;break}let l=t.name;if(!l||!a)return t.name;let p=l.split("/"),s=p.pop();if(!s)return t.name;let c=s.split(".").pop(),h=`${s.replace(`.${c}`,"")}${a}.${c}`;return p.push(h),p.join("/")}n(pt,"getTextureUrl");var Oi=require("babylonjs"),lr=!1;function cr(){if(lr)return;lr=!0;let t=Oi.SerializationHelper._TextureParser;Oi.SerializationHelper._TextureParser=(e,i,o)=>{Ge()&&(e.name&&(e.name=lt(e.name)),e.url&&(e.url=lt(e.url)));let r=pt(e,i);if(!r)return t(e,i,o);let a=e.name;e.name=r;let l=t(e,i,o);return l&&(l.name=a),l}}n(cr,"registerTextureParser");function Ei(t){if(!Array.isArray(t.frames)){let e=[];for(let i of Object.keys(t.frames))e.push({filename:i,...t.frames[i]});t.frames=e}}n(Ei,"normalizeAtlasJson");function la(t,e,i){let r=(t.metadata?.spriteAnimations??[]).find(a=>a.name===e);if(!r)return console.error(`Animation with name "${e}" not found on sprite.`);t.playAnimation(r.from,r.to,r.loop,r.delay,i)}n(la,"playSpriteAnimationFromName");var mr=require("babylonjs"),hr=require("babylonjs"),dr=require("babylonjs"),fr=require("babylonjs"),Ai=require("babylonjs"),De=require("babylonjs"),ur=require("babylonjs"),pr=!1;function gr(){pr||(pr=!0,(0,ur.AddParser)("SpriteMapNode",(t,e,i,o)=>{t.transformNodes?.forEach(r=>{if(!r.isSpriteMap)return;let a=i.transformNodes?.find(s=>s.id===r.id);if(!a)return;a.isSpriteMap=r.isSpriteMap;let l=`${o}${r.atlasJsonRelativePath}`;e.addPendingData(l);let p=new dr.WebRequest;p.open("GET",l),p.send(),p.addEventListener("load",()=>{e.removePendingData(l);let s=JSON.parse(p.responseText);Ei(s);let c=`${mr.Tools.GetFolderPath(l)}${s.meta.image}`,m=new Ai.Texture(c,e,!1,!1,Ai.Texture.NEAREST_NEAREST,null,null,null,!1,hr.Engine.TEXTUREFORMAT_RGBA),h=new fr.SpriteMap(a.name,s,m,{layerCount:r.options.layerCount,stageSize:De.Vector2.FromArray(r.options.stageSize??[10,1]),outputSize:De.Vector2.FromArray(r.options.outputSize??[100,100]),colorMultiply:De.Vector3.FromArray(r.options.colorMultiply??[1,1,1]),flipU:!0},e);r.getClassName=()=>"SpriteMapNode",r.tiles.forEach(f=>{for(let S=0,g=f.repeatCount.x+1;S<g;++S)for(let b=0,C=f.repeatCount.y+1;b<C;++b){let _=S*(f.repeatOffset.x+1),x=b*(f.repeatOffset.y+1);h.changeTiles(f.layer,new De.Vector2(f.position.x+_,(h.options.stageSize?.y??0)-1-f.position.y-x),f.tile)}});let d=h._output;d.parent=a,a.spriteMap=h})})}))}n(gr,"registerSpriteMapParser");var Sr=require("babylonjs"),yr=require("babylonjs"),mt=require("babylonjs"),br=require("babylonjs"),vr=!1;function xr(){if(vr)return;vr=!0,(0,br.RegisterShadowGeneratorSceneComponent)(yr.ShadowGenerator);let t=(0,mt.GetParser)(Sr.SceneComponentConstants.NAME_SHADOWGENERATOR);(0,mt.AddParser)("ShadowGeneratorEditorPlugin",(e,i,o,r)=>{let a=new Map;e.shadowGenerators?.forEach(l=>{if(a.set(l.id,l.mapSize),i.loadingShadowsQuality!=="high"){switch(i.loadingShadowsQuality){case"medium":l.mapSize=l.mapSize*.5;break;case"low":l.mapSize=l.mapSize*.25;break;case"very-low":l.mapSize=l.mapSize*.125;break}l.mapSize=Math.max(128,F(l.mapSize))}}),t?.(e,i,o,r),i.lights.forEach(l=>{let p=l.getShadowGenerator();if(p?.getShadowMap()){let c=p.id,m=a.get(c);m&&(p.originalMapSize=m)}})})}n(xr,"registerShadowGeneratorParser");var Dr=require("babylonjs"),_r=require("babylonjs"),wr=require("babylonjs"),Ti=require("babylonjs"),Pr=require("babylonjs");function Lr(t,e){e?.fogEnabled!==void 0&&(t.fogEnabled=e?.fogEnabled),e?.blendMode!==void 0&&(t.blendMode=e?.blendMode),e?.disableDepthWrite!==void 0&&(t.disableDepthWrite=e?.disableDepthWrite),e?.pixelPerfect!==void 0&&(t.pixelPerfect=e?.pixelPerfect),e?.useLogarithmicDepth!==void 0&&(t.useLogarithmicDepth=e?.useLogarithmicDepth),e?.metadata!==void 0&&(t.metadata=e?.metadata);for(let i of e?.sprites??[]){let o=_r.Sprite.Parse(i,t);o.uniqueId=i.uniqueId,o.metadata=i.metadata}}n(Lr,"parseSerializedSpriteManager");var Cr=!1;function Or(){Cr||(Cr=!0,(0,Pr.AddParser)("SpriteManagerNode",(t,e,i,o)=>{t.transformNodes?.forEach(r=>{if(!r.isSpriteManager)return;let a=i.transformNodes?.find(p=>p.id===r.id);if(!a)return;let l=e.getEngine();if(a.isSpriteManager=r.isSpriteManager,r.atlasJsonRelativePath){let p=`${o}${r.atlasJsonRelativePath}`;e.addPendingData(p);let s=new wr.WebRequest;s.open("GET",p),s.send(),s.addEventListener("load",()=>{e.removePendingData(p);let c=JSON.parse(s.responseText),m=`${Dr.Tools.GetFolderPath(p)}${c.meta.image}`;ct(l,m);let h=new Ti.SpriteManager(a.name,m,1e3,64,e,void 0,void 0,!0,c);a.spriteManager=h,a.getClassName=()=>"SpriteManagerNode",r.spriteManager&&Lr(h,r.spriteManager)})}else if(r.spriteManager?.textureUrl){ct(l,r.spriteManager.textureUrl);let p=`${o}${r.spriteManager.textureUrl}`,s=new Ti.SpriteManager(a.name,p,1e3,{width:r.spriteManager.cellWidth,height:r.spriteManager.cellHeight},e,void 0,void 0,!1);a.spriteManager=s,a.getClassName=()=>"SpriteManagerNode",r.spriteManager&&Lr(s,r.spriteManager)}})}))}n(Or,"registerSpriteManagerParser");var Ar=require("babylonjs"),Tr=require("babylonjs"),Er=!1;function Ir(){Er||(Er=!0,(0,Tr.AddParser)("MorphTargetManagerEditorPlugin",(t,e,i,o)=>{t.morphTargetManagers.forEach(r=>{let l=i.meshes.find(c=>c.id===r.meshId)?.morphTargetManager;if(!l||r.targets.find(c=>!c.delayLoadingFile))return;let s=[];r.targets.forEach(c=>{if(!c.delayLoadingFile)return s.push(Promise.resolve(null));let m=`${o}${c.delayLoadingFile}`;e.addPendingData(m);let h=new Ar.WebRequest;h.responseType="arraybuffer",h.open("GET",m),h.send(),s.push(new Promise(d=>{h.addEventListener("load",()=>{e.removePendingData(m),d(h.response)})}))}),Promise.all(s).then(c=>{for(let m=0,h=l.numTargets;m<h;++m){let d=l.getTarget(m),f=r.targets[m],S=c[m];if(f.positionsCount){let g=new Float32Array(S,f.positionsOffset,f.positionsCount);d._positions=g,d.setPositions(g)}if(f.normalsCount){let g=new Float32Array(S,f.normalsOffset,f.normalsCount);d._normals=g,d.setNormals(g)}if(f.tangentsCount){let g=new Float32Array(S,f.tangentsOffset,f.tangentsCount);d._tangents=g,d.setTangents(g)}if(f.uvsCount){let g=new Float32Array(S,f.uvsOffset,f.uvsCount);d._uvs=g,d.setUVs(g)}if(f.uv2sCount){let g=new Float32Array(S,f.uv2sOffset,f.uv2sCount);d._uv2s=g,d.setUV2s(g)}}for(let m=0,h=l.numTargets;m<h;++m)l.getTarget(m)._onDataLayoutChanged.notifyObservers()})})}))}n(Ir,"registerMorphTargetManagerParser");var Rr=require("babylonjs"),Vr=require("babylonjs"),Mr=!1;function Fr(){Mr||(Mr=!0,(0,Rr.AddParser)("NodeParticleSystemSetEditorPlugin",(t,e,i,o)=>{t.meshes?.forEach(r=>{if(!r.isNodeParticleSystemMesh)return;let a=i.meshes?.find(l=>l.id===r.id);a&&(r.nodeParticleSystemSet.blocks?.forEach(l=>{l.url&&(l.url=`${o}${l.url}`)}),a.nodeParticleSystemSet=Vr.NodeParticleSystemSet.Parse(r.nodeParticleSystemSet),a.nodeParticleSystemSet.id=r.nodeParticleSystemSet.id,a.nodeParticleSystemSet.uniqueId=r.uniqueId,e.addPendingData(r.id),a.nodeParticleSystemSet.buildAsync(e,!1).then(l=>{e.removePendingData(r.id),a.particleSystemSet=l,l.systems.forEach(p=>{if(bt(p)){let s=p._sizeCreation.process;s&&(p._sizeCreation.process=(c,m)=>{s(c,m),c.scale.x*=100,c.scale.y*=100})}}),l.emitterNode=a,l.start()}))})}))}n(Fr,"registerNodeParticleSystemSetParser");var Nr=require("babylonjs");function Gr(t,e){e??=new Nr.ClusteredLightContainer("Clustered Light Container",[],t);let i=t.metadata?.clusteredLight;return i&&(i.lights.length>0&&(e.horizontalTiles=i.horizontalTiles,e.verticalTiles=i.verticalTiles,e.depthSlices=i.depthSlices,e.maxRange=i.maxRange),i.lights.forEach(o=>{let r=t.getLightById(o);r&&e?.addLight(r)})),e}n(Gr,"configureLights");var Hr=require("babylonjs"),Ii=require("babylonjs"),kr=require("babylonjs"),Ur=require("babylonjs"),Br=new Map;async function zr(t,e){let i=t.getWaitingItemsCount();for(;!t.isDisposed&&(!t.isReady()||t.getWaitingItemsCount()>0);){await new Promise(r=>setTimeout(r,150));let o=i-t.getWaitingItemsCount();o===i&&t.textures.forEach(r=>{r.delayLoadState===Ii.Constants.DELAYLOADSTATE_NONE&&(r.delayLoadState=Ii.Constants.DELAYLOADSTATE_LOADED)}),e(o/i)}}n(zr,"waitForWaitingItems");async function ca(t,e,i,o,r){i.loadingQuality=r?.quality??"high",i.loadingTexturesQuality=r?.texturesQuality??i.loadingQuality,i.loadingShadowsQuality=r?.shadowsQuality??i.loadingQuality,i.loadingLodsQuality=r?.lodsQuality??i.loadingQuality,ar(),jo(),cr(),xr(),Ir(),gr(),Or(),Fr();let a=Br.get(i)??{};if(Br.set(i,a),await(0,kr.AppendSceneAsync)(`${t}${e}`,i,{pluginExtension:".babylon",onProgress:n(p=>{let s=Math.min(p.loaded/p.total*.5);r?.onProgress?.(s)},"onProgress")}),await zr(i,p=>{r?.onProgress?.(.5+p*.25)}),!r?.skipAssetsPreload){let p=0;do p=await Di(t,i,o);while(p!==0&&!i.isDisposed)}Ur.SceneLoaderFlags.ForceFullSceneLoadingForIncremental&&i.meshes.forEach(p=>V(p)&&p._checkDelayState());let l=Gr(i,a.clusteredLightContainer);a.clusteredLightContainer=l,await zr(i,p=>{r?.onProgress?.(.75+p*.25)}),r?.onProgress?.(1),_t(i),wt(i.loadingLodsQuality,i),Pt(i),Ke(i),i.metadata?.rendering&&(Vo(i,i.metadata.rendering),i.activeCamera&&fi(i.activeCamera,t,r?.postProcessConfiguration)),i.metadata?.physicsGravity&&i.getPhysicsEngine()?.setGravity(Hr.Vector3.FromArray(i.metadata?.physicsGravity)),B(i,i,o,t),i.transformNodes.forEach(p=>{B(i,p,o,t)}),i.meshes.forEach(p=>{Ro(p),B(i,p,o,t)}),i.lights.forEach(p=>{B(i,p,o,t)}),l.lights.forEach(p=>{B(i,p,o,t)}),i.cameras.forEach(p=>{B(i,p,o,t)}),i.spriteManagers?.forEach(p=>{p.sprites.forEach(s=>{B(i,s,o,t)})}),Le(i)}n(ca,"loadScene");var Wr=require("babylonjs");async function pa(t,e,i){let o=await z(t+e),a=Wr.Tools.Instantiate(o.customType).Parse(o,i,t);return a.id=o.id,a.uniqueId=o.uniqueId,a}n(pa,"loadMaterialFromFile");function ma(t){return Promise.all(t.materials.map(async e=>{let i=e.getBindedMeshes();await Promise.all(i.map(async o=>{Pe(o)||await e.forceCompilationAsync(o,{clipPlane:!!t.clipPlane,useInstances:o.hasInstances})}))}))}n(ma,"forceCompileAllSceneMaterials");var q=require("babylonjs");function Be(t){if(!isNaN(parseFloat(t))&&isFinite(t))return q.Animation.ANIMATIONTYPE_FLOAT;switch(t?.getClassName?.()){case"Vector2":return q.Animation.ANIMATIONTYPE_VECTOR2;case"Vector3":return q.Animation.ANIMATIONTYPE_VECTOR3;case"Quaternion":return q.Animation.ANIMATIONTYPE_QUATERNION;case"Color3":return q.Animation.ANIMATIONTYPE_COLOR3;case"Color4":return q.Animation.ANIMATIONTYPE_COLOR4;case"Size":return q.Animation.ANIMATIONTYPE_SIZE;case"Matrix":return q.Animation.ANIMATIONTYPE_MATRIX}return null}n(Be,"getAnimationTypeForObject");var Xr=require("babylonjs");function ha(t){return function(e,i){let o=e.constructor;o._NodesFromScene??=[],o._NodesFromScene.push({propertyKey:i,nodeName:t})}}n(ha,"nodeFromScene");function da(t){return function(e,i){let o=e.constructor;o._ComponentsFromScene??=[],o._ComponentsFromScene.push({propertyKey:i,componentConstructor:t})}}n(da,"componentFromScene");function fa(t,e=!1){return function(i,o){let r=i.constructor;r._NodesFromDescendants??=[],r._NodesFromDescendants.push({propertyKey:o,nodeName:t,directDescendantsOnly:e})}}n(fa,"nodeFromDescendants");function ua(t){return function(e,i){let o=e.constructor;o._AnimationGroups??=[],o._AnimationGroups.push({animationGroupName:t,propertyKey:i})}}n(ua,"animationGroupFromScene");function ga(t){return function(e,i){let o=e.constructor;o._SceneAssets??=[],o._SceneAssets.push({sceneName:t,propertyKey:i})}}n(ga,"sceneAsset");function va(t,e){return function(i,o){let r=i.constructor;r._GuiFromAsset??=[],r._GuiFromAsset.push({propertyKey:o,pathInAssets:t,onGuiCreated:e})}}n(va,"guiFromAsset");function Sa(t){return function(e,i){let o=e.constructor;o._SoundsFromScene??=[],o._SoundsFromScene.push({propertyKey:i,soundName:t})}}n(Sa,"soundFromScene");function ya(t,e=!1){return function(i,o){let r=i.constructor;r._ParticleSystemsFromScene??=[],r._ParticleSystemsFromScene.push({propertyKey:o,particleSystemName:t,directDescendantsOnly:e})}}n(ya,"particleSystemFromScene");function ba(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"boolean"}})}}n(ba,"visibleAsBoolean");function xa(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"string"}})}}n(xa,"visibleAsString");function La(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"number"}})}}n(La,"visibleAsNumber");function Ca(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"vector2"}})}}n(Ca,"visibleAsVector2");function Da(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"vector3"}})}}n(Da,"visibleAsVector3");function _a(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"color3"}})}}n(_a,"visibleAsColor3");function wa(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"color4"}})}}n(wa,"visibleAsColor4");function Pa(t,e,i){return function(o,r){let a=o.constructor;a._VisibleInInspector??=[],a._VisibleInInspector.push({label:e,propertyKey:r,configuration:{...i,entityType:t,type:"entity"}})}}n(Pa,"visibleAsEntity");function Oa(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"texture"}})}}n(Oa,"visibleAsTexture");function Ea(t,e){return function(i,o){let r=i.constructor;r._VisibleInInspector??=[],r._VisibleInInspector.push({label:t,propertyKey:o,configuration:{...e,type:"keymap"}})}}n(Ea,"visibleAsKeyMap");function Aa(t,e,i){return function(o,r){let a=o.constructor;a._VisibleInInspector??=[],a._VisibleInInspector.push({label:e,propertyKey:r,configuration:{...i,assetType:t,type:"asset"}})}}n(Aa,"visibleAsAsset");function Ta(t,e){return function(i,o){let r=i.constructor;r._PointerEvents??=[],r._PointerEvents.push({propertyKey:o,options:{mode:"global",...e??{}},eventTypes:Array.isArray(t)?t:[t]})}}n(Ta,"onPointerEvent");function Ia(t){return function(e,i){let o=e.constructor;o._KeyboardEvents??=[],o._KeyboardEvents.push({propertyKey:i,eventTypes:Array.isArray(t)?t:[t]})}}n(Ia,"onKeyboardEvent");function Ma(t){return function(e,i){let o=e.constructor;o._SpritesFromSpriteManager??=[],o._SpritesFromSpriteManager.push({propertyKey:i,spriteName:t})}}n(Ma,"spriteFromSpriteManager");function Ra(t){return function(e,i){let o=e.constructor;o._AnimationsFromSprite??=[],o._AnimationsFromSprite.push({propertyKey:i,animationName:t})}}n(Ra,"animationFromSprite");var ht=require("babylonjs");function Cg(t,e){let i;return t===ht.Animation.ANIMATIONTYPE_FLOAT?i=e.value:i=e.value.clone(),{value:i,frame:e.frame,interpolation:e.interpolation,inTangent:t===ht.Animation.ANIMATIONTYPE_FLOAT?e.inTangent:e.inTangent?.clone(),outTangent:t===ht.Animation.ANIMATIONTYPE_FLOAT?e.outTangent:e.outTangent?.clone()}}n(Cg,"cloneKey");function dt(t,e){let i=e.split("."),o=t;for(let r=0;r<i.length;++r)o=o[i[r]];return o}n(dt,"getPropertyValue");function Mi(t,e,i){let o=null;t.onAnimationGroupPlayObservable.add(()=>{o=e.onAfterAnimationsObservable.add(()=>{i()})}),t.onAnimationGroupPauseObservable.add(()=>{o&&(e.onAfterAnimationsObservable.remove(o),o=null)}),t.onAnimationGroupEndObservable.add(()=>{o&&(e.onAfterAnimationsObservable.remove(o),o=null)})}n(Mi,"registerAfterAnimationCallback");var Q=require("babylonjs"),ft=require("babylonjs"),U=require("babylonjs");function Va(t,e){return{name:t.name,framesPerSecond:t.framesPerSecond,outputFramesPerSecond:t.outputFramesPerSecond,tracks:t.tracks.map(i=>{let o=null,r=null;if(i.node?(o=be(i.node,e),o||(o=e.particleSystems?.find(l=>l.id===i.node)??null)):i.defaultRenderingPipeline?o=Ee():i.volumetricLightScattering&&(o=Ot()),i.propertyPath){let l=dt(o,i.propertyPath);r=Be(l)}let a=null;return i.sound&&(a=be(i.sound,e)),{node:o,sound:a,propertyPath:i.propertyPath,defaultRenderingPipeline:i.defaultRenderingPipeline,volumetricLightScattering:i.volumetricLightScattering,animationGroupWeight:i.animationGroupWeight,animationGroup:i.animationGroup?e.getAnimationGroupByName(i.animationGroup):null,animationGroups:i.animationGroups,sounds:i.sounds,soundVolume:Ri(i.soundVolume??[],Q.Animation.ANIMATIONTYPE_FLOAT),keyFrameEvents:i.keyFrameEvents?.map(l=>{let p={...l};switch(l.data?.type){case"set-enabled":p.data={type:"set-enabled",value:l.data.value,node:be(l.data.node,e)};break;case"apply-impulse":p.data={type:"apply-impulse",radius:l.data.radius,mesh:e.getMeshById(l.data.mesh),force:U.Vector3.FromArray(l.data.force),contactPoint:U.Vector3.FromArray(l.data.contactPoint)};break}return p}),keyFrameAnimations:o&&r!==null&&Ri(i.keyFrameAnimations??[],r)}})}}n(Va,"parseCinematic");function k(t,e){if(t===null)return null;if(t!==void 0)switch(e){case Q.Animation.ANIMATIONTYPE_FLOAT:return t;case Q.Animation.ANIMATIONTYPE_VECTOR2:return U.Vector2.FromArray(t);case Q.Animation.ANIMATIONTYPE_VECTOR3:return U.Vector3.FromArray(t);case Q.Animation.ANIMATIONTYPE_QUATERNION:return U.Quaternion.FromArray(t);case Q.Animation.ANIMATIONTYPE_COLOR3:return ft.Color3.FromArray(t);case Q.Animation.ANIMATIONTYPE_COLOR4:return ft.Color4.FromArray(t);case Q.Animation.ANIMATIONTYPE_MATRIX:return U.Matrix.FromArray(t)}}n(k,"parseCinematicKeyValue");function Ri(t,e){return t?.map(i=>{let o=i.type==="key"?i:null;if(o)return{...o,value:k(o.value,e),inTangent:k(o.inTangent,e),outTangent:k(o.outTangent,e)};let r=i.type==="cut"?i:null;if(r)return{...r,key1:{...r.key1,value:k(r.key1.value,e),inTangent:k(r.key1.inTangent,e),outTangent:k(r.key1.outTangent,e)},key2:{...r.key2,value:k(r.key2.value,e),inTangent:k(r.key2.inTangent,e),outTangent:k(r.key2.outTangent,e)}};throw new Error(`Unknown key frame type: ${i.type}`)})}n(Ri,"parseKeyFrameAnimations");function $r(t,e){t.onEventObservable.notifyObservers(e.eventName)}n($r,"handleApplyEvent");function Kr(t){t.node?.setEnabled(t.value)}n(Kr,"handleSetEnabledEvent");var Vi=require("babylonjs"),jr=Vi.Vector3.Zero();function Zr(t,e){let i=e.mesh?[e.mesh]:t.meshes.filter(o=>o.physicsAggregate);e.radius&&(i=i.filter(o=>{let r=o.getBoundingInfo().boundingBox.centerWorld;return Vi.Vector3.Distance(r,e.contactPoint)<=e.radius})),i.forEach(o=>{if(o.physicsAggregate?.body){let r=e.contactPoint.subtract(o.getBoundingInfo().boundingBox.centerWorld);r.multiplyInPlace(e.force),o.physicsAggregate.body.setLinearVelocity(jr),o.physicsAggregate.body.setAngularVelocity(jr),o.physicsAggregate.body.applyImpulse(r.negateInPlace(),e.contactPoint)}})}n(Zr,"handleApplyImpulseEvent");var Yr=require("babylonjs"),qr=require("babylonjs"),ze=class extends qr.AnimationGroup{static{n(this,"Cinematic")}onEventObservable=new Yr.Observable;onEvent(e,i){this.onEventObservable.add(o=>{e===o&&i()})}};function Fi(t){return t.type==="key"}n(Fi,"isCinematicKey");function _e(t){return t.type==="cut"}n(_e,"isCinematicKeyCut");function Fa(t){return t.type==="event"}n(Fa,"isCinematicKeyEvent");function Na(t){return t.type==="group"}n(Na,"isCinematicGroup");function Ga(t){return t.type==="sound"}n(Ga,"isCinematicSound");var P=require("babylonjs"),we=require("babylonjs");function Ba(t,e,i){let o=new ze(t.name,e);return t.tracks.forEach(r=>{let a=r.animationGroup;if(a&&r.animationGroups?.length){let d=a.clone(`${a.name}-cinematic-temp`),f=e.animationGroups.indexOf(d);f!==-1&&e.animationGroups.splice(f,1),o.onAnimationEndObservable.add(()=>{a.stop(),d.stop()});let S=r.animationGroups.reduce((_,x)=>Math.min(_,x.frame),Number.MAX_VALUE)??0,g=r.animationGroups.reduce((_,x)=>Math.max(_,x.frame+x.endFrame),0)??0,b={frame:S},C=new P.Animation(d.name,"frame",60,P.Animation.ANIMATIONTYPE_FLOAT,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1);if(C.setKeys([{frame:S,value:0},{frame:g,value:g}]),r.animationGroups.forEach(_=>{C.addEvent(new we.AnimationEvent(_.frame,()=>{let x=_.repeatCount??0;if(d.to=_.endFrame,d.speedRatio=_.speed,d.stop(),d.play(x>0),d.from!==_.startFrame&&d.goToFrame(_.startFrame),x){let M=0;d.onAnimationGroupLoopObservable.add(()=>{++M,M>x&&d.stop()})}}))}),o.addTargetedAnimation(C,b),(r.animationGroupWeight?.length??0)>=2&&r.animationGroupWeight.find(x=>_e(x)?x.key1.value!==1||x.key2.value!==1:x.value!==1)){let x={weight:0},M=new P.Animation(`${d.name}-weights`,"weight",60,P.Animation.ANIMATIONTYPE_FLOAT,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1),G=[];r.animationGroupWeight.forEach(v=>{_e(v)?(G.push(v.key1),G.push(v.key2)):G.push(v)}),M.setKeys(G),o.addTargetedAnimation(M,x),Mi(o,e,()=>{d.weight=x.weight})}}let l=r.sound;if(!i?.ignoreSounds&&l&&l.sound?.buffer&&r.sounds?.length){let d={dummy:0,volume:0},f=new P.Animation(l.name,"dummy",60,P.Animation.ANIMATIONTYPE_FLOAT,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1),S=0;if(r.sounds?.forEach(g=>{let b=g.endFrame-g.startFrame;S=Math.max(S,g.frame+b),f.addEvent(new we.AnimationEvent(g.frame,C=>{let x=(C-g.frame+g.startFrame)/t.framesPerSecond;l.play({startOffset:x})},!1)),f.addEvent(new we.AnimationEvent(g.frame+b,()=>{l.stop()}))}),f.setKeys([{frame:0,value:0},{frame:S,value:S}]),o.addTargetedAnimation(f,d),(r.soundVolume?.length??0)>=2){let g=new P.Animation(l.name,"volume",60,P.Animation.ANIMATIONTYPE_FLOAT,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1),b=[];r.soundVolume.forEach(C=>{_e(C)?(b.push(C.key1),b.push(C.key2)):b.push(C)}),g.setKeys(b),o.addTargetedAnimation(g,d),Mi(o,e,()=>{l.volume=d.volume})}}if(r.keyFrameEvents){let d={dummy:0},f=new P.Animation("events","dummy",60,P.Animation.ANIMATIONTYPE_FLOAT,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1),S=0;r.keyFrameEvents?.forEach(g=>{S=Math.max(S,g.frame),f.addEvent(new we.AnimationEvent(g.frame,()=>{switch(g.data?.type){case"event":$r(o,g.data);break;case"set-enabled":Kr(g.data);break;case"apply-impulse":Zr(e,g.data);break}}))}),f.setKeys([{frame:0,value:0},{frame:S+1,value:S+1}]),o.addTargetedAnimation(f,d)}let p=r.defaultRenderingPipeline?Ee():r.node;if(!p||!r.propertyPath||!r.keyFrameAnimations)return;let s=dt(p,r.propertyPath),c=Be(s);if(c===null)return;let m=new P.Animation(r.propertyPath,r.propertyPath,60,c,P.Animation.ANIMATIONLOOPMODE_CYCLE,!1),h=[];r.keyFrameAnimations?.forEach(d=>{if(Fi(d))return h.push(d);_e(d)&&(h.push(d.key1),h.push(d.key2),Xe(p)&&r.propertyPath==="position"&&m.addEvent(new we.AnimationEvent(d.key1.frame,()=>{let f=Ht();if(!f)return;let S=f.motionStrength;f.motionStrength=0,requestAnimationFrame(()=>{f.motionStrength=S})})))}),m.setKeys(h),o.addTargetedAnimation(m,p)}),o.normalize(),o}n(Ba,"generateCinematicAnimationGroup");async function Ni(t,e){return new Promise((i,o)=>{let r=indexedDB.open(t,1);r.addEventListener("error",()=>o()),r.addEventListener("blocked",()=>o()),r.addEventListener("upgradeneeded",()=>{try{e(r.result)}catch(a){o(a)}}),r.addEventListener("success",()=>{i(r.result)})})}n(Ni,"openIndexDB");function He(t,e,i){return new Promise(o=>{let a=t.transaction(e).objectStore(e).get(i);a.addEventListener("error",()=>{o(null)}),a.addEventListener("success",()=>{o(a.result??null)})})}n(He,"getFromIndexDB");async function W(t,e,i){let r=t.transaction(e,"readwrite").objectStore(e).put(i);await new Promise((a,l)=>{r.addEventListener("error",()=>l()),r.addEventListener("success",()=>a())})}n(W,"putInIndexDB");var Qr=require("babylonjs");function za(t){Qr.AbstractEngine.OfflineProviderFactory=(e,i,o=!1)=>new ke(t,e,i,o)}n(za,"setupOfflineProvider");async function Gi(t,e){let i=await new Promise(o=>{let r=new ke(t,e,a=>o(a?r:null),!1)});return await i?.open(),i}n(Gi,"createAndOpenDatabase");var ke=class{static{n(this,"Database")}enableSceneOffline=!0;enableTexturesOffline=!0;name;_database=null;_manifestVersion=null;_loadFilePromises=new Map;constructor(e,i,o,r){this.name=e,r?o(!1):this._checkManifest(i,o)}async _checkManifest(e,i){try{let o=await z(`${e}.manifest?${Date.now()}`);this._manifestVersion=o.version,i(!0)}catch{this.enableSceneOffline=!1,this.enableTexturesOffline=!1,i(!1)}}async open(e,i){try{this._database=await Ni(this.name,o=>{o.createObjectStore("files",{keyPath:"url"}),o.createObjectStore("images",{keyPath:"url"}),o.createObjectStore("versions",{keyPath:"url"})}),e?.()}catch{i?.()}}close(){this._database?.close(),this._database=null,this._loadFilePromises.clear()}async loadImage(e,i){if(!this._database){i.src=e;return}let o=null;await Si(()=>this._manifestVersion!==null);let r=this._loadFilePromises.get(e);if(r)return r.then(l=>{l!==null?i.src=l:i.src=e});let a=new Promise(async l=>{if(await this._getFileVersionForUrl(e)!==this._manifestVersion?(o=await ye(e,"blob"),await Promise.all([W(this._database,"images",{url:e,data:o}),W(this._database,"versions",{url:e,version:this._manifestVersion})])):o=(await He(this._database,"images",e))?.data??null,o!==null){let s=URL.createObjectURL(o);i.src=s}else i.src=e;l(i.src)});this._loadFilePromises.set(e,a)}async saveImage(e){if(!this._database)throw new Error("Database is not available");let i=await ye(e,"blob");await Promise.all([W(this._database,"images",{url:e,data:i}),W(this._database,"versions",{url:e,version:this._manifestVersion})])}async isFileMatchingVersion(e){return await this._getFileVersionForUrl(e)===this._manifestVersion}async loadFile(e,i,o,r,a){if(!this._database)return r?.();let l=null;await Si(()=>this._manifestVersion!==null);let p=this._loadFilePromises.get(e);if(p)return p.then(c=>{c!==null?i(c):r?.()});let s=new Promise(async c=>{await this._getFileVersionForUrl(e)!==this._manifestVersion?(l=await ye(e,a?"arraybuffer":"text",o),await Promise.all([W(this._database,"files",{url:e,data:l}),W(this._database,"versions",{url:e,version:this._manifestVersion})])):l=(await He(this._database,"files",e))?.data??null,l!==null?i(l):r?.(),c(l)});this._loadFilePromises.set(e,s)}async saveFile(e,i,o){if(!this._database)throw new Error("Database is not available");let r=await ye(e,i?"arraybuffer":"text",o);await Promise.all([W(this._database,"files",{url:e,data:r}),W(this._database,"versions",{url:e,version:this._manifestVersion})])}async _getFileVersionForUrl(e){return(await He(this._database,"versions",e))?.version??null}};var Jr=["mp3","wav"],en=["babylonbinarymeshdata"],Ha=["ktx","ktx2","jpg","jpeg","png","bmp","webp"],tn=["babylon","json"],Bi=["jpg","jpeg","png","bmp","webp"],on=["bin","ktx","ktx2",...en,...Jr],ka=[...tn,...Bi,...on];async function Ua(t,e,i){let o=[],r=await z(`${e}scenes-used-files.json`),a=[];if(i?.scenesFilter){a=i.scenesFilter.map(h=>typeof h=="string"?{sceneName:h,disableSounds:!1,disableTextures:!1,disableGeometries:!1}:h);for(let[h,d]of Object.entries(r))a.find(f=>f.sceneName===h)||delete r[h]}let l=0,p=0,s=i?.engine?.textureFormatInUse?i?.engine?.texturesSupported[0]:null,c=Object.values(r).reduce((h,d)=>h+d.length,0);function m(h){++p,i?.onProgress?.(p/c),h?.()}n(m,"notifyProgress");for(let[h,d]of Object.entries(r)){let f=h.replace(".scene",".babylon"),S=await Gi(t,`${e}${f}`);if(!S)continue;let g=a.find(b=>b.sceneName===h);for(let b=0,C=d.length;b<C;++b){let _=d[b],x=_.split(".").pop()?.toLowerCase();if(!x){m();continue}if(en.includes(x)&&g?.disableGeometries){m();continue}if(Ha.includes(x)&&g?.disableTextures){m();continue}if(Jr.includes(x)&&g?.disableSounds){m();continue}if(Bi.includes(x)&&g?.disableTextures){m();continue}if(x==="ktx")if(s){if(!_.endsWith(s)){m();continue}}else{m();continue}if(x==="ktx2"&&!Ge()){m();continue}if(o.length>300){try{await Promise.all(o)}catch{}o.splice(0,o.length)}let M=`${e}${_}`;ka.includes(x)&&o.push(new Promise(async G=>{if(await S.isFileMatchingVersion(M))return m(G);try{Bi.includes(x)?i?.disableImages||(await S.saveImage(M),++l):on.includes(x)?(await S.saveFile(M,!0),++l):tn.includes(x)&&(await S.saveFile(M,!1),++l)}catch{}m(G)}))}await Promise.all(o),S.close()}return await Promise.all(o),{loadedCount:l,processedFilesCount:p}}n(Ua,"preloadAssetsToDatabase");0&&(module.exports={AdvancedAssetContainer,AdvancedAssetContainerInstantiatedEntries,Cinematic,Database,NodeParticleSystemSet,VolumetricDebugMode,VolumetricDitherMode,VolumetricFogMode,VolumetricLightingRenderingPipeline,VolumetricShadowKind,VolumetricShadowMode,VolumetricStepDistribution,VolumetricTransmittanceMode,_applyScriptsForObject,_getKtx2TextureName,_preloadScriptsAssets,_registerScriptInstance,_removeRegisteredScriptInstance,addExcludedCompressedTexture,animationFromSprite,animationGroupFromScene,applyMeshesLODQuality,applyRenderingConfigurationForCamera,applyScriptOnObject,applyShadowsQuality,applyTexturesQuality,componentFromScene,computeVolumetricBudget,computeVolumetricShapeKey,configureEngineToUseCompressedTextures,configureMeshDistanceOrScreenCoverage,configureShadowMapRefreshRate,configureShadowMapRenderListPredicate,copyAndParseRagdollConfiguration,createAndOpenDatabase,createDefaultRenderingPipeline,createMotionBlurPostProcess,createSSAO2RenderingPipeline,createSSRRenderingPipeline,createTAARenderingPipeline,createVLSPostProcess,createVolumetricLightingRenderingPipeline,defaultPipelineCameraConfigurations,disposeDefaultRenderingPipeline,disposeMotionBlurPostProcess,disposeSSAO2RenderingPipeline,disposeSSRRenderingPipeline,disposeTAARenderingPipeline,disposeVLSPostProcess,disposeVolumetricLightingRenderingPipeline,ensureVolumetricLightConfiguration,forceCompileAllSceneMaterials,generateCinematicAnimationGroup,getAllScriptsByClassForObject,getAllVolumetricCandidateLights,getAnimationTypeForObject,getDefaultRenderingPipeline,getDefaultVolumetricLightConfiguration,getDefaultVolumetricLightingConfiguration,getFromIndexDB,getMotionBlurPostProcess,getPowerOfTwoUntil,getSSAO2RenderingPipeline,getSSRRenderingPipeline,getScriptByClassForObject,getTAARenderingPipeline,getTextureUrl,getVLSPostProcess,getVolumetricLightConfiguration,getVolumetricLightRange,getVolumetricLightSteps,getVolumetricLightWorldDirection,getVolumetricLightWorldPosition,getVolumetricLightingRenderingPipeline,guiFromAsset,isAbstractMesh,isAnyParticleSystem,isArcRotateCamera,isBone,isCamera,isCascadedShadowGenerator,isCinematicGroup,isCinematicKey,isCinematicKeyCut,isCinematicKeyEvent,isCinematicSound,isClusteredLightContainer,isDecalMesh,isDirectionalLight,isFreeCamera,isGPUParticleSystem,isGaussianSplattingMesh,isGroundMesh,isHemisphericLight,isInstancedMesh,isLight,isMesh,isNode,isNodeFromStaticGroup,isParticleSystem,isPointLight,isScene,isShadowGenerator,isSoundNode,isSpotLight,isSprite,isTexture,isTransformNode,isUsingKtx2CompressedTextures,isVolumetricLightEnabled,isVolumetricLightSupported,isVolumetricLightingSupported,loadMaterialFromFile,loadScene,markVolumetricLightsDirty,maxVolumetricArrayLights,maxVolumetricDirectionalLights,maxVolumetricShadowSlots,motionBlurPostProcessCameraConfigurations,nodeFromDescendants,nodeFromScene,normalizeAtlasJson,normalizeVolumetricLightConfiguration,normalizeVolumetricLightingConfiguration,onKeyboardEvent,onPointerEvent,openIndexDB,parseCinematic,parseCinematicKeyValue,parseDefaultRenderingPipeline,parseKeyFrameAnimations,parseMotionBlurPostProcess,parseRagdollConfiguration,parseSSAO2RenderingPipeline,parseSSRRenderingPipeline,parseTAARenderingPipeline,parseVLSPostProcess,parseVolumetricLightingRenderingPipeline,particleSystemFromScene,playSpriteAnimationFromName,preloadAssetsToDatabase,putInIndexDB,registerScriptAssetParser,resolveVolumetricShadowSlot,saveRenderingConfigurationForCamera,sceneAsset,scriptAssetsCache,scriptAssetsParsers,scriptsDictionary,selectVolumetricLights,serializeDefaultRenderingPipeline,serializeMotionBlurPostProcess,serializeSSAO2RenderingPipeline,serializeSSRRenderingPipeline,serializeTAARenderingPipeline,serializeVLSPostProcess,serializeVolumetricLightingRenderingPipeline,setDefaultRenderingPipelineRef,setMotionBlurPostProcessRef,setSSAO2RenderingPipelineRef,setSSRRenderingPipelineRef,setStaticDecalsEnabled,setTAARenderingPipelineRef,setUseKtx2CompressedTextures,setVLSPostProcessRef,setVolumetricLightingRenderingPipelineRef,setupOfflineProvider,soundFromScene,spriteFromSpriteManager,ssaoRenderingPipelineCameraConfigurations,ssrRenderingPipelineCameraConfigurations,taaRenderingPipelineCameraConfigurations,visibleAsAsset,visibleAsBoolean,visibleAsColor3,visibleAsColor4,visibleAsEntity,visibleAsKeyMap,visibleAsNumber,visibleAsString,visibleAsTexture,visibleAsVector2,visibleAsVector3,vlsPostProcessCameraConfigurations,volumetricLightMetadataKey,volumetricLightingRenderingPipelineCameraConfigurations});
|