@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 13.8 kB
JavaScript
import{math as t}from"../core/math/math.js";import{Color as s}from"../core/math/color.js";import{Mat4 as e}from"../core/math/mat4.js";import{Vec2 as i}from"../core/math/vec2.js";import{Vec3 as a}from"../core/math/vec3.js";import{Vec4 as h}from"../core/math/vec4.js";import{LIGHTTYPE_DIRECTIONAL as o,MASK_AFFECT_DYNAMIC as n,LIGHTFALLOFF_LINEAR as r,SHADOW_PCF3 as d,BLUR_GAUSSIAN as l,LIGHTSHAPE_PUNCTUAL as _,SHADOWUPDATE_REALTIME as c,LIGHTTYPE_OMNI as u,SHADOW_PCSS as p,SHADOW_PCF5 as f,SHADOW_VSM32 as w,SHADOW_VSM16 as m,SHADOW_VSM8 as y,SHADOW_PCF1 as g,MASK_BAKE as S,SHADOWUPDATE_NONE as k,SHADOWUPDATE_THISFRAME as C,LIGHTTYPE_SPOT as M}from"./constants.js";import{ShadowRenderer as B}from"./renderer/shadow-renderer.js";import{DepthState as v}from"../platform/graphics/depth-state.js";const b=new a,A={bias:0,normalBias:0},D={r:0,g:1,b:2,a:3},O={directional:o,omni:u,point:u,spot:M},T=[[new h(0,0,1,1)],[new h(0,0,.5,.5),new h(0,.5,.5,.5)],[new h(0,0,.5,.5),new h(0,.5,.5,.5),new h(.5,0,.5,.5)],[new h(0,0,.5,.5),new h(0,.5,.5,.5),new h(.5,0,.5,.5),new h(.5,.5,.5,.5)]];let U=0;class F{constructor(t,s,i,a){this.light=a,this.camera=s,this.shadowCamera=B.createShadowCamera(t,a._shadowType,a._type,i),this.shadowMatrix=new e,this.shadowViewport=new h(0,0,1,1),this.shadowScissor=new h(0,0,1,1),this.depthRangeCompensation=0,this.projectionCompensation=0,this.face=i,this.visibleCasters=[],this.viewBindGroups=[]}destroy(){this.viewBindGroups.forEach((t=>{t.defaultUniformBuffer.destroy(),t.destroy()})),this.viewBindGroups.length=0}get shadowBuffer(){const t=this.shadowCamera.renderTarget;if(t){const s=this.light;return s._type===u?t.colorBuffer:s._isPcf&&s.device.supportsDepthShadow?t.depthBuffer:t.colorBuffer}return null}}class P{constructor(t,e){this.layers=new Set,this.clusteredLighting=void 0,this.shadowDepthState=v.DEFAULT.clone(),this.device=t,this.clusteredLighting=e,this.id=U++,this._type=o,this._color=new s(.8,.8,.8),this._intensity=1,this._affectSpecularity=!0,this._luminance=0,this._castShadows=!1,this._enabled=!1,this._mask=n,this.isStatic=!1,this.key=0,this.bakeDir=!0,this.bakeNumSamples=1,this.bakeArea=0,this.attenuationStart=10,this.attenuationEnd=10,this._falloffMode=r,this._shadowType=d,this._vsmBlurSize=11,this.vsmBlurMode=l,this.vsmBias=.0025,this._cookie=null,this.cookieIntensity=1,this._cookieFalloff=!0,this._cookieChannel="rgb",this._cookieTransform=null,this._cookieTransformUniform=new Float32Array(4),this._cookieOffset=null,this._cookieOffsetUniform=new Float32Array(2),this._cookieTransformSet=!1,this._cookieOffsetSet=!1,this._innerConeAngle=40,this._outerConeAngle=45,this.cascades=null,this._shadowMatrixPalette=null,this._shadowCascadeDistances=null,this.numCascades=1,this.cascadeDistribution=.5,this._shape=_,this._finalColor=new Float32Array([.8,.8,.8]);const i=Math.pow(this._finalColor[0],2.2);this._linearFinalColor=new Float32Array([i,i,i]),this._position=new a(0,0,0),this._direction=new a(0,0,0),this._innerConeAngleCos=Math.cos(this._innerConeAngle*Math.PI/180),this._updateOuterAngle(this._outerConeAngle),this._usePhysicalUnits=void 0,this._shadowMap=null,this._shadowRenderParams=[],this._shadowCameraParams=[],this.shadowDistance=40,this._shadowResolution=1024,this._shadowBias=-5e-4,this.shadowIntensity=1,this._normalOffsetBias=0,this.shadowUpdateMode=c,this.shadowUpdateOverrides=null,this._penumbraSize=1,this._isVsm=!1,this._isPcf=!0,this._cookieMatrix=null,this._atlasViewport=null,this.atlasViewportAllocated=!1,this.atlasVersion=0,this.atlasSlotIndex=0,this.atlasSlotUpdated=!1,this._node=null,this._renderData=[],this.visibleThisFrame=!1,this.maxScreenSize=0,this._updateShadowBias()}destroy(){this._destroyShadowMap(),this.releaseRenderData(),this._renderData=null}releaseRenderData(){if(this._renderData){for(let t=0;t<this._renderData.length;t++)this._renderData[t].destroy();this._renderData.length=0}}addLayer(t){this.layers.add(t)}removeLayer(t){this.layers.delete(t)}set shadowBias(t){this._shadowBias!==t&&(this._shadowBias=t,this._updateShadowBias())}get shadowBias(){return this._shadowBias}set numCascades(t){this.cascades&&this.numCascades===t||(this.cascades=T[t-1],this._shadowMatrixPalette=new Float32Array(64),this._shadowCascadeDistances=new Float32Array(4),this._destroyShadowMap(),this.updateKey())}get numCascades(){return this.cascades.length}set shadowMap(t){this._shadowMap!==t&&(this._destroyShadowMap(),this._shadowMap=t)}get shadowMap(){return this._shadowMap}set mask(t){this._mask!==t&&(this._mask=t,this.updateKey())}get mask(){return this._mask}get numShadowFaces(){const t=this._type;return t===o?this.numCascades:t===u?6:1}set type(t){if(this._type===t)return;this._type=t,this._destroyShadowMap(),this._updateShadowBias(),this.updateKey();const s=this._shadowType;this._shadowType=null,this.shadowUpdateOverrides=null,this.shadowType=s}get type(){return this._type}set shape(t){if(this._shape===t)return;this._shape=t,this._destroyShadowMap(),this.updateKey();const s=this._shadowType;this._shadowType=null,this.shadowType=s}get shape(){return this._shape}set usePhysicalUnits(t){this._usePhysicalUnits!==t&&(this._usePhysicalUnits=t,this._updateFinalColor())}get usePhysicalUnits(){return this._usePhysicalUnits}set shadowType(t){if(this._shadowType===t)return;const s=this.device;this._type===u&&t!==d&&t!==p&&(t=d);const e=s.supportsDepthShadow;t!==f||e||(t=d),t!==w||s.textureFloatRenderable&&s.textureFloatFilterable||(t=m),t!==m||s.textureHalfFloatRenderable||(t=y),this._isVsm=t>=y&&t<=w,this._isPcf=t===g||t===d||t===f,this._shadowType=t,this._destroyShadowMap(),this.updateKey()}get shadowType(){return this._shadowType}set enabled(t){this._enabled!==t&&(this._enabled=t,this.layersDirty())}get enabled(){return this._enabled}set castShadows(t){this._castShadows!==t&&(this._castShadows=t,this._destroyShadowMap(),this.layersDirty(),this.updateKey())}get castShadows(){return this._castShadows&&this._mask!==S&&0!==this._mask}get bakeShadows(){return this._castShadows&&this._mask===S}set shadowResolution(t){this._shadowResolution!==t&&(t=this._type===u?Math.min(t,this.device.maxCubeMapSize):Math.min(t,this.device.maxTextureSize),this._shadowResolution=t,this._destroyShadowMap())}get shadowResolution(){return this._shadowResolution}set vsmBlurSize(t){this._vsmBlurSize!==t&&(t%2==0&&t++,this._vsmBlurSize=t)}get vsmBlurSize(){return this._vsmBlurSize}set normalOffsetBias(t){this._normalOffsetBias!==t&&((!this._normalOffsetBias&&t||this._normalOffsetBias&&!t)&&this.updateKey(),this._normalOffsetBias=t)}get normalOffsetBias(){return this._normalOffsetBias}set falloffMode(t){this._falloffMode!==t&&(this._falloffMode=t,this.updateKey())}get falloffMode(){return this._falloffMode}set innerConeAngle(t){this._innerConeAngle!==t&&(this._innerConeAngle=t,this._innerConeAngleCos=Math.cos(t*Math.PI/180),this._usePhysicalUnits&&this._updateFinalColor())}get innerConeAngle(){return this._innerConeAngle}set outerConeAngle(t){this._outerConeAngle!==t&&(this._outerConeAngle=t,this._updateOuterAngle(t),this._usePhysicalUnits&&this._updateFinalColor())}get outerConeAngle(){return this._outerConeAngle}set penumbraSize(t){this._penumbraSize=t}get penumbraSize(){return this._penumbraSize}_updateOuterAngle(t){const s=t*Math.PI/180;this._outerConeAngleCos=Math.cos(s),this._outerConeAngleSin=Math.sin(s)}set intensity(t){this._intensity!==t&&(this._intensity=t,this._updateFinalColor())}get intensity(){return this._intensity}set affectSpecularity(t){this._type===o&&(this._affectSpecularity=t,this.updateKey())}get affectSpecularity(){return this._affectSpecularity}set luminance(t){this._luminance!==t&&(this._luminance=t,this._updateFinalColor())}get luminance(){return this._luminance}get cookieMatrix(){return this._cookieMatrix||(this._cookieMatrix=new e),this._cookieMatrix}get atlasViewport(){return this._atlasViewport||(this._atlasViewport=new h(0,0,1,1)),this._atlasViewport}set cookie(t){this._cookie!==t&&(this._cookie=t,this.updateKey())}get cookie(){return this._cookie}set cookieFalloff(t){this._cookieFalloff!==t&&(this._cookieFalloff=t,this.updateKey())}get cookieFalloff(){return this._cookieFalloff}set cookieChannel(t){if(this._cookieChannel!==t){if(t.length<3){const s=t.charAt(t.length-1),e=3-t.length;for(let i=0;i<e;i++)t+=s}this._cookieChannel=t,this.updateKey()}}get cookieChannel(){return this._cookieChannel}set cookieTransform(t){this._cookieTransform!==t&&(this._cookieTransform=t,this._cookieTransformSet=!!t,t&&!this._cookieOffset&&(this.cookieOffset=new i,this._cookieOffsetSet=!1),this.updateKey())}get cookieTransform(){return this._cookieTransform}set cookieOffset(t){if(this._cookieOffset===t)return;!(!this._cookieTransformSet&&!t)&&!t&&this._cookieOffset?this._cookieOffset.set(0,0):this._cookieOffset=t,this._cookieOffsetSet=!!t,t&&!this._cookieTransform&&(this.cookieTransform=new h(1,1,0,0),this._cookieTransformSet=!1),this.updateKey()}get cookieOffset(){return this._cookieOffset}beginFrame(){this.visibleThisFrame=this._type===o&&this._enabled,this.maxScreenSize=0,this.atlasViewportAllocated=!1,this.atlasSlotUpdated=!1}_destroyShadowMap(){if(this.releaseRenderData(),this._shadowMap&&(this._shadowMap.cached||this._shadowMap.destroy(),this._shadowMap=null),this.shadowUpdateMode===k&&(this.shadowUpdateMode=C),this.shadowUpdateOverrides)for(let t=0;t<this.shadowUpdateOverrides.length;t++)this.shadowUpdateOverrides[t]===k&&(this.shadowUpdateOverrides[t]=C)}getRenderData(t,s){for(let e=0;e<this._renderData.length;e++){const i=this._renderData[e];if(i.camera===t&&i.face===s)return i}const e=new F(this.device,t,s,this);return this._renderData.push(e),e}clone(){const t=new P(this.device,this.clusteredLighting);return t.type=this._type,t.setColor(this._color),t.intensity=this._intensity,t.affectSpecularity=this._affectSpecularity,t.luminance=this._luminance,t.castShadows=this.castShadows,t._enabled=this._enabled,t.attenuationStart=this.attenuationStart,t.attenuationEnd=this.attenuationEnd,t.falloffMode=this._falloffMode,t.shadowType=this._shadowType,t.vsmBlurSize=this._vsmBlurSize,t.vsmBlurMode=this.vsmBlurMode,t.vsmBias=this.vsmBias,t.penumbraSize=this.penumbraSize,t.shadowUpdateMode=this.shadowUpdateMode,t.mask=this.mask,this.shadowUpdateOverrides&&(t.shadowUpdateOverrides=this.shadowUpdateOverrides.slice()),t.innerConeAngle=this._innerConeAngle,t.outerConeAngle=this._outerConeAngle,t.numCascades=this.numCascades,t.cascadeDistribution=this.cascadeDistribution,t.shape=this._shape,t.shadowDepthState.copy(this.shadowDepthState),t.shadowBias=this.shadowBias,t.normalOffsetBias=this._normalOffsetBias,t.shadowResolution=this._shadowResolution,t.shadowDistance=this.shadowDistance,t.shadowIntensity=this.shadowIntensity,t}static getLightUnitConversion(t,s=Math.PI/4,e=0){switch(t){case M:{const t=Math.cos(s),i=Math.cos(e);return 2*Math.PI*(1-i+(i-t)/2)}case u:return 4*Math.PI;case o:return 1}}_getUniformBiasValues(t){const s=t.shadowCamera._farClip;switch(this._type){case u:A.bias=this.shadowBias,A.normalBias=this._normalOffsetBias;break;case M:this._isVsm?A.bias=-2e-4:(A.bias=20*this.shadowBias,this.device.isWebGL1&&this.device.extStandardDerivatives&&(A.bias*=-100)),A.normalBias=this._isVsm?this.vsmBias/(this.attenuationEnd/7):this._normalOffsetBias;break;case o:this._isVsm?A.bias=-2e-4:(A.bias=this.shadowBias/s*100,this.device.isWebGL1&&this.device.extStandardDerivatives&&(A.bias*=-100)),A.normalBias=this._isVsm?this.vsmBias/(s/7):this._normalOffsetBias}return A}getColor(){return this._color}getBoundingSphere(t){if(this._type===M){const s=this.attenuationEnd,e=this._outerConeAngle,i=this._outerConeAngleCos,a=this._node;b.copy(a.up),e>45?(t.radius=s*this._outerConeAngleSin,b.mulScalar(-s*i)):(t.radius=s/(2*i),b.mulScalar(-t.radius)),t.center.add2(a.getPosition(),b)}else this._type===u&&(t.center=this._node.getPosition(),t.radius=this.attenuationEnd)}getBoundingBox(s){if(this._type===M){const e=this.attenuationEnd,i=this._outerConeAngle,a=this._node,h=Math.abs(Math.sin(i*t.DEG_TO_RAD)*e);s.center.set(0,.5*-e,0),s.halfExtents.set(h,.5*e,h),s.setFromTransformedAabb(s,a.getWorldTransform(),!0)}else this._type===u&&(s.center.copy(this._node.getPosition()),s.halfExtents.set(this.attenuationEnd,this.attenuationEnd,this.attenuationEnd))}_updateShadowBias(){const t=this.device;if(t.isWebGL2||t.isWebGPU)if(this._type!==u||this.clusteredLighting){const t=-1e3*this.shadowBias;this.shadowDepthState.depthBias=t,this.shadowDepthState.depthBiasSlope=t}else this.shadowDepthState.depthBias=0,this.shadowDepthState.depthBiasSlope=0}_updateFinalColor(){const s=this._color,e=s.r,i=s.g,a=s.b;let h=this._intensity;this._usePhysicalUnits&&(h=this._luminance/P.getLightUnitConversion(this._type,this._outerConeAngle*t.DEG_TO_RAD,this._innerConeAngle*t.DEG_TO_RAD));const o=this._finalColor,n=this._linearFinalColor;o[0]=e*h,o[1]=i*h,o[2]=a*h,h>=1?(n[0]=Math.pow(e,2.2)*h,n[1]=Math.pow(i,2.2)*h,n[2]=Math.pow(a,2.2)*h):(n[0]=Math.pow(o[0],2.2),n[1]=Math.pow(o[1],2.2),n[2]=Math.pow(o[2],2.2))}setColor(){1===arguments.length?this._color.set(arguments[0].r,arguments[0].g,arguments[0].b):3===arguments.length&&this._color.set(arguments[0],arguments[1],arguments[2]),this._updateFinalColor()}layersDirty(){this.layers.forEach((t=>{t.markLightsDirty()}))}updateKey(){let t=this._type<<29|(this._castShadows?1:0)<<28|this._shadowType<<25|this._falloffMode<<23|(0!==this._normalOffsetBias?1:0)<<22|(this._cookie?1:0)<<21|(this._cookieFalloff?1:0)<<20|D[this._cookieChannel.charAt(0)]<<18|(this._cookieTransform?1:0)<<12|this._shape<<10|this.numCascades-1<<8|(this.affectSpecularity?1:0)<<7|this.mask<<6;3===this._cookieChannel.length&&(t|=D[this._cookieChannel.charAt(1)]<<16,t|=D[this._cookieChannel.charAt(2)]<<14),t!==this.key&&this.layersDirty(),this.key=t}}export{P as Light,O as lightTypes};