fragmentShader = `
precision highp float;
varying vec2 vUv;
varying vec3 vPos;
varying float vParticleIndex;
varying vec2 vLifetime;
uniform float time;
uniform vec3 colorBase;
uniform vec3 colorStart;
uniform vec3 colorPeak;
uniform vec3 colorEnd;
#define PI 3.1415926536
#define PI2 6.28318530718
float drawBase (in vec2 uv, in float min, in float max) {
float dist = sqrt(dot(uv, uv));
if (dist >= max || dist <= min) {
return 0.0;
}
float sm = smoothstep(max, max - 0.01, dist);
float sm2 = smoothstep(min, min - 0.01, dist);
float alpha = sm * sm2;
return (1.0-alpha);
}
void main() {
// figure out opacity early
float alpha = drawBase(vUv - vec2(0.5), 0.0, 0.5);
float progress = vLifetime.x / vLifetime.y;
alpha *= (1.0 - progress);
// lower the alpha since many particles will overlap
alpha /= 7.0;
// discard if not needed
if (alpha == 0.0) {
discard;
}
vec4 color = vec4(colorBase, alpha);
float alteration = sin(vLifetime.x + vLifetime.y + vParticleIndex) * 0.25;
float range1 = progress * 3.0 + alteration;
color.rgb = mix(color.rgb, colorStart.rgb, range1);
float range2 = progress * 3.0 - vLifetime.y + alteration;
color.rgb = mix(color.rgb, colorPeak.rgb, range2);
float range3 = progress * 3.0 - vLifetime.y * 2.0 + alteration;
color.rgb = mix(color.rgb, colorEnd.rgb, range3);
gl_FragColor = color;
}
`