Game Development Community

Particle sorting issue

by Lukas Joergensen · in Torque 3D Professional · 02/14/2013 (2:40 pm) · 15 replies

Hey guys!
I'm having an issue with having two particle emitters on top of each other!
It seems that if two emitters are emitting particles in the same area, T3D can't figure out what particles are in front and decides that either emitter A's particles are in front or else emitter B's particles are in front.
But this is rarely the desired outcome!

For my specific case I try to create an emitter with some clouds and then an emitter that creates raindrops which fall down from those clouds.

Recorded this video of the issue:

#1
02/14/2013 (4:02 pm)
Lukas,

Question, not a criticism. Why use two emitters when you can use a sprite sheet to get the same effect? Just asking.

Ron
#2
02/15/2013 (12:01 am)
@Ron no offense taken! :)

I'm not sure how I would achieve the same effect with spritesheets.. PLease enlighten me! :)
I may claim that I'm beginning to get my hand around the coding part of game development, but the art part is still far beyond me.
#3
02/15/2013 (12:34 am)
Does the rain emitter have "useInvAlpha" set? This is a bug I've noticed with such particles on top of others. Noticed it ever since I started with TGE 9 years ago.
#4
02/15/2013 (12:48 am)
@Jacob will be home in a couple of hours then I can confirm, but I believe it is (don't know why tho).
Would setting it to false remove the issue?
#5
02/15/2013 (7:34 am)
There have been alpha-related z-sort issues before - place a few trees near some water and then look at the tree from underwater. They might have fixed that one but I haven't looked recently.
#6
02/15/2013 (10:07 am)
Okay, tried every combination of useInvAlpha but with no luck. The problem persists.

Guess I will need to have a look into the engine then *sigh*.

Edit:
From what I can see, sorting of particles seems to be on a emitter-basis only so while you can succesfully sort particles on a single emitter, sorting particles between two emitters doesn't seem to work.
From what I can see the sorting between emitters happens like this:
ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint( camPos );
It uses the sorting distance based on the emitters world box.
I might be wrong of course, I'm not really a T3D guru ;) so would be happy if anyone could enlighten me further!
#7
02/15/2013 (10:27 am)
I've had limited success by changing
d.setZReadWrite(true, false);
To
d.setZReadWrite(true, true);
In renderParticleMgr.cpp:
_getHighResStateBlock
and in
_getMixedResStateBlock
However it gives som ugly artifacts (it acts like if the particles weren't transparent)
#8
02/15/2013 (12:31 pm)
Eh, just use so much alpha and increase particle number. That way you can't tell what is what or where.
#9
02/16/2013 (10:53 am)
@Frank
That sounds like an ugly solution :P Would prefer fixing it properly! :)

Okay so to summarize the issue:

Particles are only sorted on a per-emitter basis, meaning that particles belonging to a single emitter is sorted properly but when 2 emitter emit particles on top of each other, the particles belonging to the emitter in front will be treated as the top-most particles.

(This part is not anything I know something about so it is only guesses)
[theory]
Particles don't write to the z-buffer, so they can't tell where they are in relation to the other particles.
[/theory]

Possible solutions
1. You could construct the vertexbuffers in the renderParticleMgr.cpp instead of in the ParticleEmitter.cpp and thus get properly sorted particles (although it would be tricky to implement)

2. You could make particles write to the z-buffer as described above, although it creates some artifacts that needs to be dealt with. I guess that the artifacts is a result of the fact that the Particle shader wasn't made for particles writing to the z-buffer. But have no idea why or how to fix it.
#10
02/17/2013 (5:23 am)
According to this there is no effective way of doing it...
Sure you could do some per-particle sorting but it ends up with a massive amount of draw calls, which is not really ideal. So the best solution is to fake it I guess.
#11
02/17/2013 (6:28 am)
I haven't really looked at the particle code in ages, so I'm just shooting theory here, but what about having it where you have emitters detect if they bounds-intersect another emitter.
If it does, it takes both, turns them off, and procedurally creates a 'compound emitter', that uses particle data for both, but emits from a single emitter as far as the engine is concerned. All the emitted particles would be sorted because it's a single emitter, but you wouldn't need to do special rules for each possible combination of emitters.
I guess, think sorta how explosions use multiple emitters, and have it build something similar if the emitters intersect bounds. If they don't intersect, you don't ever need to do it. Could even flag some emitters to never become compound, etc.

Again, just tossing random theory out, but it may get around the emitters conflicting.
#12
02/17/2013 (8:41 am)
@Jeff that is also one of the ideas that I had. Except I would have done something like creating a composite emitter class rather than doing it procedurally and then use sprite sheets to be able to draw all the particles in a single draw call.
#13
02/18/2013 (3:30 pm)
Okay I tried doing the quick and dirty fix, and scale the bounding box of the rain emitter so it was smaller than the cloud emitter, this creates a whole new problem tho, now the rain particles seems to get culled out at certain angles. Like this.
Setting the particle emitter node to global bounds didn't fix the culling issue.
And setting the ParticleEmitter to global bounds wont work because it changes it's bounding box every frame.
#14
02/19/2013 (6:18 pm)
@Lukas

Why not go the opposite direction? Scale the cloud emitter up so it's slightly bigger than the rain emitter? That may prevent the culling problem of the bounds being smaller than usual, while still giving the same functional advantage.
#15
02/20/2013 (7:38 am)
Place the rain emitter just below the cloud - make it a short vertical box so it's only a unit or so thick and have it just touch the bottom of the cloud. It should be far enough from the camera that you can't really tell anyway....

Unless the rain is glowing?