gpuUpdateParticles.compute.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Do not edit.
  2. import { ShaderStore } from "../Engines/shaderStore.js";
  3. const name = "gpuUpdateParticlesComputeShader";
  4. const shader = `struct Particle {position : vec3<f32>,
  5. age : f32,
  6. size : vec3<f32>,
  7. life : f32,
  8. seed : vec4<f32>,
  9. direction : vec3<f32>,
  10. dummy0: f32,
  11. #ifdef CUSTOMEMITTER
  12. initialPosition : vec3<f32>,
  13. dummy1: f32,
  14. #endif
  15. #ifndef COLORGRADIENTS
  16. color : vec4<f32>,
  17. #endif
  18. #ifndef BILLBOARD
  19. initialDirection : vec3<f32>,
  20. dummy2: f32,
  21. #endif
  22. #ifdef NOISE
  23. noiseCoordinates1 : vec3<f32>,
  24. dummy3: f32,
  25. noiseCoordinates2 : vec3<f32>,
  26. dummy4: f32,
  27. #endif
  28. #ifdef ANGULARSPEEDGRADIENTS
  29. angle : f32,
  30. #else
  31. angle : vec2<f32>,
  32. #endif
  33. #ifdef ANIMATESHEET
  34. cellIndex : f32,
  35. #ifdef ANIMATESHEETRANDOMSTART
  36. cellStartOffset : f32,
  37. #endif
  38. #endif
  39. };struct Particles {particles : array<Particle>,};struct SimParams {currentCount : f32,
  40. timeDelta : f32,
  41. stopFactor : f32,
  42. randomTextureSize: i32,
  43. lifeTime : vec2<f32>,
  44. emitPower : vec2<f32>,
  45. #ifndef COLORGRADIENTS
  46. color1 : vec4<f32>,
  47. color2 : vec4<f32>,
  48. #endif
  49. sizeRange : vec2<f32>,
  50. scaleRange : vec4<f32>,
  51. angleRange : vec4<f32>,
  52. gravity : vec3<f32>,
  53. #ifdef LIMITVELOCITYGRADIENTS
  54. limitVelocityDamping : f32,
  55. #endif
  56. #ifdef ANIMATESHEET
  57. cellInfos : vec4<f32>,
  58. #endif
  59. #ifdef NOISE
  60. noiseStrength : vec3<f32>,
  61. #endif
  62. #ifndef LOCAL
  63. emitterWM : mat4x4<f32>,
  64. #endif
  65. #ifdef BOXEMITTER
  66. direction1 : vec3<f32>,
  67. direction2 : vec3<f32>,
  68. minEmitBox : vec3<f32>,
  69. maxEmitBox : vec3<f32>,
  70. #endif
  71. #ifdef CONEEMITTER
  72. radius : vec2<f32>,
  73. coneAngle : f32,
  74. height : vec2<f32>,
  75. directionRandomizer : f32,
  76. #endif
  77. #ifdef CYLINDEREMITTER
  78. radius : f32,
  79. height : f32,
  80. radiusRange : f32,
  81. #ifdef DIRECTEDCYLINDEREMITTER
  82. direction1 : vec3<f32>,
  83. direction2 : vec3<f32>,
  84. #else
  85. directionRandomizer : f32,
  86. #endif
  87. #endif
  88. #ifdef HEMISPHERICEMITTER
  89. radius : f32,
  90. radiusRange : f32,
  91. directionRandomizer : f32,
  92. #endif
  93. #ifdef POINTEMITTER
  94. direction1 : vec3<f32>,
  95. direction2 : vec3<f32>,
  96. #endif
  97. #ifdef SPHEREEMITTER
  98. radius : f32,
  99. radiusRange : f32,
  100. #ifdef DIRECTEDSPHEREEMITTER
  101. direction1 : vec3<f32>,
  102. direction2 : vec3<f32>,
  103. #else
  104. directionRandomizer : f32,
  105. #endif
  106. #endif
  107. };@binding(0) @group(0) var<uniform> params : SimParams;@binding(1) @group(0) var<storage,read> particlesIn : Particles;@binding(2) @group(0) var<storage,read_write> particlesOut : Particles;@binding(3) @group(0) var randomTexture : texture_2d<f32>;@binding(4) @group(0) var randomTexture2 : texture_2d<f32>;
  108. #ifdef SIZEGRADIENTS
  109. @binding(0) @group(1) var sizeGradientSampler : sampler;@binding(1) @group(1) var sizeGradientTexture : texture_2d<f32>;
  110. #endif
  111. #ifdef ANGULARSPEEDGRADIENTS
  112. @binding(2) @group(1) var angularSpeedGradientSampler : sampler;@binding(3) @group(1) var angularSpeedGradientTexture : texture_2d<f32>;
  113. #endif
  114. #ifdef VELOCITYGRADIENTS
  115. @binding(4) @group(1) var velocityGradientSampler : sampler;@binding(5) @group(1) var velocityGradientTexture : texture_2d<f32>;
  116. #endif
  117. #ifdef LIMITVELOCITYGRADIENTS
  118. @binding(6) @group(1) var limitVelocityGradientSampler : sampler;@binding(7) @group(1) var limitVelocityGradientTexture : texture_2d<f32>;
  119. #endif
  120. #ifdef DRAGGRADIENTS
  121. @binding(8) @group(1) var dragGradientSampler : sampler;@binding(9) @group(1) var dragGradientTexture : texture_2d<f32>;
  122. #endif
  123. #ifdef NOISE
  124. @binding(10) @group(1) var noiseSampler : sampler;@binding(11) @group(1) var noiseTexture : texture_2d<f32>;
  125. #endif
  126. fn getRandomVec3(offset : f32,vertexID : f32)->vec3<f32> {return textureLoad(randomTexture2,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0).rgb;}
  127. fn getRandomVec4(offset : f32,vertexID : f32)->vec4<f32> {return textureLoad(randomTexture,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0);}
  128. @compute @workgroup_size(64)
  129. fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {let index : u32=GlobalInvocationID.x;let vertexID : f32=f32(index);if (index>=u32(params.currentCount)) {return;}
  130. let PI : f32=3.14159;let timeDelta : f32=params.timeDelta;let newAge : f32=particlesIn.particles[index].age+timeDelta;let life : f32=particlesIn.particles[index].life;let seed : vec4<f32>=particlesIn.particles[index].seed;let direction : vec3<f32>=particlesIn.particles[index].direction;if (newAge>=life && params.stopFactor != 0.) {var newPosition : vec3<f32>;var newDirection : vec3<f32>;let randoms : vec4<f32>=getRandomVec4(seed.x,vertexID);let outLife : f32=params.lifeTime.x+(params.lifeTime.y-params.lifeTime.x)*randoms.r;particlesOut.particles[index].life=outLife;particlesOut.particles[index].age=newAge-life;particlesOut.particles[index].seed=seed;var sizex : f32;
  131. #ifdef SIZEGRADIENTS
  132. sizex=textureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(0.,0.),0.).r;
  133. #else
  134. sizex=params.sizeRange.x+(params.sizeRange.y-params.sizeRange.x)*randoms.g;
  135. #endif
  136. particlesOut.particles[index].size=vec3<f32>(
  137. sizex,
  138. params.scaleRange.x+(params.scaleRange.y-params.scaleRange.x)*randoms.b,
  139. params.scaleRange.z+(params.scaleRange.w-params.scaleRange.z)*randoms.a);
  140. #ifndef COLORGRADIENTS
  141. particlesOut.particles[index].color=params.color1+(params.color2-params.color1)*randoms.b;
  142. #endif
  143. #ifndef ANGULARSPEEDGRADIENTS
  144. particlesOut.particles[index].angle=vec2<f32>(
  145. params.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r,
  146. params.angleRange.x+(params.angleRange.y-params.angleRange.x)*randoms.a);
  147. #else
  148. particlesOut.particles[index].angle=params.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r;
  149. #endif
  150. #if defined(POINTEMITTER)
  151. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=vec3<f32>(0.,0.,0.);newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;
  152. #elif defined(BOXEMITTER)
  153. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=params.minEmitBox+(params.maxEmitBox-params.minEmitBox)*randoms2;newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;
  154. #elif defined(HEMISPHERICEMITTER)
  155. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,abs(randY),randZ);newDirection=normalize(newPosition+params.directionRandomizer*randoms3);
  156. #elif defined(SPHEREEMITTER)
  157. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,randY,randZ);
  158. #ifdef DIRECTEDSPHEREEMITTER
  159. newDirection=normalize(params.direction1+(params.direction2-params.direction1)*randoms3);
  160. #else
  161. newDirection=normalize(newPosition+params.directionRandomizer*randoms3);
  162. #endif
  163. #elif defined(CYLINDEREMITTER)
  164. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let yPos : f32=(-0.5+randoms2.x)*params.height;var angle : f32=randoms2.y*PI*2.;let inverseRadiusRangeSquared : f32=(1.-params.radiusRange)*(1.-params.radiusRange);let positionRadius : f32=params.radius*sqrt(inverseRadiusRangeSquared+randoms2.z*(1.-inverseRadiusRangeSquared));let xPos : f32=positionRadius*cos(angle);let zPos : f32=positionRadius*sin(angle);newPosition=vec3<f32>(xPos,yPos,zPos);
  165. #ifdef DIRECTEDCYLINDEREMITTER
  166. newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;
  167. #else
  168. angle=angle+(-0.5+randoms3.x)*PI*params.directionRandomizer;newDirection=vec3<f32>(cos(angle),(-0.5+randoms3.y)*params.directionRandomizer,sin(angle));newDirection=normalize(newDirection);
  169. #endif
  170. #elif defined(CONEEMITTER)
  171. let randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let s : f32=2.0*PI*randoms2.x;
  172. #ifdef CONEEMITTERSPAWNPOINT
  173. let h : f32=0.0001;
  174. #else
  175. var h : f32=randoms2.y*params.height.y;h=1.-h*h;
  176. #endif
  177. var lRadius : f32=params.radius.x-params.radius.x*randoms2.z*params.radius.y;lRadius=lRadius*h;let randX : f32=lRadius*sin(s);let randZ : f32=lRadius*cos(s);let randY : f32=h *params.height.x;newPosition=vec3<f32>(randX,randY,randZ);
  178. if (abs(cos(params.coneAngle))==1.0) {newDirection=vec3<f32>(0.,1.0,0.);} else {let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newDirection=normalize(newPosition+params.directionRandomizer*randoms3); }
  179. #elif defined(CUSTOMEMITTER)
  180. newPosition=particlesIn.particles[index].initialPosition;particlesOut.particles[index].initialPosition=newPosition;
  181. #else
  182. newPosition=vec3<f32>(0.,0.,0.);newDirection=2.0*(getRandomVec3(seed.w,vertexID)-vec3<f32>(0.5,0.5,0.5));
  183. #endif
  184. let power : f32=params.emitPower.x+(params.emitPower.y-params.emitPower.x)*randoms.a;
  185. #ifdef LOCAL
  186. particlesOut.particles[index].position=newPosition;
  187. #else
  188. particlesOut.particles[index].position=(params.emitterWM*vec4<f32>(newPosition,1.)).xyz;
  189. #endif
  190. #ifdef CUSTOMEMITTER
  191. particlesOut.particles[index].direction=direction;
  192. #ifndef BILLBOARD
  193. particlesOut.particles[index].initialDirection=direction;
  194. #endif
  195. #else
  196. #ifdef LOCAL
  197. let initial : vec3<f32>=newDirection;
  198. #else
  199. let initial : vec3<f32>=(params.emitterWM*vec4<f32>(newDirection,0.)).xyz;
  200. #endif
  201. particlesOut.particles[index].direction=initial*power;
  202. #ifndef BILLBOARD
  203. particlesOut.particles[index].initialDirection=initial;
  204. #endif
  205. #endif
  206. #ifdef ANIMATESHEET
  207. particlesOut.particles[index].cellIndex=params.cellInfos.x;
  208. #ifdef ANIMATESHEETRANDOMSTART
  209. particlesOut.particles[index].cellStartOffset=randoms.a*outLife;
  210. #endif
  211. #endif
  212. #ifdef NOISE
  213. particlesOut.particles[index].noiseCoordinates1=particlesIn.particles[index].noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=particlesIn.particles[index].noiseCoordinates2;
  214. #endif
  215. } else {var directionScale : f32=timeDelta;particlesOut.particles[index].age=newAge;let ageGradient : f32=newAge/life;
  216. #ifdef VELOCITYGRADIENTS
  217. directionScale=directionScale*textureSampleLevel(velocityGradientTexture,velocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;
  218. #endif
  219. #ifdef DRAGGRADIENTS
  220. directionScale=directionScale*(1.0-textureSampleLevel(dragGradientTexture,dragGradientSampler,vec2<f32>(ageGradient,0.),0.).r);
  221. #endif
  222. let position : vec3<f32>=particlesIn.particles[index].position;
  223. #if defined(CUSTOMEMITTER)
  224. particlesOut.particles[index].position=position+(direction-position)*ageGradient;
  225. particlesOut.particles[index].initialPosition=particlesIn.particles[index].initialPosition;
  226. #else
  227. particlesOut.particles[index].position=position+direction*directionScale;
  228. #endif
  229. particlesOut.particles[index].life=life;particlesOut.particles[index].seed=seed;
  230. #ifndef COLORGRADIENTS
  231. particlesOut.particles[index].color=particlesIn.particles[index].color;
  232. #endif
  233. #ifdef SIZEGRADIENTS
  234. particlesOut.particles[index].size=vec3<f32>(
  235. textureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(ageGradient,0.),0.).r,
  236. particlesIn.particles[index].size.yz);
  237. #else
  238. particlesOut.particles[index].size=particlesIn.particles[index].size;
  239. #endif
  240. #ifndef BILLBOARD
  241. particlesOut.particles[index].initialDirection=particlesIn.particles[index].initialDirection;
  242. #endif
  243. #ifdef CUSTOMEMITTER
  244. particlesOut.particles[index].direction=direction;
  245. #else
  246. var updatedDirection : vec3<f32>=direction+params.gravity*timeDelta;
  247. #ifdef LIMITVELOCITYGRADIENTS
  248. let limitVelocity : f32=textureSampleLevel(limitVelocityGradientTexture,limitVelocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;let currentVelocity : f32=length(updatedDirection);if (currentVelocity>limitVelocity) {updatedDirection=updatedDirection*params.limitVelocityDamping;}
  249. #endif
  250. particlesOut.particles[index].direction=updatedDirection;
  251. #ifdef NOISE
  252. let noiseCoordinates1 : vec3<f32>=particlesIn.particles[index].noiseCoordinates1;let noiseCoordinates2 : vec3<f32>=particlesIn.particles[index].noiseCoordinates2;let fetchedR : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.x,noiseCoordinates1.y)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedG : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.z,noiseCoordinates2.x)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedB : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates2.y,noiseCoordinates2.z)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let force : vec3<f32>=vec3<f32>(-1.+2.*fetchedR,-1.+2.*fetchedG,-1.+2.*fetchedB)*params.noiseStrength;particlesOut.particles[index].direction=particlesOut.particles[index].direction+force*timeDelta;particlesOut.particles[index].noiseCoordinates1=noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=noiseCoordinates2;
  253. #endif
  254. #endif
  255. #ifdef ANGULARSPEEDGRADIENTS
  256. let angularSpeed : f32=textureSampleLevel(angularSpeedGradientTexture,angularSpeedGradientSampler,vec2<f32>(ageGradient,0.),0.).r;particlesOut.particles[index].angle=particlesIn.particles[index].angle+angularSpeed*timeDelta;
  257. #else
  258. let angle : vec2<f32>=particlesIn.particles[index].angle;particlesOut.particles[index].angle=vec2<f32>(angle.x+angle.y*timeDelta,angle.y);
  259. #endif
  260. #ifdef ANIMATESHEET
  261. var offsetAge : f32=particlesOut.particles[index].age;let dist : f32=params.cellInfos.y-params.cellInfos.x;
  262. #ifdef ANIMATESHEETRANDOMSTART
  263. let cellStartOffset : f32=particlesIn.particles[index].cellStartOffset;particlesOut.particles[index].cellStartOffset=cellStartOffset;offsetAge=offsetAge+cellStartOffset;
  264. #else
  265. let cellStartOffset : f32=0.;
  266. #endif
  267. var ratio : f32;if (params.cellInfos.w==1.0) {ratio=clamp(((cellStartOffset+params.cellInfos.z*offsetAge) % life)/life,0.,1.0);}
  268. else {ratio=clamp((cellStartOffset+params.cellInfos.z*offsetAge)/life,0.,1.0);}
  269. particlesOut.particles[index].cellIndex=f32(i32(params.cellInfos.x+ratio*dist));
  270. #endif
  271. }}
  272. `;
  273. // Sideeffect
  274. ShaderStore.ShadersStoreWGSL[name] = shader;
  275. /** @internal */
  276. export const gpuUpdateParticlesComputeShader = { name, shader };
  277. //# sourceMappingURL=gpuUpdateParticles.compute.js.map