What is a particle system?

jwatte's picture

A particle system is something which can be used to make smoke, explosions, contrails, steam, and other kinds of "cloudy" or "sparkly" effects.

In a particle system, some number of "particles" are simulated -- typically, some initial velocity, some gravity, some wind, and some air drag resistance affects the particles. Additionally, the particles may have properties that change over time, such as size, translucency, color, etc.

Particles "come from" an emitter, which creates them in an initial state, and then are simulated until they "die" -- typically, after some pre-set time, or when the alpha goes to 0.

Finally, particle systems are rendered using blending into the frame buffer. Each particle is typically turned into a billboarded quad, which draws an image of a cloud puff, smoke puff, fireball piece, sparkly star, etc. When many of these are drawn together, it can make for an amazing, volumetric effect.

Traditionally, particle systems have been implemented on the CPU, using CPU cycles to simulate the particles. However, if you make some simplifying assumptions about particle behavior, you can actually calculate the state of any given particle knowing just its emitter position and its age. That math is then crammed into a vertex shader, whose only parameter needs to be emitter position and current age of the system (as well as camera parameters for billboarding). That way, you can render a particle system entirely on the GPU. That's what the Particle System sample is doing.

To create good particle systems/effects, there are three things that go together. The first is an understanding of how colors blend into the framebuffer, so that the right particle image/texture can be created. The second is an understanding of how the particle simulation works, so that the right behavior (billowing, falling, etc) can be configured on the particles. The third is an artistic sense, so that you know how to combine the texture and behavior to get the effect you actually want.

A simple, CPU-side particle system will look something like:

void OnUpdate() {
  foreach (Emitter e in emitters_) {
    e.EmitParticle(this);
  }
  foreach (Particle p in particles_) {
    if (p.IsAlive) {
      p.UpdateState();
    }
  }
}

void OnDraw() {
  ClearVertices();
  foreach (Particle p in particles_) {
    if (p.IsAlive) {
      EmitVerticesForParticle(p);
    }
  }
  GraphicsDevice.Vertices[0].SetSource(myVertices_, ...);
  GraphicsDevice.VertexDeclaration = myVertexDeclaration_;
  myEffect_.Begin();
  foreach (EffectPass ep in myEffect_.Passes) {
    ep.Begin();
    GraphicsDevice.DrawPrimitives(PrimitiveType.Triangles, ...);
    ep.End();
  }
  myEffect_.End();
}