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