Particles Causing Slow Rendering

Started by
11 comments, last by C0lumbo 10 years, 8 months ago

The particles engine works fine, but when I put some heavy smoke or heavy fire and the player look directly at them, I get slow rendering (20 - 30 FPS) normally I get (60 - 61 FPS).

I'm using 4 vertices per particle (camera facing billboards)

Also, I'm rendering all of them in one single draw call.

This problem happen in both debug and release mode.

GPU: GTX 550 Ti

Advertisement

Particles can be pretty devastating for fill rate, especially on a PC with large resolutions. You can confirm if you're fill-rate bound by setting up a scissor rect so you're only rendering to a small square of the screen and seeing if that improves your frame-rate.

If you are fill rate bound, you should make sure your pixel shader is as optimised as it can be. You should make sure you render all your opaque stuff, and then render your particles with depth testing on. You could try to make a similar looking effect with fewer layers of particles. I've also heard that people often render their particles to a lower resolution render target, then copy that over onto their main frame buffer, but I've never implemented it myself.

why not use point sprites? You'd have a 4th of the vertices to render

Vertices hardly will be the performance problem here, pixels (fill rate) are usually problematic with particle systems. And the GPU internally has to render the point sprites as quads anyway (I guess), so you are just saving some memory (smaller vertex buffer).

I personaly stopped using point sprites when I got into some problems with them on different GPUs - they had different sizes on the screen with the same values. And also the maximum size is limited and the limit can be quite small on some GPUs.

I agree it's not the problem, I was just suggesting point sprites overall :)

@C0lumbo:

> "and then render your particles with depth testing on."

I can test particles depth with the scene depth, but how do I test particles depth with other particles depth?


I agree it's not the problem, I was just suggesting point sprites overall smile.png

Point sprites have, as already suggested, several drawbacks/issues and limitations, so I wouldn't really suggest them, given that the gain is very minimal - eventually you might want to use hardware instancing in some form or another, so what you save is literally the space for 3 vertices. Also, point sprites can be just that-a completely screen-aligned quad, while particles can come in many variations - locked around a certain axis, oriented towards their move direction, all things you can't emulate with point sprites at all. So I would rather recommend not using them at all, anymore...


I can test particles depth with the scene depth, but how do I test particles depth with other particles depth?

Not to want to speak for someone else, but thats not what he probably meant, he most likely suggested testing against the scene depth, so that at least you won't draw in parts where particles are covered by something from the scene. Two ways however to achieve some effect of this sort were to:

- Enable alpha testing, and clip all alpha beyond 0.01 (or any such small value). I don't know if it improved performance in that you render fewer pixels, but at least you could now enable depth rendering/testing for particles that have a transparent "background" and are themselves mostly solid.

- Use a depth stencil, and increment stencil at each pixel you render a particle to per 1. Now after a certain threshold, like 6, you discard any further pixels at this spot. Works best in combination with the method above, and can give quite a speed boost in your case.

^ You cant use alpha-testing when simulating smoke or fire, unless you want it to look bad.

@Medo

Don't get confused, you already have "depth testing" on, and it would be stupid in this case to have it off anyway.

The best thing to be done is to decrease particles count when they occupy most of the screen space.

EDIT: How it can be done:

1. Get approximate OBB of emitted particles.

2. Transform 8 points of that box into screen space

3. Compute screen axis aligned rectangle from those points

4. If volume of rectangle is occupying (say) 70% of the screen space decrease particle count emitted.


You cant use alpha-testing when simulating smoke or fire, unless you want it to look bad.

Well, you can at least enable alpha testing with a very low test value near 0.0f, to cull away the completely transparent parts... again, I don't know if this actually helps performance or not, but at least in DX11 clip() sometimes seems to help, so it might be worth a try. You are probably right that you can't use alpha-testing with depth-write here, though.


Not to want to speak for someone else, but thats not what he probably meant, he most likely suggested testing against the scene depth, so that at least you won't draw in parts where particles are covered by something from the scene. Two ways however to achieve some effect of this sort were to:

Yes, that is what I meant.

Couple of other tips (if you are indeed fill-rate bound)

- Make sure that your UV coordinates are fitting tightly around the relevant part of the particle texture. You'd be amazed how often I find particles being rendered where half the fill rate is wasted because the smoke or fire bit of the texture only occupies the centre of the particle texture tile instead of filling it properly..

- Have your particle system fade out particles as they get close to the camera. This should be a parameter in your particle setup so you can tune it for each type of particle. Not only does this improve the visuals by getting rid of the horrible jarring disappearance of a particle as it moves past your near clip plane, you will also be able to push out the fade out distance to reduce fill rate problems.

Edit: Probably the biggest easiest win will be to use fewer particles though. e.g. Use 8 smoke particles at 0.2 opacity each instead of 16 smoke particles at 0.1 opacity each, etc.

This topic is closed to new replies.

Advertisement