gpuUpdateParticles.vertex.fx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #version 300 es
  2. #define PI 3.14159
  3. uniform float currentCount;
  4. uniform float timeDelta;
  5. uniform float stopFactor;
  6. uniform mat4 emitterWM;
  7. uniform vec2 lifeTime;
  8. uniform vec2 emitPower;
  9. uniform vec2 sizeRange;
  10. uniform vec4 scaleRange;
  11. #ifndef COLORGRADIENTS
  12. uniform vec4 color1;
  13. uniform vec4 color2;
  14. #endif
  15. uniform vec3 gravity;
  16. uniform sampler2D randomSampler;
  17. uniform sampler2D randomSampler2;
  18. uniform vec4 angleRange;
  19. #ifdef BOXEMITTER
  20. uniform vec3 direction1;
  21. uniform vec3 direction2;
  22. uniform vec3 minEmitBox;
  23. uniform vec3 maxEmitBox;
  24. #endif
  25. #ifdef POINTEMITTER
  26. uniform vec3 direction1;
  27. uniform vec3 direction2;
  28. #endif
  29. #ifdef SPHEREEMITTER
  30. uniform float radius;
  31. uniform float radiusRange;
  32. #ifdef DIRECTEDSPHEREEMITTER
  33. uniform vec3 direction1;
  34. uniform vec3 direction2;
  35. #else
  36. uniform float directionRandomizer;
  37. #endif
  38. #endif
  39. #ifdef CONEEMITTER
  40. uniform vec2 radius;
  41. uniform float coneAngle;
  42. uniform vec2 height;
  43. uniform float directionRandomizer;
  44. #endif
  45. // Particles state
  46. in vec3 position;
  47. in float age;
  48. in float life;
  49. in vec4 seed;
  50. in vec3 size;
  51. #ifndef COLORGRADIENTS
  52. in vec4 color;
  53. #endif
  54. in vec3 direction;
  55. #ifndef BILLBOARD
  56. in vec3 initialDirection;
  57. #endif
  58. #ifdef ANGULARSPEEDGRADIENTS
  59. in float angle;
  60. #else
  61. in vec2 angle;
  62. #endif
  63. #ifdef ANIMATESHEET
  64. in float cellIndex;
  65. #endif
  66. // Output
  67. out vec3 outPosition;
  68. out float outAge;
  69. out float outLife;
  70. out vec4 outSeed;
  71. out vec3 outSize;
  72. #ifndef COLORGRADIENTS
  73. out vec4 outColor;
  74. #endif
  75. out vec3 outDirection;
  76. #ifndef BILLBOARD
  77. out vec3 outInitialDirection;
  78. #endif
  79. #ifdef ANGULARSPEEDGRADIENTS
  80. out float outAngle;
  81. #else
  82. out vec2 outAngle;
  83. #endif
  84. #ifdef ANIMATESHEET
  85. out float outCellIndex;
  86. #endif
  87. #ifdef SIZEGRADIENTS
  88. uniform sampler2D sizeGradientSampler;
  89. #endif
  90. #ifdef ANGULARSPEEDGRADIENTS
  91. uniform sampler2D angularSpeedGradientSampler;
  92. #endif
  93. #ifdef VELOCITYGRADIENTS
  94. uniform sampler2D velocityGradientSampler;
  95. #endif
  96. #ifdef NOISE
  97. uniform vec3 noiseStrength;
  98. uniform sampler2D noiseSampler;
  99. #endif
  100. #ifdef ANIMATESHEET
  101. uniform vec3 cellInfos;
  102. #endif
  103. vec3 getRandomVec3(float offset) {
  104. return texture(randomSampler2, vec2(float(gl_VertexID) * offset / currentCount, 0)).rgb;
  105. }
  106. vec4 getRandomVec4(float offset) {
  107. return texture(randomSampler, vec2(float(gl_VertexID) * offset / currentCount, 0));
  108. }
  109. void main() {
  110. if (age >= life) {
  111. if (stopFactor == 0.) {
  112. outPosition = position;
  113. outAge = life;
  114. outLife = life;
  115. outSeed = seed;
  116. #ifndef COLORGRADIENTS
  117. outColor = vec4(0.,0.,0.,0.);
  118. #endif
  119. outSize = vec3(0., 0., 0.);
  120. #ifndef BILLBOARD
  121. outInitialDirection = initialDirection;
  122. #endif
  123. outDirection = direction;
  124. outAngle = angle;
  125. #ifdef ANIMATESHEET
  126. outCellIndex = cellIndex;
  127. #endif
  128. return;
  129. }
  130. vec3 position;
  131. vec3 direction;
  132. // Let's get some random values
  133. vec4 randoms = getRandomVec4(seed.x);
  134. // Age and life
  135. outAge = 0.0;
  136. outLife = lifeTime.x + (lifeTime.y - lifeTime.x) * randoms.r;
  137. // Seed
  138. outSeed = seed;
  139. // Size
  140. #ifdef SIZEGRADIENTS
  141. outSize.x = texture(sizeGradientSampler, vec2(0, 0)).r;
  142. #else
  143. outSize.x = sizeRange.x + (sizeRange.y - sizeRange.x) * randoms.g;
  144. #endif
  145. outSize.y = scaleRange.x + (scaleRange.y - scaleRange.x) * randoms.b;
  146. outSize.z = scaleRange.z + (scaleRange.w - scaleRange.z) * randoms.a;
  147. #ifndef COLORGRADIENTS
  148. // Color
  149. outColor = color1 + (color2 - color1) * randoms.b;
  150. #endif
  151. // Angular speed
  152. #ifndef ANGULARSPEEDGRADIENTS
  153. outAngle.y = angleRange.x + (angleRange.y - angleRange.x) * randoms.a;
  154. outAngle.x = angleRange.z + (angleRange.w - angleRange.z) * randoms.r;
  155. #else
  156. outAngle = angleRange.z + (angleRange.w - angleRange.z) * randoms.r;
  157. #endif
  158. // Position / Direction (based on emitter type)
  159. #ifdef POINTEMITTER
  160. vec3 randoms2 = getRandomVec3(seed.y);
  161. vec3 randoms3 = getRandomVec3(seed.z);
  162. position = vec3(0, 0, 0);
  163. direction = direction1 + (direction2 - direction1) * randoms3;
  164. #elif defined(BOXEMITTER)
  165. vec3 randoms2 = getRandomVec3(seed.y);
  166. vec3 randoms3 = getRandomVec3(seed.z);
  167. position = minEmitBox + (maxEmitBox - minEmitBox) * randoms2;
  168. direction = direction1 + (direction2 - direction1) * randoms3;
  169. #elif defined(SPHEREEMITTER)
  170. vec3 randoms2 = getRandomVec3(seed.y);
  171. vec3 randoms3 = getRandomVec3(seed.z);
  172. // Position on the sphere surface
  173. float phi = 2.0 * PI * randoms2.x;
  174. float theta = acos(2.0 * randoms2.y - 1.0);
  175. float randX = cos(phi) * sin(theta);
  176. float randY = cos(theta);
  177. float randZ = sin(phi) * sin(theta);
  178. position = (radius - (radius * radiusRange * randoms2.z)) * vec3(randX, randY, randZ);
  179. #ifdef DIRECTEDSPHEREEMITTER
  180. direction = direction1 + (direction2 - direction1) * randoms3;
  181. #else
  182. // Direction
  183. direction = position + directionRandomizer * randoms3;
  184. #endif
  185. #elif defined(CONEEMITTER)
  186. vec3 randoms2 = getRandomVec3(seed.y);
  187. float s = 2.0 * PI * randoms2.x;
  188. float h = randoms2.y * height.y;
  189. // Better distribution in a cone at normal angles.
  190. h = 1. - h * h;
  191. float lRadius = radius.x - radius.x * randoms2.z * radius.y;
  192. lRadius = lRadius * h;
  193. float randX = lRadius * sin(s);
  194. float randZ = lRadius * cos(s);
  195. float randY = h * height.x;
  196. position = vec3(randX, randY, randZ);
  197. // Direction
  198. if (abs(cos(coneAngle)) == 1.0) {
  199. direction = vec3(0., 1.0, 0.);
  200. } else {
  201. vec3 randoms3 = getRandomVec3(seed.z);
  202. direction = position + directionRandomizer * randoms3;
  203. }
  204. #else
  205. // Create the particle at origin
  206. position = vec3(0., 0., 0.);
  207. // Spread in all directions
  208. direction = 2.0 * (getRandomVec3(seed.w) - vec3(0.5, 0.5, 0.5));
  209. #endif
  210. float power = emitPower.x + (emitPower.y - emitPower.x) * randoms.a;
  211. outPosition = (emitterWM * vec4(position, 1.)).xyz;
  212. vec3 initial = (emitterWM * vec4(normalize(direction), 0.)).xyz;
  213. outDirection = initial * power;
  214. #ifndef BILLBOARD
  215. outInitialDirection = initial;
  216. #endif
  217. #ifdef ANIMATESHEET
  218. outCellIndex = cellInfos.x;
  219. #endif
  220. } else {
  221. float directionScale = timeDelta;
  222. float ageGradient = age / life;
  223. #ifdef VELOCITYGRADIENTS
  224. directionScale *= texture(velocityGradientSampler, vec2(ageGradient, 0)).r;
  225. #endif
  226. outPosition = position + direction * directionScale;
  227. outAge = age + timeDelta;
  228. outLife = life;
  229. outSeed = seed;
  230. #ifndef COLORGRADIENTS
  231. outColor = color;
  232. #endif
  233. #ifdef SIZEGRADIENTS
  234. outSize.x = texture(sizeGradientSampler, vec2(ageGradient, 0)).r;
  235. outSize.yz = size.yz;
  236. #else
  237. outSize = size;
  238. #endif
  239. #ifndef BILLBOARD
  240. outInitialDirection = initialDirection;
  241. #endif
  242. outDirection = direction + gravity * timeDelta;
  243. #ifdef NOISE
  244. vec3 localPosition = outPosition - emitterWM[3].xyz;
  245. float fetchedR = texture(noiseSampler, vec2(localPosition.y, localPosition.z) * vec2(0.5) + vec2(0.5)).r;
  246. float fetchedG = texture(noiseSampler, vec2(localPosition.x + 0.33, localPosition.z + 0.33) * vec2(0.5) + vec2(0.5)).r;
  247. float fetchedB = texture(noiseSampler, vec2(localPosition.z - 0.33, localPosition.y - 0.33) * vec2(0.5) + vec2(0.5)).r;
  248. vec3 force = vec3(2. * fetchedR - 1., 2. * fetchedG - 1., 2. * fetchedB - 1.) * noiseStrength;
  249. outDirection = outDirection + force * timeDelta;
  250. #endif
  251. #ifdef ANGULARSPEEDGRADIENTS
  252. float angularSpeed = texture(angularSpeedGradientSampler, vec2(ageGradient, 0)).r;
  253. outAngle = angle + angularSpeed * timeDelta;
  254. #else
  255. outAngle = vec2(angle.x + angle.y * timeDelta, angle.y);
  256. #endif
  257. #ifdef ANIMATESHEET
  258. float dist = cellInfos.y - cellInfos.x;
  259. float ratio = clamp(mod(outAge * cellInfos.z, life) / life, 0., 1.0);
  260. outCellIndex = float(int(cellInfos.x + ratio * dist));
  261. #endif
  262. }
  263. }