Skip to main content
GameDev.net gamedev.net
🔒 Locked

Particle system optimization

Started by RandomLogic Feb 22, 2003 at 3:31 PM 14 replies 750+ views
Original Post
RandomLogic
RandomLogic
Hi, I have a working particle system. Currently what it does is hold a single quad and render all the particles (no texture change) one after another after I edit the world matrix and send it to the hardware. This of course kills the fps. I want to switch to using a vertex buffer for all quads then render with the same world matrix, I should get a very big boost from this. I am faced with a problem though. How do I manage the VB''s? I mean if I create a VB (per emitter let''s say) and some particle in the array dies then I need to either draw the primitives in chunks from the array, or copy the whole thing to a new VB. Another alternative I encoutered was to create a new VB each time I update the world (maybe even for all the particles??) but this sounds taxing on the hardware, I haven''t tried this in any of my code so I don''t know what kind of impact it''d have on fps. One last thing, Does anyone have any expirience with d3d''s point sprites? is there stuff you could do with a quad based PS that you couldn''t with point sprites? What generation hardware supports this feature? or in short... what''s the deal with point sprites? cheers, Random Logic
There aren't any stupid questions,Only stupid people.
randal
randal
I''m sure there''s a better way to do this.. but what I do is lock the vertex buffer every frame, loop through the particles and copy the alive particles into the vertex buffer and incriment a counter each loop.. then i use the counter value in the draw primitive call so i''m only drawing the alive particles. my framerate seems pretty good doing this, but my system is fairly fast.. hope this helps
Fuzztrek
Fuzztrek
Use a dynamic vertex buffer. This way, you are directly editing the vertex data (ie, position, color, etc) without having to mess with a world matrix for every particle. If you have some sort of recycling code for your array (so you don''t have to keep creating new particles), just reset the particle properties of the particles that have ''died'' to their starting values. You definatly do NOT want to be setting textures, texture stages, sampler stages, or matrix''s for every single particle. Doing it for every emitter is bad enough, but reasonable, IMO.

Check here for some documentation on dynamic vertex buffers and Direct3D Memory Pools.

¬_¬
RandomLogic
RandomLogic
Hey,

Thanks for the advice. I rand into a different problem now...
I changed my rendering function to draw a single buffer instead of many. All the particles are now being drawn in the same place on screen (i.e. overlapping) while the enitre batch moves and rotates. I obviously have''nt set the matrices correctly.

How shold I do it? BTW I set the vertices of the quads like this:

quads.x = partPos - 0.5
quads[i].y = partPos - 0.5
.
.
.
quads[i+3].x = partPos + 0.5
quads[i+3].y = partPos + 0.5

and I don''t touch the z.

Cheers,
Random Logic

There aren't any stupid questions,Only stupid people.
RandomLogic
RandomLogic
After further considiration I decided that not touching z values is stupid (I want to position the particle somewhere in the world don''t I?). Anyways it still don''t work. from my understanding what should work is to set the world matrix to be the inverse of the rotation of the view matrix. Am I wrong?

Anyone, please drop in the code you use to set up the matrices for particle rendering.

Cheers,
Radndom Logic
There aren't any stupid questions,Only stupid people.
3dModelMan
3dModelMan
I''ve posted this link before but it basically shows you how to define a particle using just a point in world space and a size, then how to calculate the vertices using the view matrix.

I''m stuffing my particles into one big vertex buffer, which has to be changed every time the particle system is updated - not every frame. I''m sure you could live with updating the particles 15 or 20 times a second instead of 100+.

My final optimisation is to support multi-textures. The particles are sorted by texture. So each particle has a point in world space, a size, and a texture index. So they are sorted every update before the VB is rebuilt. Then I keep track of how many particles to draw with each texture.

- Matt
RandomLogic
RandomLogic
Once more (with feeling)...

After I set a VB with all particles positioned according to their respective x,y,z, I should create a single world matrix that represents the rotation towards the camera (such that each particle is rotated around it''s originto match the camera''s rotation), then set it. projection and view should stay the same, then I render the whole VB with a single TRIANGLE_LIST call.

Is this right? cuz it does''nt work for me.
Please drop in a snippet if you''ve done something similar

Cheers,
Random Logic
There aren't any stupid questions,Only stupid people.
3dModelMan
3dModelMan
No it''s not right.

Take a look at that link I posted. You will need to recalculate the all vertex coordinates every time the camera moves and/or every time you update the particle system. Using that method you will end up will all the particles facing the camera and all the vertices in world space. Use an identity matrix as your world transform, then you can render all of the particles at once.

As long as the particles remain in their own space, you will have to apply individual transformations on them and draw them one at a time. That''s why the tutorial uses a single point in space to define the particle position, then calculates the position of each vertex using the view vectors.


SoaringTortoise
SoaringTortoise
The problems with point-sprites:

1) Can''t change the size of a single PS, have to change for all (no optimisation for slowly expanding/contracting particles from multiple emitters).
2) Can''t change the texture per PS (have to split into multiple PS buffers)
3) You are forced to use BB''s, so you can''t use your particle update code to render giblets or similar chunky meshes that basically behave the same as particles.
4) Because you are forced to store by texture, you can get serious alpha glitches because you can''t easilly sort by depth and texture.





Learning to fly is easy, but as a tortoise, the landings are really rough.
Always prey on the weak, the timid and the stupid. Otherwise you'll just get your butt kicked
For a tortoise, this is extremely hard to do, but when you get it right... the expression on their faces ...
JHL
JHL
The most optimized way would be to use point sprites and vertex shaders, well you it does limit you to billboards and in the way you use textures, you can have the size change and do anything that can be represented a function of time, and it is the most optimized way.
Fuzztrek
Fuzztrek
Ah. Here''s what I do:

Lock the VB. Enter a loop, and modify all of the particles in the VB. Unlock VB, send to draw primitive. If you increase all of the particles by the same amount, all of the particles will appear to move together.
RandomLogic
RandomLogic
hi,

I DO calculate all the vertex positions every update... that wasn''t my problem. Boys and girls if you populate 4000 indices in the index buffer with a repetative pattern it''s gonna draw the same quad over and over again (doh!!). Now I have the paricle effect working but (there''s always a but isn''t there?). As I said I calculate the vertices position every update. matibee, you extract the ''view vectors'' and use them to position the vertex. What I tried to do is set the vertices so the particle''s center is positioned somewhere in world coordinates and then before I render the whole batch I set the world matrix to the oppisite rotation of the camera. This keeps the quads facing the camera but also moves them in space. Technically that should be exactly what you did there no? just instead of directly to the vertex data you use the rotation matrix? it''s as if the rotation I applied is in world coordinates and not the quads local. any idea why that is?
There aren't any stupid questions,Only stupid people.
3dModelMan
3dModelMan
quote:

matibee, you extract the ''view vectors'' and use them to position the vertex. What I tried to do is set the vertices so the particle''s center is positioned somewhere in world coordinates and then before I render the whole batch I set the world matrix to the oppisite rotation of the camera. This keeps the quads facing the camera but also moves them in space. Technically that should be exactly what you did there no?


In a word. No.

Your rotation is not being applied at the quads centre, it''s being applied at the world centre. Every particle has it''s own origin, so there''s absolutely no way you can apply one rotation transformation and expect them all to follow. This is why the view vectors are used to calculate the vertex positions when the system is updated, then there are no transformations required, since all the verts are already in world space.

quote:

it''s as if the rotation I applied is in world coordinates and not the quads local. any idea why that is?



Try experimenting or reading up on transformations. To apply rotations to an object around it''s own centre you must rotate first, then translate. Your particles are already translated, therefore cannot be rotated (not the way you expect anyhow).

- Matt

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.