Gamasutra: The Art & Business of Making Gamesspacer
Building an Advanced Particle System
arrowPress Releases
February 25, 2017
Games Press
View All     RSS

If you enjoy reading this site, you might also want to check out these UBM Tech sites:

Building an Advanced Particle System

June 23, 2000 Article Start Page 1 of 3 Next

Imagine a scene in a game in which a rocket flies through the air, leaving a smoke trail behind it. Suddenly the rocket explodes, sparks flying everywhere. Out of the disintegrating rocket a creature is jettisoned towards you, its body parts exploding and blood flying through the air, leaving messy blood splatters on the camera lens. What do most of the elements in this scene have in common?

Yes, most of these elements are violent. But in terms of technology, most of the effects in a scene like this would benefit from a good particle system. Smoke, sparks, and blood are routinely created in today's games using particle systems.
To realize these effects, you need to build a particle system, and not just a simple one. You need an advanced particle system, one that's fast, flexible, and extensible. If you are new to particle systems, I recommend you begin by reading Jeff Lander's article on particle systems ("The Ocean Spray in Your Face," Graphic Content, July 1998). The difference between Lander's column and this article is that the former describes the basics of particles, whereas I will demonstrate how to build a more advanced system. With this article I will include the full source code for an advanced particle system, and you can download an application that demonstrates the system.

Performance and Requirements

Advanced particle systems can result in pretty large amounts of code, so it's important to design your data structures well. Also be aware of the fact that particle systems can decrease the frame rate significantly if not constructed properly, and most performance hits are due to memory management problems caused by the particle system.

When designing a particle system, one of the first things to keep in mind is that particle systems greatly increase the number of visible polygons per frame. Each particle probably needs four vertices and two triangles. Thus, with 2,000 visible snowflake particles in a scene, we're adding 4,000 visible triangles for the snow alone. And since most particles move, we can't precalculate the vertex buffer, so the vertex buffers will probably need to be changed every frame.

The trick is to perform as few memory operations (allocations and releases) as possible. Thus, if a particle dies after some period of time, don't release it from memory. Instead, set a flag that marks it as dead or respawn (reinitialize) it. Then when all particles are tagged as "dead," release the entire particle system (including all particles within this system), or if it's a constant system, keep the particle system alive. If you want to respawn the system or just add a new particle to a system, you should automatically initialize the particle with its default settings/properties set up according to the system to which it belongs.

For example, let's say you have a smoke system. When you create or respawn a particle, you might have to set its values as described in Table 1. (Of course, the start color, energy, size, and velocity will be different for blood than, say, smoke.) Note that the values also depend on the settings of the system itself. If you set up wind for a smoke system so the smoke blows to the left, the velocity for a new particle will differ from a smoke system in which the smoke just rises unaffected by wind. If you have a constant smoke system, and a smoke particle's energy becomes 0 (so you can't see it anymore), you'll want to respawn its settings so it will be replaced at the bottom of the smoke system at full energy.
Some particle systems may need to have their particles rendered in different ways. For example, you may want to have multiple blood systems, such "blood squirt," "blood splat," "blood pool," and "blood splat on camera lens," each containing the appropriate particles. "Blood squirt" would render blood squirts flying through the air, and when these squirts collided with a wall, the "blood splat" system would be called, creating messy blood splats on walls and floors. A blood pool system would create pools of blood on the floor after someone had been shot dead on the ground.

Each particle system behaves in a unique manner. Blood splats are rendered differently than smoke is displayed. Smoke particles always face the active camera, whereas blood splats are mapped (and maybe clipped) onto the plane of the polygon that the splat collides with.

When creating a particle system, it is important to consider all of the possible parameters that you may want to affect in the system at any time in the game, and build that flexibility into your system. Consider a smoke system again. We might want to change the wind direction vector so that a car moving closely past a smoke system makes the smoke particles respond to the wind generated by the passing car.

At this point you may have realized that each of these systems (blood splat, smoke, sparks, and so on) is very specific to certain tasks. But what if we want to control the particles within a system in a way not supported by the formulae in the system? To support that kind of flexibility, we need to create a "manual" particle system as well, one that allows us to update all particle attributes every frame.

The last feature we might consider is the ability to link particle systems within the hierarchy of our engine. Perhaps at some point we'll want to link a smoke or glow particle system to a cigarette, which in turn is linked to the head of a smoking character. If the character moves its head or starts to walk, the position of the particle systems which are linked to the cigarette should also be updated correctly.
So there you have some basic requirements for an advanced particle system. In the next section, I'll show how to design a good data structure that is capable of doing all the above-mentioned features.

Article Start Page 1 of 3 Next

Related Jobs

Cignition — Palo Alto, California, United States

Gameplay Programmer
Studio Wildcard
Studio Wildcard — Kirkland, Washington, United States

Senior Engine Programmer
Studio Wildcard
Studio Wildcard — Seattle, WA, Washington, United States

Senior Gameplay Programmer
Intel — Hillsboro, Oregon, United States

Graphics and Multicore Developer Relations Engineer

Loading Comments

loader image