particleSystemChunk = `
${myRandChunk}
${easingChunk}
${zoneChunk}
${transformChunk}
mat4 emitterTransform(float timeSec) {
${emitterTransform}
}
// Calculates a transform of a single particle at a given time of its lifespan
// given the myRand is procedurally seeded per particle
// @ particleTimeSec - time in [0, lifeSec)
// @ t - phase in [0, 1),
// @ iteration - an integer iteration of particle instance (each iteration seeds another particle)
mat4 particleTransform(in float particleTimeSec, in float t, in float iteration) {
vec3 initialVelocity = (vec3(randDir3()) + vec3(0.0, randInRange(2.0, 4.0), 0.0)) * 5.0;
vec3 gravity = vec3(0.0, ${toGlslFloatLiteral(gravity)}, 0.0);
vec3 displacementInTime = initialVelocity * particleTimeSec + gravity * particleTimeSec * particleTimeSec;
return identity
* translate(randInBoxZone(vec3(-2.0, 0.0, -2.0), vec3(2.0, 0.0, 2.0))) // initial position in a (flat) box
// * translate(randInBallZone() * 2.0) // initial position in a ball
* translate(displacementInTime)
* scale(mix(vec3(0.0), vec3(randInRange(3.0, 6.0)), easeInQuad(t))) // scale in
* scale(mix(vec3(1.0), vec3(0.0), easeInQuad(t))) // scale out
* rotate(randDir3(), myRand()) // initial rotation
* rotate(randDir3(), myRand() * particleTimeSec); // additional rotation through time
}
// Prepares particle iteration variables, seeds the random, returns particle transform
mat4 particleMain(in float timeSec, in float seed, bool debug) {
if (debug) { return emitterTransform(timeSec); }
myRandSeed = seed;
float lifeSec = randInRange(2.0, 5.0);
float initialLifeOffsetSec = randInRange(-lifeSec, 0.0);
float iterationWithPhase = (timeSec + initialLifeOffsetSec) / lifeSec;
float iteration = floor(iterationWithPhase);
float t = fract(iterationWithPhase);
float particleTimeSec = t * lifeSec;
float emissionTimeSec = timeSec - particleTimeSec;
float iterationSeed = fract(iteration * 1e-10);
myRandSeed = fract(myRandSeed + iterationSeed); // reseed rand for every iteration
return emitterTransform(emissionTimeSec) * particleTransform(particleTimeSec, t, iteration);
}
`