# Particle System Question

This topic is 2869 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey everyone,

I have a particle system but am wondering if there is a more efficient way to implement it. The current particle class I have looks like this.

 //=============================================// //// Copyright 2012 - Ember in the Rain, LLC // // All Rights Reserved // // Developer: Shawn M. Foster // //=============================================// #ifndef _PARTICLE_H_ #define _PARTICLE_H_ class Particle { public: /** Variables **/ //============================// int id; int lastTime; int pType; bool active; Vector position; Vector velocity; Vector acceleration; Vector color; float size; float mass; float age; float lifeSpan; /** Methods **/ //============================// Particle(LONG id); ~Particle(); void Update(int time); void DrawParticle(); }; #endif 

I am wondering if it would be more efficient to simplify the particle class to something like this.

 #ifndef _N_PARTICLE_H_ #define _N_PARTICLE_H_ /** Particle Class **/ /**----------------------------------------------**/ class NParticle { public: NParticle(); float mass; //mass float age; //age Vector pos; //position vector Vector vel; //velocity vector Vector frc; //force accumulator Vector col; //RGB color float rad; //repulsive radius }; /**----------------------------------------------**/ #endif 

And then do any updating and drawing of the particles in the Particle System Class.. Does this sound like a better approach . Do you think that I do too much processing by updating the particle in the particle class and drawing it in that class?

Thanks,

Shawn

##### Share on other sites
Yes, it is better to batch things, and don't draw every particle on its own.
Make one particle system, and draw that in one draw call if possible.

You might also want to inline your constructor in case you will use that to quickly create individual particles.

##### Share on other sites
Thanks for the reply. So when you say inline my constructor you mean declaring and defining it all in the class declaration?

Like this...

 #ifndef _N_PARTICLE_H_ #define _N_PARTICLE_H_ /** Particle Class **/ /**----------------------------------------------**/ class NParticle { public: NParticle(int indx) {id = indx;} int id; float mass; //mass float age; //age Vector pos; //position vector Vector vel; //velocity vector Vector frc; //force accumulator Vector col; //RGB color float rad; //repulsive radius }; /**----------------------------------------------**/ #endif 

Thanks,

Shawn

##### Share on other sites
He means to prepend the inline keyword to your ctor. This will remove the overhead of having to call to the ctor function every single time a particle is created. It will simply put the calling code wherever you create a particle(instead of having to "move" to the ctor, it is already there)

##### Share on other sites

He means to prepend the inline keyword to your ctor.

Actually defining the constructor in the class definition inlines implicitly. ;-) However, I don't think inlining the constructor will result in a big speed gain. But there are a few rules of thumbs you might consider in terms of optimizing your particle system:

Batch Drawcalls
Don't do a single drawcall for each particle. Rather batch many particles and render those with a single drawcall.

Use Texturatlases
Packing particle textures together in a atlas avoids texture switches

Try low resolution rendering
Render particle effects to low resolution targets for the sake of fillrate saving

Simulation on gpu
If your gpu is free you could do the simulation on gpu side to save memory bandwith (etc...)

Avoid Branches (etc...)
Don't do to many branches, virtual function calls etc.. Don't provide an update methode for a particle, do rather operate on particle batches

And then do any updating and drawing of the particles in the Particle System Class..

Yep, that sounds better!

If you'r doing the simulation on the CPU you could consider to swap the simulation to a free CPU core.

Use SIMD
Again, if you'r doing the simulation on the CPU you could use SIMD for speeding up the simulation.

Use cachefriendly datastructures
Using processor caches properly can result in big speed gains

Use specialized allocators (particle pools)
You could pool/preallocate particles to speed up allocation

##### Share on other sites
Thanks for the replies.

Don't do a single drawcall for each particle. Rather batch many particles and render those with a single drawcall.
[/quote]

So in this situation I fill my particle array once, then loop through my array of particles and call the draw function for each iteration?
Or, iterate through the particles inside of the draw function?

currently I draw the particles in the same loop as I update each particle's position. Which is a member of the ParticleSystem class.

I will look in to all of the other suggestions you made. Thanks again for your reply.

~Shawn

##### Share on other sites

So in this situation I fill my particle array once, then loop through my array of particles and call the draw function for each iteration?

No not exactly. You would loop through all your particles and write the vertices in one big vertexbuffer. Afterwards you just draw the geometrie residing in this vertexbuffer. Here is some pseudocode to illustrate the idea:

 for each particle p { /// this'll generate the actual geometry for the particle (i.e. a quad) vertices = generateVerticesForParticle(p); /// draw a single particle drawPrimitive(vertices) } 

 for each particle p { /// this'll generate the actual geometry for the particle (i.e. a quad) vertices = generateVerticesForParticle(p); /// write the vertices to the end of the vertexbuffer writeVerticesToVertexbuffer(vertexBuffer, vertices); } /// draw the particles in a single draw call drawPrimitives(vertexBuffer); 

##### Share on other sites
Great thanks. I will play around with it and see if I can optimize it.

##### Share on other sites
Switching from an AOS (array of structures) approach to a SOA (structure of arrays) approach for your particle data, then ensuring your arrays are 128 bit aligned allows for blindingly fast SIMD implementations.

A tightly packed float3 array thats 128-bit aligned at the start is faster to operate on than a typical aligned "128-bit" float3 structure, as long as you ensure the number of particles is a multiple of 4.

Memory is also kept contigious, which is always a bonus as cache read/writes are less likely to miss.

• 9
• 15
• 9
• 9
• 56