Public
Edited
Feb 26, 2023
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
count = Math.floor(Math.pow(2, countPow))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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);
}
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more