Particle System on the GPU By David Carmichael Project Description The goal of the project was to make a particle system using DirectX 10 and HLSL on that runs almost entirely on the GPU. A geometry shader is used to update particles, handle particle birth and death, and also collision testing. For the scope of this project I only handle simple collisions with boxes and spheres. For each different type of particle, or system of particles, there is an effect file that defines all of its behaviors. For example there is an Explosions.fx file which is used to make different kinds of explosions. Approach For my system I have a main Particle System which stores all running Particle Effects which are each made corresponding to an effect file. The Particle System is a static singleton class, so you can only have one of them. Also only the Particle System can make Particle Effects because Particle System is a friend class of Particle Effect, whose constructor is protected. The Particle System has factory methods to make the Particle Effects which it returns so that individual effects can be given unique settings. Any settings which are to be common among all effects can be set through the Particle System and it will set them for each effect. The different settings for effects are the world, view, and projection matrices, camera forward, affecter force, and flags for updating and rendering. After the system and effects are initialized to use the effects the Update and Render methods in the Particle System are to be called. The Update function calls the Update technique inside of the effects shader to update all of the particles. A geometry shader with stream out is used for this, which means all vertices passed into, or drawn, will pass through the geometry shader. Any vertices that the shader returns are streamed out to a buffer, and this is how particle birth, updating, and death are handled. The Render function is similar, except this time the geometry shader turns each vertex, representing one particle, is turned into a billboard(four vertices) which get passed onto a particle shader. To achieve randomness on the GPU for the effects I make a randomly generated texture at initialization time on the CPU and then pass it into the shaders. Then to access this texture the running time of the system is used as a “seed” into the texture. Collisions are handled through two textures passed into the shaders. The first texture stores the position of a primitive in the rgb, and the type of primitive in the alpha. The second texture stores the dimensions of a primitive in the rgb, and a flag for whether or not the primitive should contain or repel a particle in the alpha. Technical Details Buffers: There are a total of three buffers used for each Particle Effect. Two of the buffers are used for the Updating. The geometry shader cannot stream out to the same buffer that it is accepting input from, so it is necessary to have two buffers that you swap back and forth. The buffer that you stream out to one frame will be the input buffer used the next frame. The buffer that was streamed out to is always the one used for the render phase as those will be the most up to date particles. The third buffer is used for adding in new emitters to the effect. Between each update any emitters that need to be added are put into the buffer, and then when the next update happens they are passed along to the geometry shader along with all of the other particles. Randomness: Getting randomness on the GPU is not too complicated. I simple make a randomly generated texture which gets passed to the shader. The run time of the system can then be used to access the texture for a random value(color) to use. Results The Following image is an example of the particle system being used in the game to make many explosions. Future Enhancements I would love to add in support to use meshes to represent particles in place of point textures. And further, to increase efficiency while using meshes I would like to use imposters. Imposters are textures that are “disguised” as models. Basically a model is rendered to a texture one time, and then that texture is used in place of the model until viewing conditions of the model have changed within a certain threshold in which case it is re-rendered. This would increase efficiency greatly, especially for particles far in the distance that wouldn’t need to be rerendered as often. Appendix A The code is in C++ using DirectX 10 and HLSL shader model 4.0. The particle system can be used with any DirectX 10 code, all the system needs to run correctly is a properly set up DirectX10 device object (ID3D10Device).