Particle 3D Sample

This sample shows how to implement an efficient 3D particle system. It animates the particles entirely on the graphics card by using a custom vertex shader, so it can draw large numbers of particles with minimal CPU overhead. The sample builds on the ideas introduced in the 2D Particle sample, showing how those principles can be extended to work in 3D and optimized through the use of shaders. If you are unfamiliar with the concept of a particle system, you should start with the simpler implementation in the 2D Particle sample.

Sample Overview

When displaying large numbers of particles, games can easily become bottlenecked by the amount of CPU work involved in updating everything and transferring the latest particle positions across to the GPU for drawing. This sample avoids that by animating particles entirely on the GPU. The CPU overhead remains low regardless of how many particles are active. Moving eye candy to the GPU leaves the CPU free for other things such as gameplay, physics, or AI.

When a new particle is created, the CPU fills a vertex structure with the position, velocity, and time at which the particle was created. After this vertex is uploaded to the GPU, the CPU never needs to touch it again. Every frame, the current time is set as a vertex shader parameter. When the GPU draws the particles, it can work out the age of each one by comparing the creation time (which is stored as part of the vertex data) with the current time. Knowing the starting position, velocity, and age, the shader can then compute the current position and draw a billboard quad at this location.

New particles are always added to the end of the vertex buffer, and old ones are removed from the start. Because all particles last the same amount of time, this means the active particles will always be grouped together in a consecutive region of the buffer, and so can all be drawn in a single call. The CPU is responsible for adding new particle vertices to the end of the buffer, and for retiring old ones from the start, but it does not need to do anything with the active particles in the middle of the buffer. Even games with thousands of particles typically only create and retire a few each frame, so the resulting CPU workload is very low.

Although this sample works in 3D, the same code can be used for efficient 2D particle systems by setting an orthographic matrix as the camera projection.

Sample Controls

This sample uses the following keyboard and gamepad controls.

Action Keyboard control Gamepad control
Switch the particle effect SPACEBAR A
Rotate the model

UP ARROW, DOWN ARROW, LEFT ARROW, and RIGHT ARROW

or W, S, A, and D

Right thumb stick
Zoom Z and X Triggers
Reset R Right thumb stick press
Exit the sample ESC or ALT+F4 BACK

How the Sample Works

When you add new textures for a particle system, XNA Game Studio defaults them to create a texture with the Color format and without mipmaps. Textures without mipmaps look bad and are inefficient when drawn in 3D. You should change the Texture processor properties on these textures to set Generate Mip Maps to true and Texture Format to DxtCompressed.

This sample does not sort the particles in any way. That would be too inefficient. The resulting artifacts are usually too subtle to be a problem, but you can see some sorting problems if you look at the smoke plume from certain angles.

Extending the Sample

To make the particle systems easier to tweak, the ParticleSettings data could be loaded from an XML configuration file.

There are no cats in this sample. It would be cool if one could jump through the burning hoop.