Particle System on the GPU By David Carmichael Project

advertisement
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).
Download