Time for Action: Fountain of Sparks

Let's see how we can use point sprites to create a fountain of sparks:

  1. Open the ch10_02_point-sprites.html file in your browser:

  1. This example showcases a simple fountain of sparks effect with point sprites. You can adjust the size and lifetime of the particles by using the sliders.
  2. The particle simulation is performed by maintaining a list of particles that are comprised of position, velocity, and lifespan. In every frame, we iterate through the list and move the particles according to the velocity; we also apply gravity and reduce the remaining lifespan. Once a particle's lifespan has reached 0, it's reset to the origin with a random velocity and updated lifespan.
  3. With every iteration of the particle's simulation, the particle positions and lifespans are copied to an array that is then used to update a vertex buffer. This vertex buffer is what is rendered to produce the onscreen sprites.
  4. Let's experiment with some of the other values that control the simulation and see how they affect the scene. Open up ch10_02_point-sprites.html in your editor.
  1. First, locate the call to configureParticles at the bottom of the configure function. The number passed as an argument, initially set to 1024, determines how many particles are created. Try changing it to a lower or higher value to see the effect it has on the particle system. Be careful, though, since extremely high values (for example, in the millions) may cause performance issues.
  2. Next, find the resetParticle function. This function is called any time a particle is created or reset. There are several values here that can have a significant effect on how the scene renders:
function resetParticle(particle) {
particle.position = [0, 0, 0];

particle.velocity = [
Math.random() * 20 - 10,
Math.random() * 20,
Math.random() * 20 - 10,
];

particle.lifespan = Math.random() * particleLifespan;
particle.remainingLife = particle.lifespan;
}
  1. The particle.position is the xyz starting coordinates for the particle. Initially, all points start at the world origin (0, 0, 0), but this could be set to anything. It's often desirable to have the particles originate from the location of another object so as to give the impression that the object is producing the particles. You can also randomize the position to make the particles appear within a given area.
  2. particle.velocity is the initial velocity of the particle. Here, you can see that it has been randomized so that particles spread out as they move away from the origin. Particles that move in random directions tend to look more like explosions or sprays, while those that move in the same direction give the appearance of a steady stream. In this case, the y value is designed to always be positive, while the x and z values may either be positive or negative. Experiment with what happens when you increase or decrease these velocity values or remove the random element from one of the components.
  3. Finally, particle.lifespan determines how long a particle is displayed before being reset. This uses the value from the controls while being randomized to provide visual variety. If you remove the random element from the particle lifespan, all of the particles will expire and reset at the same time, resulting in fireworks-like bursts of particles.
  1. Next, find the updateParticles function. This function is called once per frame to update the position and velocity of all particles before pushing the new values to the vertex buffer. It's interesting to note that in terms of manipulating the simulation behavior, gravity is applied mid-way through the function:
function updateParticles(elapsed) {
// Loop through all the particles in the array
particles.forEach((particle, i) => {
// Track the particles lifespan
particle.remainingLife -= elapsed;

if (particle.remainingLife <= 0) {
// Once the particle expires, reset it to the origin with a
// new velocity
resetParticle(particle);
}

// Update the particle position
particle.position[0] += particle.velocity[0] * elapsed;
particle.position[1] += particle.velocity[1] * elapsed;
particle.position[2] += particle.velocity[2] * elapsed;

// Apply gravity to the velocity
particle.velocity[1] -= 9.8 * elapsed;

if (particle.position[1] < 0) {
// Allow particles to bounce off the floor
particle.velocity[1] *= -0.75;
particle.position[1] = 0;
}

// Update the corresponding values in the array
const index = i * 4;
particleArray[index] = particle.position[0];
particleArray[index + 1] = particle.position[1];
particleArray[index + 2] = particle.position[2];
particleArray[index + 3] = particle.remainingLife /
particle.lifespan;
});

// Once we are done looping through all the particles, update the
// buffer once
gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
gl.bufferData(gl.ARRAY_BUFFER, particleArray, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}

  1. The 9.8 here is the acceleration applied to the y component over time. In other words, this is the gravity. We can remove this calculation entirely to create an environment where the particles float indefinitely along their original trajectories. We can increase the value to make the particles fall very quickly (giving them a heavy appearance), or we can change the component that the deceleration is applied to so that we can change the direction of gravity. For example, subtracting from velocity[0] makes the particles fall sideways.
  2. This is also where we apply a simple collision response with the floor. Any particles with a y position less than 0 (below the floor) have their velocities reversed and reduced. This gives us a realistic bouncing motion. We can make the particles less bouncy by reducing the multiplier (that is, 0.25 instead of 0.75) or even eliminate bouncing altogether by simply setting the y velocity to 0. Additionally, we can remove the floor by taking away the check for y < 0, which will allow the particles to fall indefinitely.
  3. It's also worth seeing the different effects we can achieve with different textures. Try changing the path for the spriteTexture in the configure function to see what it looks like when you use different images.

What just happened?

We've seen how point sprites can be used to efficiently render particle effects. We've also seen the different ways that we can manipulate a particle simulation to achieve various effects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.231.155