Storing / Adding / Drawing particles

Hey, I am drawing about 5000 particles. There will probably be 10-20 different types of particles in there, each with different images.
Since switching textures seems to take time, I think the best way is to draw each type 1 particle with the first texture, then each type 2 particle with the next texture, etc until I have drawn all the particles.

I have come up with two different ways to do this, I am wondering which is better? or there is an even better way?

  1. have a single list of particles, and loop through it N times where N is the number of different types of particles.
    This means if there are 100 particle types I will have to loop through all the particles 100 times when drawing. But adding particles will be fast.

  2. have a Map<ParticleType, List> but then whenever I add a new particle I have to find out which list it belongs to.
    Using the double-arraylist switching method talked about here http://www.java-gaming.org/index.php?topic=27016.0 by theagentd and princec
    means that each time I swap the lists I have to reinsert the list back into the hashmap after I swap it (I would use 2 Maps, one for the current and one for the next)

Thanks,
roland

Push all your particle sprites in the same texture. :point:

There are several steps you can take to improving sprite/particle performance with OpenGL:

  1. Use a single sprite sheet like Riven said. This really should be the first optimization for any game.
  2. Batch all particle quads into a single list – for example, glBegin, then draw each particle, then glEnd. This should be performant enough to render 5000+ sprites on modern hardware.
  3. Simple culling – don’t render anything outside of your desired view.
  4. Use GL_TRIANGLES and VBOs (or simple vertex arrays) to further improve performance, instead of immediate mode and glBegin/glEnd. This would probably lead to a LibGDX SpriteBatch-like implementation.
  5. If geometry shaders are supported, use them instead of rendering triangles.
  6. If performance is still not suitable, look into specific optimizations such as storing velocity/position in a float texture, using OpenCL/CUDA, or what have you.

Generally you’ll find your game is “fast enough” at step 3, and the rest exist more or less for the heck of it.

Thanks for the replies ;D I will definitely follow the first 3 steps.

What if I want to switch between blend modes for different particle types? should I loop through the list of particles once for each blend mode?

why you want to have different blend modes, try to split the particles up in two list. I would think that you won’t change the blend modes of a living particle, so that shouldn’t be a problem.

Also, as an addition to the optimization list, in OpenGL there is this great PointSpirits extension, were you only have to provide the center point for each particle and OpenGL will expand it automatically to a screen aligned Quad.

I actually only really want two blendmodes at this point:
Additive, for fire, etc

GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE);

And another for smoke:

GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

If there’s a way to just use a single blend mode that will work for both I would like to know it :slight_smile:
otherwise I will use two lists, thanks.

I can’t use point sprites because I want rotation as well :frowning:

Pre-multiplied alpha.

http://home.comcast.net/~tom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]

Simple solution: use two lists, one containing all “normal blend” particles, another containing all “additive blend” particles. That way you are still taking advantage of batching. A more advanced solution would be to sort all particle elements based on their properties: texture, blend mode, etc.

Fixed function point sprites are generally not a great idea… Maximum size varies wildly between systems, they get culled based on their center, can’t use texture atlases, can’t use rotation as roland was saying, etc. GL_POINTS and geometry shaders (if supported) would be a better bet.

Ok, I got pre-multiplied alpha working :slight_smile: I will make a tutorial on it I think