# Drawing particles with CPU instead of GPU (XNA)

I'm trying out modifications to the following particle system. http://create.msdn.com/en-US/education/catalog/sample/particle_3d

I have a function such that when I press Space, all the particles have their positions and velocities set to 0.

for (int i = 0; i < particles.GetLength(0); i++)
{
particles[i].Position = Vector3.Zero;
particles[i].Velocity = Vector3.Zero;
}


However, when I press space, the particles are still moving. If I go to FireParticleSystem.cs I can turn settings.Gravity to 0 and the particles stop moving, but the particles are still not being shifted to (0,0,0).

As I understand it, the problem lies in the fact that the GPU is processing all the particle positions, and it's calculating where the particles should be based on their initial position, their initial velocity and multiplying by their age. Therefore, all I've been able to do is change the initial position and velocity of particles, but I'm unable to do it on the fly since the GPU is handling everything.

I want the CPU to calculate the positions of the particles individually. This is because I will be later implementing some sort of wind to push the particles around. How do I stop the GPU from taking over? I think it's something to do with VertexBuffers and the draw function, but I don't know how to modify it to make it work.

• I changed your tag from 'xna-4.0' to 'xna' because I don't think anything in your question is XNA 4 specific, except for the fact that the sample you link to happens to have been updated to compile with XNA 4. – user1430 Feb 1 '11 at 18:16

The particle system you are using as a base is explicitly designed to perform all its animation on the GPU. To disable that, you need to use a different design.

You can modify the baseline you have to remove all position update/animation code from the vertex shader (see ComputeParticlePosition) and move that to your application. You'll have to employ dynamic vertex buffers -- locking the buffer each frame, copying the position out of the particle system data structure and in to the buffer (although with the rest of the particle's vertex attributes), and then unlocking the buffer. You may want to remove/modify the rest of the ComputeParticleWhatever methods in the shader, since any modifications they make to the particle system will clobber any updates you do on the CPU.

Then you'll have complete CPU-side control over the particle attributes, at the cost of decreased performance due to the additional cost of updating the vertex buffer each frame -- this the bottleneck that the sample describes avoiding in the description:

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, so 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.

So you should be aware that you are eliminating this optimization by moving per-frame update back to the GPU. Note that, depending on the complexity of your "wind" function, you could probably instead push that computation to the GPU as well, which would give you the finer control you are after as well as obviate the need to update a vertex buffer every frame.

Alternatively, you can modify the shader used to update your particles so that it does the wind calculations on the GPU as well. That way you have the added wind control, but don't lose the performance benefits of the GPU particle system. Obviously there are limitations to what you can do with a GPU particle system, but adding wind shouldn't be one of them. Good Luck!

• Ha, my very first post and I failed. Josh already pointed out that it might be possible to move the "wind" update to the shader. – Justin Chambers Feb 7 '11 at 16:14