Particle techniques

Started by
7 comments, last by spek 12 years, 11 months ago
Hey,

I'd like to know how modern games manage their particles. I can think of 3 ways:
- Let the CPU calculate the motion and render quads. The "traditional" way.
- Make a VBO, and let the vertex-shader update the positions/motion via a texture (like GPU cloth works)
- Make a VBO, and let the vertex-shader interpolate the position based on some parameters (start, velocity, currentTime, ...)

I can imagine solution 2 and 3 are quite a lot faster, but these are somewhat limited when it comes to complex movement, spawning time schedules, or (simple) collision detection with the floor. Plus I wouldn't know how to depth-sort the particles then.

So, I still prefer the old CPU way. In order to optimize a bit, I'll use clusters that contain multiple particles. So I don't sort/calculate per particle, but per cluster. But when we want thousands and thousands of particles, it still becomes a long, long loop of calculations and draw calls... So, how do modern engines solve this?

Rick
Advertisement
I'm not an expert on this but I can tell you some things that might help:

Plus I wouldn't know how to depth-sort the particles then.[/quote]

You can solve this by looking up "Premultiplied alpha". That way you don't need depth-sorting anymore, meaning you can draw particles in any order. It should give you a huge performance-boost.

But when we want thousands and thousands of particles, it still becomes a long, long loop of calculations and draw calls...
[/quote]

You could at least reduce the amount of draw calls by using hardware instancing, if you are using directx. That way you only need 1 draw call per emitter. Look up the sdk-examples or the nvidia sdk example how to do it.

So if you still want to go with CPU calculations, these 2 steps should give you you at least 8 times the performance. I can draw around 50.000 particles on a single core of an old Core2Duo with 70 FPS, and havn't optimized my particle system yet. Not an excellent value but for standard cases it should work fine.
50.000 particles sounds perfect. But I'm using OpenGL 2.x here... It doesn't have instancing as far as I know. Pre-multiplied alpha... Not sure what you mean with that, that the sum of alpha would be '1' with X additive blended particles behind each other, to prevent extreme bright values? In some cases I want normal-transparent particles though. For example shrapnel or blood flying around shouldn't be additive. Although that won't come in such huge numbers of course.

But ok, maybe I can just ignore the sorting problem. Let's see what we can do with VBO's:
- Make a fixed large number of quads inside a VBO. The quads are not positioned yet.
- Use a texture to map the current position and motion vector for each particle (1 pixel per particle)
- Vertex shader reads the texture, then updates it ( output.newPosition = input.oldPosition + input.motion + gravity ). Eventually use a simple comparison to detect ground and bounce off the particles (or let them dissapear)
- Finally render the quads in the world using that position texture


I guess this can work, but managing the spawning and "recycling" of old dissapeared particles is nasty. I'd probably need to store a (cyclic) "lifetime" value into one of those textures as well. The VS should get a number of how many particles are active at the time. Say a VBO contains 1000 particles, and I only want to see about 250. The first 250 should fly around, the other 750 should be hidden somewhere. Whenever a particle lifetime has exceeded, it resets to an initial position/motion vector.


The other solution is to work without any textures, just pure mathematical. For each particle, the VS calculates the position based on a formula, given the initial position, motion and elapsed time. But getting that to work in a somewhat flexible way sounds even harder.
Pre-multiplied alpha... Not sure what you mean with that, that the sum of alpha would be '1' with X additive blended particles behind each other, to prevent extreme bright values? In some cases I want normal-transparent particles though. For example shrapnel or blood flying around shouldn't be additive. Although that won't come in such huge numbers of course.[/quote]

No, premultiplied alpha is not like additive blending. In the shader (programs in your case?) you multiplied the color of the particles with their alpha value and change the alpha blending to behave in a certain way. Can't really describe it, take a look at this site, it should be quite easy to implement:

http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

I can't help you with the other stuff, as I haven't tried it out, too. Good luck, though!
no, if u don't use a simple ADD blend u need to sort particles.

On old hardware u can use of course Textures, which u modify in a shader, for the particle attributes, but with OpenGL 3 u have Transform Feedback with which u can "render" with a Vertex Shader into another buffer object.

Two good resource for GPU particle sorting for once and rendering rediculouse much particles are these two
http://http.develope..._chapter46.html
http://directtovideo.wordpress.com/(take also a look at his demos)
Thanks and thanks! I have something to read this weekend :)

OpenGL 3.0... I'll wait with that one. I'm getting crazy updating everything all the time. Newton2, OpenAL to FMOD, and so on. Or is upgrading OpenGL 2 to 3 a peace of cake? Anyhow, rendering data into a VBO sounds very useful for cloth, physics, and such.

Thank you gentleman
no, if u don't use a simple ADD blend u need to sort particles.[/quote]

Well even if premultiplied alpha in fact is nothing more than an add blend, then it doesn't mind. I can render every particle I want, and they look fine. Blood, shrapnel and other solid particles are drawn just as solid as they should, and particles with alpha like fire draw transparent. I just wanted to tell spek that he can use pre-alpha without negative sideeffects like additive/substractive blending.
As Danny02 said, check out transform feedback buffer based particles.

My implementation of GPU particle systems works with OpenGL 2 (i.e., EXT_transform_feedback). You save a lot compared to other GPU techniques because you don't need to deal with rasterization; glEnable(GL_RASTERIZER_DISCARD). Basically, you use a vertex shader to transform everything, but the data stops there, and is written to a vertex buffer object.

My version supports multiple emitters, attractors, and collision detection, among other things. The whole thing runs at 50fps with 1 million particles, and at 10fps with 4 million (most of this is drawing the particles. If I don't draw the particles, 4 million runs at 50fps).

-G

[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]

Just discovered there is transform feedback demo in the OpenGL nVidia SDK 10.0 Haven't studied the code yet, but if I understand it right, this technique allows to alter VBO data via a vertex-data, thus without textures to keep track of the vertices. That would be extremely handy, also for cloth physics. And if OpenGL 2 supports it after all.... Better start reading :)

Thanks

This topic is closed to new replies.

Advertisement