@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 7.82 kB
JavaScript
import{Vec3 as t}from"../../core/math/vec3.js";import{PIXELFORMAT_RGBA8 as e,PIXELFORMAT_RGBA32F as i,ADDRESS_CLAMP_TO_EDGE as s,TEXTURETYPE_DEFAULT as a,FILTER_NEAREST as o}from"../../platform/graphics/constants.js";import{FloatPacking as h}from"../../core/math/float-packing.js";import{MASK_AFFECT_DYNAMIC as r,MASK_AFFECT_LIGHTMAPPED as l,LIGHTTYPE_SPOT as T,LIGHTSHAPE_PUNCTUAL as _}from"../constants.js";import{Texture as n}from"../../platform/graphics/texture.js";import{DeviceCache as A}from"../../platform/graphics/device-cache.js";import{LightCamera as g}from"../renderer/light-camera.js";const d=new t,u=new Float32Array(6),O=new t(-.5,0,0),x=new t(0,0,.5),I={FLAGS:0,COLOR_A:1,COLOR_B:2,SPOT_ANGLES:3,SHADOW_BIAS:4,COOKIE_A:5,COOKIE_B:6,COUNT_ALWAYS:7,POSITION_X:7,POSITION_Y:8,POSITION_Z:9,RANGE:10,SPOT_DIRECTION_X:11,SPOT_DIRECTION_Y:12,SPOT_DIRECTION_Z:13,PROJ_MAT_00:14,ATLAS_VIEWPORT_A:14,PROJ_MAT_01:15,ATLAS_VIEWPORT_B:15,PROJ_MAT_02:16,PROJ_MAT_03:17,PROJ_MAT_10:18,PROJ_MAT_11:19,PROJ_MAT_12:20,PROJ_MAT_13:21,PROJ_MAT_20:22,PROJ_MAT_21:23,PROJ_MAT_22:24,PROJ_MAT_23:25,PROJ_MAT_30:26,PROJ_MAT_31:27,PROJ_MAT_32:28,PROJ_MAT_33:29,AREA_DATA_WIDTH_X:30,AREA_DATA_WIDTH_Y:31,AREA_DATA_WIDTH_Z:32,AREA_DATA_HEIGHT_X:33,AREA_DATA_HEIGHT_Y:34,AREA_DATA_HEIGHT_Z:35,COUNT:36},R={POSITION_RANGE:0,SPOT_DIRECTION:1,PROJ_MAT_0:2,ATLAS_VIEWPORT:2,PROJ_MAT_1:3,PROJ_MAT_2:4,PROJ_MAT_3:5,AREA_DATA_WIDTH:6,AREA_DATA_HEIGHT:7,COUNT:8},c=new A;class D{static getLightTextureFormat(t){return t.extTextureFloat&&t.maxTextures>8?0:1}static getShaderDefines(t){return c.get(t,(()=>{const e=(t,e,i,s)=>Object.keys(e).map((t=>`#define ${i}${t} ${e[t]}${s}`)).join("\n"),i=0===D.getLightTextureFormat(t)?"FLOAT":"8BIT",s=t.supportsTextureFetch?"":".5";return`\n\t\t\t\t\t\t\t\t\n#define CLUSTER_TEXTURE_${i}\n\t\t\t\t\t\t\t\t${e(0,I,"CLUSTER_TEXTURE_8_",s)}\n\t\t\t\t\t\t\t\t${e(0,R,"CLUSTER_TEXTURE_F_",s)}\n\t\t\t\t\t\t`}))}constructor(s){this.device=s,this.cookiesEnabled=!1,this.shadowsEnabled=!1,this.areaLightsEnabled=!1,this.maxLights=255;let a=I.COUNT_ALWAYS,o=0;this.lightTextureFormat=D.getLightTextureFormat(s),0===this.lightTextureFormat?o=R.COUNT:a=I.COUNT,this.lights8=new Uint8ClampedArray(4*a*this.maxLights),this.lightsTexture8=this.createTexture(this.device,a,this.maxLights,e,"LightsTexture8"),this._lightsTexture8Id=this.device.scope.resolve("lightsTexture8"),o?(this.lightsFloat=new Float32Array(4*o*this.maxLights),this.lightsTextureFloat=this.createTexture(this.device,o,this.maxLights,i,"LightsTextureFloat"),this._lightsTextureFloatId=this.device.scope.resolve("lightsTextureFloat")):(this.lightsFloat=null,this.lightsTextureFloat=null,this._lightsTextureFloatId=void 0),this._lightsTextureInvSizeId=this.device.scope.resolve("lightsTextureInvSize"),this._lightsTextureInvSizeData=new Float32Array(4),this._lightsTextureInvSizeData[0]=o?1/this.lightsTextureFloat.width:0,this._lightsTextureInvSizeData[1]=o?1/this.lightsTextureFloat.height:0,this._lightsTextureInvSizeData[2]=1/this.lightsTexture8.width,this._lightsTextureInvSizeData[3]=1/this.lightsTexture8.height,this.invMaxColorValue=0,this.invMaxAttenuation=0,this.boundsMin=new t,this.boundsDelta=new t}destroy(){this.lightsTexture8&&(this.lightsTexture8.destroy(),this.lightsTexture8=null),this.lightsTextureFloat&&(this.lightsTextureFloat.destroy(),this.lightsTextureFloat=null)}createTexture(t,e,i,h,r){return new n(t,{name:r,width:e,height:i,mipmaps:!1,format:h,addressU:s,addressV:s,type:a,magFilter:o,minFilter:o,anisotropy:1})}setCompressionRanges(t,e){this.invMaxColorValue=1/e,this.invMaxAttenuation=1/t}setBounds(t,e){this.boundsMin.copy(t),this.boundsDelta.copy(e)}uploadTextures(){this.lightsTextureFloat&&(this.lightsTextureFloat.lock().set(this.lightsFloat),this.lightsTextureFloat.unlock()),this.lightsTexture8.lock().set(this.lights8),this.lightsTexture8.unlock()}updateUniforms(){this._lightsTexture8Id.setValue(this.lightsTexture8),0===this.lightTextureFormat&&this._lightsTextureFloatId.setValue(this.lightsTextureFloat),this._lightsTextureInvSizeId.setValue(this._lightsTextureInvSizeData)}getSpotDirection(t,e){e._node.getWorldTransform().getY(t).mulScalar(-1),t.normalize()}getLightAreaSizes(t){const e=t._node.getWorldTransform();return e.transformVector(O,d),u[0]=d.x,u[1]=d.y,u[2]=d.z,e.transformVector(x,d),u[3]=d.x,u[4]=d.y,u[5]=d.z,u}addLightDataFlags(t,e,i,s,a,o){t[e+0]=s?255:0,t[e+1]=64*i._shape,t[e+2]=255*i._falloffMode,t[e+3]=a?255*o:0}addLightDataColor(t,e,i,s,a){const o=this.invMaxColorValue,T=s?i._linearFinalColor:i._finalColor;h.float2Bytes(T[0]*o,t,e+0,2),h.float2Bytes(T[1]*o,t,e+2,2),h.float2Bytes(T[2]*o,t,e+4,2),t[e+6]=a?255:0;const _=!!(i.mask&r),n=!!(i.mask&l);t[e+7]=_&&n?127:n?255:0}addLightDataSpotAngles(t,e,i){h.float2Bytes(.499999*i._innerConeAngleCos+.5,t,e+0,2),h.float2Bytes(.499999*i._outerConeAngleCos+.5,t,e+2,2)}addLightDataShadowBias(t,e,i){const s=i.getRenderData(null,0),a=i._getUniformBiasValues(s);h.float2BytesRange(a.bias,t,e,-1,20,2),h.float2Bytes(a.normalBias,t,e+2,2)}addLightDataPositionRange(t,e,i,s){const a=d.sub2(s,this.boundsMin).div(this.boundsDelta);h.float2Bytes(a.x,t,e+0,4),h.float2Bytes(a.y,t,e+4,4),h.float2Bytes(a.z,t,e+8,4),h.float2Bytes(i.attenuationEnd*this.invMaxAttenuation,t,e+12,4)}addLightDataSpotDirection(t,e,i){this.getSpotDirection(d,i),h.float2Bytes(.499999*d.x+.5,t,e+0,4),h.float2Bytes(.499999*d.y+.5,t,e+4,4),h.float2Bytes(.499999*d.z+.5,t,e+8,4)}addLightDataLightProjMatrix(t,e,i){const s=i.data;for(let i=0;i<12;i++)h.float2BytesRange(s[i],t,e+4*i,-2,2,4);for(let i=12;i<16;i++)h.float2MantissaExponent(s[i],t,e+4*i,4)}addLightDataCookies(t,e,i){const s="rgb"===i._cookieChannel;if(t[e+0]=Math.floor(255*i.cookieIntensity),t[e+1]=s?255:0,!s){const s=i._cookieChannel;t[e+4]="rrr"===s?255:0,t[e+5]="ggg"===s?255:0,t[e+6]="bbb"===s?255:0,t[e+7]="aaa"===s?255:0}}addLightAtlasViewport(t,e,i){h.float2Bytes(i.x,t,e+0,2),h.float2Bytes(i.y,t,e+2,2),h.float2Bytes(i.z/3,t,e+4,2)}addLightAreaSizes(t,e,i){const s=this.getLightAreaSizes(i);for(let i=0;i<6;i++)h.float2MantissaExponent(s[i],t,e+4*i,4)}addLightData(t,e,i){const s=t._type===T,a=t.atlasViewportAllocated,o=this.cookiesEnabled&&!!t._cookie&&a,h=this.areaLightsEnabled&&t.shape!==_,r=this.shadowsEnabled&&t.castShadows&&a,l=t._node.getPosition();let n=null,A=null;if(s)if(r){n=t.getRenderData(null,0).shadowMatrix}else o&&(n=g.evalSpotCookieMatrix(t));else(r||o)&&(A=t.atlasViewport);const u=this.lights8,O=e*this.lightsTexture8.width*4;if(this.addLightDataFlags(u,O+4*I.FLAGS,t,s,r,t.shadowIntensity),this.addLightDataColor(u,O+4*I.COLOR_A,t,i,o),s&&this.addLightDataSpotAngles(u,O+4*I.SPOT_ANGLES,t),t.castShadows&&this.addLightDataShadowBias(u,O+4*I.SHADOW_BIAS,t),o&&this.addLightDataCookies(u,O+4*I.COOKIE_A,t),0===this.lightTextureFormat){const i=this.lightsFloat,a=e*this.lightsTextureFloat.width*4;if(i[a+4*R.POSITION_RANGE+0]=l.x,i[a+4*R.POSITION_RANGE+1]=l.y,i[a+4*R.POSITION_RANGE+2]=l.z,i[a+4*R.POSITION_RANGE+3]=t.attenuationEnd,s&&(this.getSpotDirection(d,t),i[a+4*R.SPOT_DIRECTION+0]=d.x,i[a+4*R.SPOT_DIRECTION+1]=d.y,i[a+4*R.SPOT_DIRECTION+2]=d.z),n){const t=n.data;for(let e=0;e<16;e++)i[a+4*R.PROJ_MAT_0+e]=t[e]}if(A&&(i[a+4*R.ATLAS_VIEWPORT+0]=A.x,i[a+4*R.ATLAS_VIEWPORT+1]=A.y,i[a+4*R.ATLAS_VIEWPORT+2]=A.z/3),h){const e=this.getLightAreaSizes(t);i[a+4*R.AREA_DATA_WIDTH+0]=e[0],i[a+4*R.AREA_DATA_WIDTH+1]=e[1],i[a+4*R.AREA_DATA_WIDTH+2]=e[2],i[a+4*R.AREA_DATA_HEIGHT+0]=e[3],i[a+4*R.AREA_DATA_HEIGHT+1]=e[4],i[a+4*R.AREA_DATA_HEIGHT+2]=e[5]}}else this.addLightDataPositionRange(u,O+4*I.POSITION_X,t,l),s&&this.addLightDataSpotDirection(u,O+4*I.SPOT_DIRECTION_X,t),n&&this.addLightDataLightProjMatrix(u,O+4*I.PROJ_MAT_00,n),A&&this.addLightAtlasViewport(u,O+4*I.ATLAS_VIEWPORT_A,A),h&&this.addLightAreaSizes(u,O+4*I.AREA_DATA_WIDTH_X,t)}}export{D as LightsBuffer};