particleSystemChunk = `
${randomBySpatialChunk}
${myRandChunk}
${easingChunk}
${zoneChunk}
${transformChunk}
vec3 projectOnVector(vec3 v, vec3 target) {
return (dot(target, target) != 0.0)
? (target * dot(v, target) / dot(target, target))
: vec3(0.0);
}
uniform vec3 prevPosRelative;
uniform float prevTimeSec;
uniform float zeroTimeSec;
mat4 particleTransform(in float particleTimeSec, in float t, in float iteration) {
vec3 initialVelocity = randDir3() * 1.0;
initialVelocity -= projectOnVector(initialVelocity, prevPosRelative);
initialVelocity += normalize(prevPosRelative) * randInRange(1.0, 3.0);
vec3 displacementInTime = initialVelocity * particleTimeSec;
return identity
* translate(displacementInTime)
* scale(mix(vec3(0.0), vec3(randInRange(0.3, 0.8)), min(1.0, easeOutQuad(t * 2.5)))) // scale in
* scale(mix(vec3(1.0), vec3(0.0), easeOutQuad(t))); // scale out
}
mat4 emitterTransform(float timeSec) {
if ((timeSec > zeroTimeSec || timeSec <= prevTimeSec)) { return scaleZero; }
return ${
generateDiscretely
? `identity`
: `translate(mix(prevPosRelative, vec3(0.0), (timeSec - zeroTimeSec) / (prevTimeSec - zeroTimeSec)))`
};
}
// 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(0.8, 1.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);
}
`