For the “Advanced 3D Graphics Programming” module in the final year of my university degree, we were given an open-ended assignment whereby we could choose to create a tech-demo of any graphics technique that we wanted, and attempt to enhance it in some way (in terms of performance, quality, or by combining it with other techniques). After some deliberation, I chose to create a particle effect system using a traditional “billboarding” technique in DirectX 9 with C++. I then demonstrated the performance benefit that could be gained by reproducing the exact same effect with “point sprites” instead, and wrote a report to document my findings. My work received a “B+” grade overall.
An x86 (Windows) executable of this application is available from the following link if you’d like to try it out.
Particles App – x86 Executable (.ZIP, 25.8 KB)
Read on for the technical details of this project.
Effects like rain, snow, smoke, fire or sparks are very common in games, and it would be prohibitively expensive to produce actual geometry for rendering them, so particle systems are used instead.
With the billboard technique, each particle consists of a simple quad of geometry with a texture on it, rotated so that it always faces the camera viewpoint. These quads can be drawn on top of each other many times, blending the texture colour together to produce the final effect. With point sprites, the basic principle is the same, but instead of each particle having a quad of geometry, all of the particles are collectively stored as individual points of data in a special dynamic vertex buffer, meaning that moving, rotating and drawing them is less computationally expensive because all of their data is conveniently stored in the same place.
My application directly compares and contrasts the performance difference between billboard particles and point sprite particles by having two emitters (sources of particles) in the same scene, one of each technique. The blue particles are point sprites, and the orange particles are billboards. Importantly, the application’s V-Sync is disabled, meaning that the framerate is unrestricted rather than being forced to try and maintain 60fps. By adjusting the controls, you can easily see that with a high number of point sprite particles, an equivalent number of billboard particles has a significant impact on the framerate.
Press and hold “H” to see the application controls. You can turn the emitters on and off using the left and right mouse buttons, but note that the particles still “age” even when the emitters are off, otherwise the ones that were created just after you switched off the emitter but haven’t disappeared yet wouldn’t behave properly. This means that when you turn the emitter back on, you’ll get a gush of all the particles that have been reset all at once. You can also create this “firework” effect by having a high “emit step” value (the number of particles that are emitted in a single update cycle) and a high “init’ particles” value (the number of particles that the emitter will eventually produce).
Note that if the current number of particles plus the “emit step” is equal to or greater than the “init’ particles” value, the emitter will default to an “emit step” value of 1 in order to gradually reach the “init’ particles” limit without overrunning it.
The “key-lock” setting determines whether or not holding down a key will constantly provide input. With the key-lock on, buttons for changing the emitter properties need to be pressed multiple times to change their value (good for precise adjustments). With the key-lock off, you can just hold down the button to continuously change the value.
With newer editions of DirectX, even higher performance and better quality particle effects can be achieved by using shaders. Both billboards and point sprites have other limitations as well – because billboards do not use a dynamic vertex buffer, it is difficult to change their properties (besides position) without the use of shaders. For example, the billboard particles in my application lack the colour-shift ability of the point sprites, which is what allows them to fade away as they age. This makes the billboard emitter look like it is larger and behaving slightly differently, even though it is not. On the other hand, because point sprites do not have any geometry, it is hard to make them rotate independently of the camera (for example, with billboards you might only allow rotation around the Y axis, or you might want to induce spin around the Z axis), and it can also be tricky to get point sprites to scale properly. In my application for example, the point sprites scale correctly with perspective as the camera moves around the scene (allowing them to look like true 3D objects), but changing the camera’s Field-of-View angle with the mouse’s scroll-wheel results in different scaling behaviour when compared to the billboard particles.
Both emitters use the “particle.bmp” texture bundled with the executable. Feel free to experiment by changing this texture if you wish, so long as the format is the same. Note that black works like the alpha channel, so the darker the texture, the more transparent it is.