UNPKG

@animech-public/playcanvas

Version:
2 lines (1 loc) 28.5 kB
import{Curve as t}from"../../core/math/curve.js";import{CurveSet as e}from"../../core/math/curve-set.js";import{Mat4 as i}from"../../core/math/mat4.js";import{math as s}from"../../core/math/math.js";import{Quat as r}from"../../core/math/quat.js";import{Vec3 as a}from"../../core/math/vec3.js";import{BoundingBox as h}from"../../core/shape/bounding-box.js";import{FILTER_LINEAR as n,PRIMITIVE_TRIANGLES as o,CULLFACE_NONE as l,BUFFER_DYNAMIC as m,INDEXFORMAT_UINT16 as c,SEMANTIC_ATTR0 as p,TYPE_FLOAT32 as d,SEMANTIC_ATTR1 as u,SEMANTIC_ATTR2 as f,SEMANTIC_ATTR3 as x,SEMANTIC_ATTR4 as S,SEMANTIC_TEXCOORD0 as T,ADDRESS_CLAMP_TO_EDGE as w,PIXELFORMAT_RGBA8 as P,PIXELFORMAT_RGBA32F as y,FILTER_NEAREST as B}from"../../platform/graphics/constants.js";import{DeviceCache as g}from"../../platform/graphics/device-cache.js";import{IndexBuffer as M}from"../../platform/graphics/index-buffer.js";import{RenderTarget as v}from"../../platform/graphics/render-target.js";import{Texture as U}from"../../platform/graphics/texture.js";import{VertexBuffer as b}from"../../platform/graphics/vertex-buffer.js";import{VertexFormat as q}from"../../platform/graphics/vertex-format.js";import{ShaderProcessorOptions as A}from"../../platform/graphics/shader-processor-options.js";import{EMITTERSHAPE_BOX as I,EMITTERSHAPE_SPHERE as E,EMITTERSHAPE_HEMISPHERE as R,EMITTERSHAPE_CYLINDER as z,EMITTERSHAPE_CONE as V,PARTICLESORT_NONE as F,SHADER_FORWARD as C,PARTICLEORIENTATION_SCREEN as N,PARTICLEORIENTATION_WORLD as _,PARTICLEMODE_GPU as D,BLEND_NORMAL as G}from"../constants.js";import{Mesh as O}from"../mesh.js";import{MeshInstance as k}from"../mesh-instance.js";import{Material as L}from"../materials/material.js";import{getProgramLibrary as j}from"../shader-lib/get-program-library.js";import{createShaderFromCode as W}from"../shader-lib/utils.js";import{shaderChunks as $}from"../shader-lib/chunks/chunks.js";import{particle as X}from"../shader-lib/programs/particle.js";import{ParticleCPUUpdater as Y}from"./cpu-updater.js";import{ParticleGPUUpdater as Z}from"./gpu-updater.js";const Q=[[-1,-1],[1,-1],[1,1],[-1,1]];function H(t,e,i,s,r=y,a,h){let o=B;h&&r===P&&(o=n);const l=new U(t,{width:e,height:i,format:r,cubemap:!1,mipmaps:!1,minFilter:o,magFilter:o,addressU:w,addressV:w,name:"ParticleSystemTexture"}),m=l.lock();if(r===P){const t=new Uint8Array(s.length);for(let e=0;e<s.length;e++)t[e]=s[e]*a*255;s=t}return m.set(s),l.unlock(),l}function K(t){return Math.max(Math.min(t,1),0)}const J=new t([0,0,1,0]),tt=new t([0,1,1,1]),et=new e([0,0,1,0],[0,0,1,0],[0,0,1,0]),it=new e([0,1,1,1],[0,1,1,1],[0,1,1,1]);let st=2;const rt=new Float32Array(3),at=new i,ht=new a,nt=new a,ot=new a;let lt,mt;function ct(t,e){void 0!==mt[t]&&null!==mt[t]?lt[t]=mt[t]:lt[t]=e}function pt(t,e,i){return(255*t<<16|255*e<<8|255*i)/(1<<24)}function dt(t,e){const i=t.length/3,s=new Array(4*i);for(let r=0;r<i;r++)s[4*r]=t[3*r],s[4*r+1]=t[3*r+1],s[4*r+2]=t[3*r+2],s[4*r+3]=pt(e[3*r],e[3*r+1],e[3*r+2]);return s}function ut(t,e){const i=e.length,s=t.length/i;for(let r=0;r<s;r++)for(let s=0;s<i;s++){const a=Math.abs(t[r*i+s]);e[s]=Math.max(e[s],a)}}function ft(t,e,i){const s=function(t,e){const i=new Float32Array(t.length);for(let s=0;s<t.length;s++)i[s]=t[s]-e[s];return i}(e,t);return ut(s,i),function(t,e){const i=e.length,s=t.length/i;for(let r=0;r<s;r++)for(let s=0;s<i;s++)t[r*i+s]/=0===e[s]?1:e[s],t[r*i+s]*=.5,t[r*i+s]+=.5}(s,i),s}const xt=new g;class St{constructor(t,e){this.graphicsDevice=t;const i=t;this.precision=32,this._addTimeTime=0,lt=this,mt=e,ct("numParticles",1),this.numParticles>t.maxTextureSize&&(this.numParticles=t.maxTextureSize),ct("rate",1),ct("rate2",this.rate),ct("lifetime",50),ct("emitterExtents",new a(0,0,0)),ct("emitterExtentsInner",new a(0,0,0)),ct("emitterRadius",0),ct("emitterRadiusInner",0),ct("emitterLength",0),ct("emitterLengthInner",0),ct("emitterShape",I),ct("initialVelocity",1),ct("wrap",!1),ct("localSpace",!1),ct("screenSpace",!1),ct("wrapBounds",null),ct("colorMap",this.defaultParamTexture),ct("normalMap",null),ct("loop",!0),ct("preWarm",!1),ct("sort",F),ct("mode",D),ct("scene",null),ct("lighting",!1),ct("halfLambert",!1),ct("intensity",1),ct("stretch",0),ct("alignToMotion",!1),ct("depthSoftening",0),ct("mesh",null),ct("particleNormal",new a(0,1,0)),ct("orientation",N),ct("depthWrite",!1),ct("noFog",!1),ct("blendType",G),ct("node",null),ct("startAngle",0),ct("startAngle2",this.startAngle),ct("animTilesX",1),ct("animTilesY",1),ct("animStartFrame",0),ct("animNumFrames",1),ct("animNumAnimations",1),ct("animIndex",0),ct("randomizeAnimIndex",!1),ct("animSpeed",1),ct("animLoop",!0),this._gpuUpdater=new Z(this,i),this._cpuUpdater=new Y(this),this.emitterPosUniform=new Float32Array(3),this.wrapBoundsUniform=new Float32Array(3),this.emitterScaleUniform=new Float32Array([1,1,1]),ct("colorGraph",it),ct("colorGraph2",this.colorGraph),ct("scaleGraph",tt),ct("scaleGraph2",this.scaleGraph),ct("alphaGraph",tt),ct("alphaGraph2",this.alphaGraph),ct("localVelocityGraph",et),ct("localVelocityGraph2",this.localVelocityGraph),ct("velocityGraph",et),ct("velocityGraph2",this.velocityGraph),ct("rotationSpeedGraph",J),ct("rotationSpeedGraph2",this.rotationSpeedGraph),ct("radialSpeedGraph",J),ct("radialSpeedGraph2",this.radialSpeedGraph),this.animTilesParams=new Float32Array(2),this.animParams=new Float32Array(4),this.animIndexParams=new Float32Array(2),this.internalTex0=null,this.internalTex1=null,this.internalTex2=null,this.colorParam=null,this.vbToSort=null,this.vbOld=null,this.particleDistance=null,this.camera=null,this.swapTex=!1,this.useMesh=!0,this.useCpu=!t.supportsGpuParticles,this.pack8=!0,this.localBounds=new h,this.worldBoundsNoTrail=new h,this.worldBoundsTrail=[new h,new h],this.worldBounds=new h,this.worldBoundsSize=new a,this.prevWorldBoundsSize=new a,this.prevWorldBoundsCenter=new a,this.prevEmitterExtents=this.emitterExtents,this.prevEmitterRadius=this.emitterRadius,this.worldBoundsMul=new a,this.worldBoundsAdd=new a,this.timeToSwitchBounds=0,this.shaderParticleUpdateRespawn=null,this.shaderParticleUpdateNoRespawn=null,this.shaderParticleUpdateOnStop=null,this.numParticleVerts=0,this.numParticleIndices=0,this.material=null,this.meshInstance=null,this.drawOrder=0,this.seed=Math.random(),this.fixedTimeStep=1/60,this.maxSubSteps=10,this.simTime=0,this.simTimeTotal=0,this.beenReset=!1,this._layer=null,this.rebuild()}get defaultParamTexture(){return xt.get(this.graphicsDevice,(()=>{const t=16,e=new Float32Array(1024);for(let i=0;i<t;i++)for(let s=0;s<t;s++){const r=s+1-8.5,a=i+1-8.5,h=K(1-K(Math.sqrt(r*r+a*a)/t)-.5),n=i*t+s;e[4*n]=1,e[4*n+1]=1,e[4*n+2]=1,e[4*n+3]=h}const i=H(this.graphicsDevice,t,t,e,P,1,!0);return i.minFilter=n,i.magFilter=n,i}))}onChangeCamera(){this.regenShader(),this.resetMaterial()}calculateBoundsMad(){this.worldBoundsMul.x=1/this.worldBoundsSize.x,this.worldBoundsMul.y=1/this.worldBoundsSize.y,this.worldBoundsMul.z=1/this.worldBoundsSize.z,this.worldBoundsAdd.copy(this.worldBounds.center).mul(this.worldBoundsMul).mulScalar(-1),this.worldBoundsAdd.x+=.5,this.worldBoundsAdd.y+=.5,this.worldBoundsAdd.z+=.5}calculateWorldBounds(){if(!this.node)return;if(this.prevWorldBoundsSize.copy(this.worldBoundsSize),this.prevWorldBoundsCenter.copy(this.worldBounds.center),!this.useCpu){let t=!1;this.emitterShape===I?t=!this.emitterExtents.equals(this.prevEmitterExtents):this.emitterShape===E||this.emitterShape===R?t=!(this.emitterRadius===this.prevEmitterRadius):this.emitterShape===z||this.emitterShape===V?t=!(this.emitterRadius===this.prevEmitterRadius&&this.emitterLength===this.prevEmitterLength):console.warn(`ParticleEmitter: Unknown emitter shape ${this.emitterShape}`),t&&this.calculateLocalBounds()}const t=this.node.getWorldTransform();this.localSpace?this.worldBoundsNoTrail.copy(this.localBounds):this.worldBoundsNoTrail.setFromTransformedAabb(this.localBounds,t),this.worldBoundsTrail[0].add(this.worldBoundsNoTrail),this.worldBoundsTrail[1].add(this.worldBoundsNoTrail);const e=this.simTimeTotal;e>=this.timeToSwitchBounds&&(this.worldBoundsTrail[0].copy(this.worldBoundsTrail[1]),this.worldBoundsTrail[1].copy(this.worldBoundsNoTrail),this.timeToSwitchBounds=e+this.lifetime),this.worldBounds.copy(this.worldBoundsTrail[0]),this.worldBoundsSize.copy(this.worldBounds.halfExtents).mulScalar(2),this.localSpace?(this.meshInstance.aabb.setFromTransformedAabb(this.worldBounds,t),this.meshInstance.mesh.aabb.setFromTransformedAabb(this.worldBounds,t)):(this.meshInstance.aabb.copy(this.worldBounds),this.meshInstance.mesh.aabb.copy(this.worldBounds)),this.meshInstance._aabbVer=1-this.meshInstance._aabbVer,this.pack8&&this.calculateBoundsMad()}resetWorldBounds(){this.node&&(this.worldBoundsNoTrail.setFromTransformedAabb(this.localBounds,this.localSpace?i.IDENTITY:this.node.getWorldTransform()),this.worldBoundsTrail[0].copy(this.worldBoundsNoTrail),this.worldBoundsTrail[1].copy(this.worldBoundsNoTrail),this.worldBounds.copy(this.worldBoundsTrail[0]),this.worldBoundsSize.copy(this.worldBounds.halfExtents).mulScalar(2),this.prevWorldBoundsSize.copy(this.worldBoundsSize),this.prevWorldBoundsCenter.copy(this.worldBounds.center),this.simTimeTotal=0,this.timeToSwitchBounds=0)}calculateLocalBounds(){let t=Number.MAX_VALUE,e=Number.MAX_VALUE,i=Number.MAX_VALUE,s=-Number.MAX_VALUE,r=-Number.MAX_VALUE,a=-Number.MAX_VALUE,h=0,n=0;const o=this.lifetime/this.precision,l=[this.qVelocity,this.qVelocity2],m=[this.qLocalVelocity,this.qLocalVelocity2],c=[0,0],p=[0,0],d=[0,0],u=[0,0],f=[0,0];let x,S,T;for(let w=0;w<this.precision+1;w++){const P=Math.min(w,this.precision-1);for(let h=0;h<2;h++)x=m[h][3*P+0]*o+c[h],S=m[h][3*P+1]*o+p[h],T=m[h][3*P+2]*o+d[h],t=Math.min(x,t),e=Math.min(S,e),i=Math.min(T,i),s=Math.max(x,s),r=Math.max(S,r),a=Math.max(T,a),c[h]=x,p[h]=S,d[h]=T;for(let t=0;t<2;t++)f[t]+=o*Math.sqrt(l[t][3*P+0]*l[t][3*P+0]+l[t][3*P+1]*l[t][3*P+1]+l[t][3*P+2]*l[t][3*P+2]);u[0]+=this.qRadialSpeed[P]*o,u[1]+=this.qRadialSpeed2[P]*o,h=Math.max(h,Math.max(Math.abs(u[0]),Math.abs(u[1]))),n=Math.max(n,this.qScale[P])}this.emitterShape===I?(x=.5*this.emitterExtents.x,S=.5*this.emitterExtents.y,T=.5*this.emitterExtents.z):this.emitterShape===E?(x=this.emitterRadius,S=this.emitterRadius,T=this.emitterRadius):this.emitterShape===R?(x=this.emitterRadius,S=this.emitterRadius,T=this.emitterRadius,a=-T):this.emitterShape===z||this.emitterShape===V?(x=this.emitterRadius,S=this.emitterRadius,T=.5*this.emitterLength):console.warn(`ParticleEmitter: Unknown emitter shape ${this.emitterShape}`);const w=Math.max(f[0],f[1]);nt.x=t-n-x-h-w,nt.y=e-n-S-h-w,nt.z=i-n-T-h-w,ot.x=s+n+x+h+w,ot.y=r+n+S+h+w,ot.z=a+n+T+h+w,this.localBounds.setMinMax(nt,ot)}rebuild(){const t=this.graphicsDevice;if(null===this.colorMap&&(this.colorMap=this.defaultParamTexture),this.useCpu=this.useCpu||this.sort>F||t.maxVertexTextures<=1||t.fragmentUniformsCount<64||t.forceCpuParticles||!t.extTextureFloat,this._destroyResources(),this.pack8=(this.pack8||!t.textureFloatRenderable)&&!this.useCpu,st=this.useCpu||this.pack8?4:2,this.useMesh=!1,this.mesh){this.numParticles*this.mesh.vertexBuffer.numVertices>65535||(this.useMesh=!0)}this.numParticlesPot=s.nextPowerOfTwo(this.numParticles),this.rebuildGraphs(),this.calculateLocalBounds(),this.resetWorldBounds(),this.node&&(this.worldBounds.setFromTransformedAabb(this.localBounds,this.localSpace?i.IDENTITY:this.node.getWorldTransform()),this.worldBoundsTrail[0].copy(this.worldBounds),this.worldBoundsTrail[1].copy(this.worldBounds),this.worldBoundsSize.copy(this.worldBounds.halfExtents).mulScalar(2),this.prevWorldBoundsSize.copy(this.worldBoundsSize),this.prevWorldBoundsCenter.copy(this.worldBounds.center),this.pack8&&this.calculateBoundsMad()),this.vbToSort=new Array(this.numParticles);for(let t=0;t<this.numParticles;t++)this.vbToSort[t]=[0,0];this.particleDistance=new Float32Array(this.numParticles),this._gpuUpdater.randomize(),this.particleTex=new Float32Array(this.numParticlesPot*st*4);const e=null===this.node||this.localSpace?a.ZERO:this.node.getPosition();this.emitterShape===I?(null===this.node||this.localSpace?at.setTRS(a.ZERO,r.IDENTITY,this.emitterExtents):at.setTRS(a.ZERO,this.node.getRotation(),ht.copy(this.emitterExtents).mul(this.node.localScale)),rt[0]=0!==this.emitterExtents.x?this.emitterExtentsInner.x/this.emitterExtents.x:0,rt[1]=0!==this.emitterExtents.y?this.emitterExtentsInner.y/this.emitterExtents.y:0,rt[2]=0!==this.emitterExtents.z?this.emitterExtentsInner.z/this.emitterExtents.z:0):this.emitterShape===E||(this.emitterShape===R||this.emitterShape===z||this.emitterShape===V?null===this.node||this.localSpace?at.setIdentity():at.setTRS(a.ZERO,this.node.getRotation(),this.node.localScale):console.warn(`ParticleEmitter: Unknown emitter shape ${this.emitterShape}`));for(let t=0;t<this.numParticles;t++)this._cpuUpdater.calcSpawnPosition(this.particleTex,at,rt,e,t),this.useCpu&&(this.particleTex[4*t+3+2*this.numParticlesPot*4]=1);this.particleTexStart=new Float32Array(this.numParticlesPot*st*4);for(let t=0;t<this.particleTexStart.length;t++)this.particleTexStart[t]=this.particleTex[t];this.useCpu||(this.pack8?(this.particleTexIN=H(t,this.numParticlesPot,st,this.particleTex,P,1,!1),this.particleTexOUT=H(t,this.numParticlesPot,st,this.particleTex,P,1,!1),this.particleTexStart=H(t,this.numParticlesPot,st,this.particleTexStart,P,1,!1)):(this.particleTexIN=H(t,this.numParticlesPot,st,this.particleTex),this.particleTexOUT=H(t,this.numParticlesPot,st,this.particleTex),this.particleTexStart=H(t,this.numParticlesPot,st,this.particleTexStart)),this.rtParticleTexIN=new v({colorBuffer:this.particleTexIN,depth:!1}),this.rtParticleTexOUT=new v({colorBuffer:this.particleTexOUT,depth:!1}),this.swapTex=!1);let h="";this.emitterShape===I?h=$.particleUpdaterAABBPS:this.emitterShape===E?h=$.particleUpdaterSpherePS:this.emitterShape===R?h=$.particleUpdaterHemispherePS:this.emitterShape===z?h=$.particleUpdaterCylinderPS:this.emitterShape===V?h=$.particleUpdaterConePS:console.warn(`ParticleEmitter: Unknown emitter shape ${this.emitterShape}`);const n=(this.localSpace?"#define LOCAL_SPACE\n":"")+$.particleUpdaterInitPS+(this.pack8?$.particleInputRgba8PS+$.particleOutputRgba8PS:$.particleInputFloatPS+$.particleOutputFloatPS)+h+$.particleUpdaterStartPS,m=n+$.particleUpdaterRespawnPS+$.particleUpdaterEndPS,c=n+$.particleUpdaterNoRespawnPS+$.particleUpdaterEndPS,p=n+$.particleUpdaterOnStopPS+$.particleUpdaterEndPS,d=`${this.emitterShape}${this.pack8}${this.localSpace}`;this.shaderParticleUpdateRespawn=W(t,$.fullscreenQuadVS,m,`fsQuad0${d}`),this.shaderParticleUpdateNoRespawn=W(t,$.fullscreenQuadVS,c,`fsQuad1${d}`),this.shaderParticleUpdateOnStop=W(t,$.fullscreenQuadVS,p,`fsQuad2${d}`),this.numParticleVerts=this.useMesh?this.mesh.vertexBuffer.numVertices:4,this.numParticleIndices=this.useMesh?this.mesh.indexBuffer[0].numIndices:6,this._allocate(this.numParticles);const u=new O(t);u.vertexBuffer=this.vertexBuffer,u.indexBuffer[0]=this.indexBuffer,u.primitive[0].type=o,u.primitive[0].base=0,u.primitive[0].count=this.numParticles*this.numParticleIndices,u.primitive[0].indexed=!0,this.material=new L,this.material.name=this.node.name,this.material.cull=l,this.material.alphaWrite=!1,this.material.blendType=this.blendType,this.material.depthWrite=this.depthWrite,this.material.emitter=this,this.regenShader(),this.resetMaterial();const f=!this.meshInstance||this.meshInstance.visible;this.meshInstance=new k(u,this.material,this.node),this.meshInstance.pick=!1,this.meshInstance.updateKey(),this.meshInstance.cull=!0,this.localSpace?this.meshInstance.aabb.setFromTransformedAabb(this.worldBounds,this.node.getWorldTransform()):this.meshInstance.aabb.copy(this.worldBounds),this.meshInstance._updateAabb=!1,this.meshInstance.visible=f,this._initializeTextures(),this.resetTime(),this.addTime(0,!1),this.preWarm&&this.prewarm(this.lifetime)}_isAnimated(){return this.animNumFrames>=1&&(this.animTilesX>1||this.animTilesY>1)&&(this.colorMap&&this.colorMap!==this.defaultParamTexture||this.normalMap)}rebuildGraphs(){const t=this.precision,e=this.graphicsDevice;this.qLocalVelocity=this.localVelocityGraph.quantize(t),this.qVelocity=this.velocityGraph.quantize(t),this.qColor=this.colorGraph.quantizeClamped(t,0,1),this.qRotSpeed=this.rotationSpeedGraph.quantize(t),this.qScale=this.scaleGraph.quantize(t),this.qAlpha=this.alphaGraph.quantize(t),this.qRadialSpeed=this.radialSpeedGraph.quantize(t),this.qLocalVelocity2=this.localVelocityGraph2.quantize(t),this.qVelocity2=this.velocityGraph2.quantize(t),this.qColor2=this.colorGraph2.quantizeClamped(t,0,1),this.qRotSpeed2=this.rotationSpeedGraph2.quantize(t),this.qScale2=this.scaleGraph2.quantize(t),this.qAlpha2=this.alphaGraph2.quantize(t),this.qRadialSpeed2=this.radialSpeedGraph2.quantize(t);for(let e=0;e<t;e++)this.qRotSpeed[e]*=s.DEG_TO_RAD,this.qRotSpeed2[e]*=s.DEG_TO_RAD;if(this.localVelocityUMax=new Float32Array(3),this.velocityUMax=new Float32Array(3),this.colorUMax=new Float32Array(3),this.rotSpeedUMax=[0],this.scaleUMax=[0],this.alphaUMax=[0],this.radialSpeedUMax=[0],this.qLocalVelocityDiv=ft(this.qLocalVelocity,this.qLocalVelocity2,this.localVelocityUMax),this.qVelocityDiv=ft(this.qVelocity,this.qVelocity2,this.velocityUMax),this.qColorDiv=ft(this.qColor,this.qColor2,this.colorUMax),this.qRotSpeedDiv=ft(this.qRotSpeed,this.qRotSpeed2,this.rotSpeedUMax),this.qScaleDiv=ft(this.qScale,this.qScale2,this.scaleUMax),this.qAlphaDiv=ft(this.qAlpha,this.qAlpha2,this.alphaUMax),this.qRadialSpeedDiv=ft(this.qRadialSpeed,this.qRadialSpeed2,this.radialSpeedUMax),this.pack8){const t=[0,0,0];ut(this.qVelocity,t);const e=[0,0,0];ut(this.qVelocity2,e);const i=[0,0,0];ut(this.qLocalVelocity,i);const s=[0,0,0];ut(this.qLocalVelocity2,s);const r=[0];ut(this.qRadialSpeed,r);const a=[0];ut(this.qRadialSpeed2,a);let h=Math.max(t[0],e[0]);h=Math.max(h,t[1]),h=Math.max(h,e[1]),h=Math.max(h,t[2]),h=Math.max(h,e[2]);let n=Math.max(i[0],s[0]);n=Math.max(n,i[1]),n=Math.max(n,s[1]),n=Math.max(n,i[2]),n=Math.max(n,s[2]);const o=Math.max(r[0],a[0]);this.maxVel=h+n+o}this.useCpu||(this.internalTex0=H(e,t,1,dt(this.qLocalVelocity,this.qLocalVelocityDiv)),this.internalTex1=H(e,t,1,dt(this.qVelocity,this.qVelocityDiv)),this.internalTex2=H(e,t,1,function(t,e,i,s,r){const a=new Array(4*t.length);for(let h=0;h<t.length;h++)a[4*h]=t[h],a[4*h+1]=e[h],a[4*h+2]=0,a[4*h+3]=pt(i[h],s[h],r[h]);return a}(this.qRotSpeed,this.qScale,this.qScaleDiv,this.qRotSpeedDiv,this.qAlphaDiv)),this.internalTex3=H(e,t,1,function(t,e){const i=new Array(4*t.length);for(let s=0;s<t.length;s++)i[4*s]=t[s],i[4*s+1]=e[s],i[4*s+2]=0,i[4*s+3]=0;return i}(this.qRadialSpeed,this.qRadialSpeedDiv))),this.colorParam=H(e,t,1,function(t,e){const i=new Array(4*e.length);for(let s=0;s<e.length;s++)i[4*s]=t[3*s],i[4*s+1]=t[3*s+1],i[4*s+2]=t[3*s+2],i[4*s+3]=e[s];return i}(this.qColor,this.qAlpha),P,1,!0)}_initializeTextures(){this.colorMap&&(this.material.setParameter("colorMap",this.colorMap),this.lighting&&this.normalMap&&this.material.setParameter("normalMap",this.normalMap))}regenShader(){const t=j(this.graphicsDevice);t.register("particle",X);const e=null!==this.normalMap;this.normalOption=0,this.lighting&&(this.normalOption=e?2:1),this.material.getShaderVariant=function(e,i,s,r,a,h,n,o){this.emitter.scene&&this.emitter.camera!==this.emitter.scene._activeCamera&&(this.emitter.camera=this.emitter.scene._activeCamera,this.emitter.onChangeCamera());const l=this.emitter.inTools,m=new A(n,o);return t.getProgram("particle",{pass:C,useCpu:this.emitter.useCpu,normal:this.emitter.normalOption,halflambert:this.emitter.halfLambert,stretch:this.emitter.stretch,alignToMotion:this.emitter.alignToMotion,soft:this.emitter.depthSoftening,mesh:this.emitter.useMesh,gamma:this.emitter.scene?this.emitter.scene.gammaCorrection:0,toneMap:this.emitter.scene?this.emitter.scene.toneMapping:0,fog:this.emitter.scene&&!this.emitter.noFog?this.emitter.scene.fog:"none",wrap:this.emitter.wrap&&this.emitter.wrapBounds,localSpace:this.emitter.localSpace,screenSpace:!l&&this.emitter.screenSpace,blend:this.blendType,animTex:this.emitter._isAnimated(),animTexLoop:this.emitter.animLoop,pack8:this.emitter.pack8,customFace:this.emitter.orientation!==N},m)},this.material.shader=this.material.getShaderVariant()}resetMaterial(){const t=this.material;t.setParameter("stretch",this.stretch),this._isAnimated()&&(t.setParameter("animTexTilesParams",this.animTilesParams),t.setParameter("animTexParams",this.animParams),t.setParameter("animTexIndexParams",this.animIndexParams)),t.setParameter("colorMult",this.intensity),this.useCpu||(t.setParameter("internalTex0",this.internalTex0),t.setParameter("internalTex1",this.internalTex1),t.setParameter("internalTex2",this.internalTex2),t.setParameter("internalTex3",this.internalTex3)),t.setParameter("colorParam",this.colorParam),t.setParameter("numParticles",this.numParticles),t.setParameter("numParticlesPot",this.numParticlesPot),t.setParameter("lifetime",this.lifetime),t.setParameter("rate",this.rate),t.setParameter("rateDiv",this.rate2-this.rate),t.setParameter("seed",this.seed),t.setParameter("scaleDivMult",this.scaleUMax[0]),t.setParameter("alphaDivMult",this.alphaUMax[0]),t.setParameter("radialSpeedDivMult",this.radialSpeedUMax[0]),t.setParameter("graphNumSamples",this.precision),t.setParameter("graphSampleSize",1/this.precision),t.setParameter("emitterScale",new Float32Array([1,1,1])),this.pack8&&(this._gpuUpdater._setInputBounds(),t.setParameter("inBoundsSize",this._gpuUpdater.inBoundsSizeUniform),t.setParameter("inBoundsCenter",this._gpuUpdater.inBoundsCenterUniform),t.setParameter("maxVel",this.maxVel)),this.wrap&&this.wrapBounds&&(this.wrapBoundsUniform[0]=this.wrapBounds.x,this.wrapBoundsUniform[1]=this.wrapBounds.y,this.wrapBoundsUniform[2]=this.wrapBounds.z,t.setParameter("wrapBounds",this.wrapBoundsUniform)),this.colorMap&&t.setParameter("colorMap",this.colorMap),this.lighting&&this.normalMap&&t.setParameter("normalMap",this.normalMap),this.depthSoftening>0&&t.setParameter("softening",1/(this.depthSoftening*this.depthSoftening*100)),this.stretch>0&&(t.cull=l),this._compParticleFaceParams()}_compParticleFaceParams(){let t,e;if(this.orientation===N)t=new Float32Array([1,0,0]),e=new Float32Array([0,0,1]);else{let s;if(this.orientation===_)s=this.particleNormal.normalize();else{s=(null===this.node?i.IDENTITY:this.node.getWorldTransform()).transformVector(this.particleNormal).normalize()}const r=new a(1,0,0);1===Math.abs(r.dot(s))&&r.set(0,0,1);const h=(new a).cross(s,r).normalize();r.cross(h,s).normalize(),t=new Float32Array([r.x,r.y,r.z]),e=new Float32Array([h.x,h.y,h.z])}this.material.setParameter("faceTangent",t),this.material.setParameter("faceBinorm",e)}_allocate(t){const e=t*this.numParticleVerts,i=t*this.numParticleIndices;if(void 0===this.vertexBuffer||this.vertexBuffer.getNumVertices()!==e){if(this.useCpu){const t=[{semantic:p,components:4,type:d},{semantic:u,components:4,type:d},{semantic:f,components:4,type:d},{semantic:x,components:1,type:d},{semantic:S,components:this.useMesh?4:2,type:d}],s=new q(this.graphicsDevice,t);this.vertexBuffer=new b(this.graphicsDevice,s,e,{usage:m}),this.indexBuffer=new M(this.graphicsDevice,c,i)}else{const t=[{semantic:p,components:4,type:d}];this.useMesh&&t.push({semantic:u,components:2,type:d});const s=new q(this.graphicsDevice,t);this.vertexBuffer=new b(this.graphicsDevice,s,e,{usage:m}),this.indexBuffer=new M(this.graphicsDevice,c,i)}const s=new Float32Array(this.vertexBuffer.lock());let r,a,h;if(this.useMesh){r=new Float32Array(this.mesh.vertexBuffer.lock()),a=r.length/this.mesh.vertexBuffer.numVertices;for(let t=0;t<this.mesh.vertexBuffer.format.elements.length;t++)if(this.mesh.vertexBuffer.format.elements[t].name===T){h=this.mesh.vertexBuffer.format.elements[t].offset/4;break}}for(let t=0;t<e;t++){const e=Math.floor(t/this.numParticleVerts);if(this.useMesh){const i=t%this.numParticleVerts;s[6*t]=r[i*a],s[6*t+1]=r[i*a+1],s[6*t+2]=r[i*a+2],s[6*t+3]=e,s[6*t+4]=r[i*a+h+0],s[6*t+5]=1-r[i*a+h+1]}else{const i=t%4;s[4*t]=Q[i][0],s[4*t+1]=Q[i][1],s[4*t+2]=0,s[4*t+3]=e}}this.useCpu&&(this.vbCPU=new Float32Array(s),this.vbOld=new Float32Array(this.vbCPU.length)),this.vertexBuffer.unlock(),this.useMesh&&this.mesh.vertexBuffer.unlock();let n=0;const o=new Uint16Array(this.indexBuffer.lock());this.useMesh&&(r=new Uint16Array(this.mesh.indexBuffer[0].lock()));for(let e=0;e<t;e++)if(this.useMesh)for(let t=0;t<this.numParticleIndices;t++)o[e*this.numParticleIndices+t]=r[t]+e*this.numParticleVerts;else{const t=4*e;o[n++]=t,o[n++]=t+1,o[n++]=t+2,o[n++]=t,o[n++]=t+2,o[n++]=t+3}this.indexBuffer.unlock(),this.useMesh&&this.mesh.indexBuffer[0].unlock()}}reset(){if(this.beenReset=!0,this.seed=Math.random(),this.material.setParameter("seed",this.seed),this.useCpu)for(let t=0;t<this.particleTexStart.length;t++)this.particleTex[t]=this.particleTexStart[t];else this._initializeTextures();this.resetWorldBounds(),this.resetTime();const t=this.loop;this.loop=!0,this.addTime(0,!1),this.loop=t,this.preWarm&&this.prewarm(this.lifetime)}prewarm(t){const e=t/this.lifetime,i=Math.min(Math.floor(e*this.precision),this.precision),s=t/i;for(let t=0;t<i;t++)this.addTime(s,!1)}resetTime(){this.endTime=function(t){const e=Math.max(t.rate,t.rate2)*t.numParticles+t.lifetime;return Date.now()+1e3*e}(this)}finishFrame(){this.useCpu&&this.vertexBuffer.unlock()}addTime(t,e){const i=this.graphicsDevice;if(this.simTimeTotal+=t,this.calculateWorldBounds(),this._isAnimated()){const t=this.animTilesParams;t[0]=1/this.animTilesX,t[1]=1/this.animTilesY;const e=this.animParams;e[0]=this.animStartFrame,e[1]=this.animNumFrames*this.animSpeed,e[2]=this.animNumFrames-1,e[3]=this.animNumAnimations-1;const i=this.animIndexParams;i[0]=this.animIndex,i[1]=this.randomizeAnimIndex}let s;this.scene&&this.camera!==this.scene._activeCamera&&(this.camera=this.scene._activeCamera,this.onChangeCamera()),this.emitterShape===I?(rt[0]=0!==this.emitterExtents.x?this.emitterExtentsInner.x/this.emitterExtents.x:0,rt[1]=0!==this.emitterExtents.y?this.emitterExtentsInner.y/this.emitterExtents.y:0,rt[2]=0!==this.emitterExtents.z?this.emitterExtentsInner.z/this.emitterExtents.z:0,null===this.meshInstance.node?at.setTRS(a.ZERO,r.IDENTITY,this.emitterExtents):at.setTRS(a.ZERO,this.meshInstance.node.getRotation(),ht.copy(this.emitterExtents).mul(this.meshInstance.node.localScale))):this.emitterShape===E||(this.emitterShape===R||this.emitterShape===z||this.emitterShape===V?null===this.node||this.localSpace?at.setIdentity():at.setTRS(a.ZERO,this.node.getRotation(),this.node.localScale):console.warn(`ParticleEmitter: Unknown emitter shape ${this.emitterShape}`));const h=null===this.meshInstance.node?a.ONE:this.meshInstance.node.localScale;if(this.emitterScaleUniform[0]=h.x,this.emitterScaleUniform[1]=h.y,this.emitterScaleUniform[2]=h.z,this.material.setParameter("emitterScale",this.emitterScaleUniform),this.localSpace&&this.meshInstance.node&&(s=this.meshInstance.node.getPosition(),this.emitterPosUniform[0]=s.x,this.emitterPosUniform[1]=s.y,this.emitterPosUniform[2]=s.z,this.material.setParameter("emitterPos",this.emitterPosUniform)),this._compParticleFaceParams(),this.useCpu){const i=new Float32Array(this.vertexBuffer.lock());this._cpuUpdater.update(i,this.vbToSort,this.particleTex,at,rt,s,t,e)}else this._gpuUpdater.update(i,at,rt,t,e);this.loop||Date.now()>this.endTime&&(this.onFinished&&this.onFinished(),this.meshInstance.visible=!1),this.meshInstance&&(this.meshInstance.drawOrder=this.drawOrder)}_destroyResources(){this.particleTexIN&&(this.particleTexIN.destroy(),this.particleTexIN=null),this.particleTexOUT&&(this.particleTexOUT.destroy(),this.particleTexOUT=null),this.particleTexStart&&this.particleTexStart.destroy&&(this.particleTexStart.destroy(),this.particleTexStart=null),this.rtParticleTexIN&&(this.rtParticleTexIN.destroy(),this.rtParticleTexIN=null),this.rtParticleTexOUT&&(this.rtParticleTexOUT.destroy(),this.rtParticleTexOUT=null),this.internalTex0&&(this.internalTex0.destroy(),this.internalTex0=null),this.internalTex1&&(this.internalTex1.destroy(),this.internalTex1=null),this.internalTex2&&(this.internalTex2.destroy(),this.internalTex2=null),this.internalTex3&&(this.internalTex3.destroy(),this.internalTex3=null),this.colorParam&&(this.colorParam.destroy(),this.colorParam=null),this.vertexBuffer&&(this.vertexBuffer.destroy(),this.vertexBuffer=void 0),this.indexBuffer&&(this.indexBuffer.destroy(),this.indexBuffer=void 0),this.material&&(this.material.destroy(),this.material=null)}destroy(){this.camera=null,this._destroyResources()}}export{St as ParticleEmitter};