Shuriken ParticleSystem Observation #2: The perils of Sort Mode
- March 8th, 2012
- By Faust
- Write comment
First of all, the rendering order of particles within a particle-system is not really an issue unless your particle-system produces overlapping particles and they are rendered with a shader that uses an order-dependent blend. Obviously, if the particles are scattered in all directions, rarely overlapping, the order they are rendered is not going to matter. The same holds if you are using a shader like “Particles/Additive” with a blend that adds color directly to the frame-buffer, an operation which is mathematically commutative, (a+b = b+a). In these cases, you just want the fastest option, (most likely Sort Mode = None).

However, if you are using an order-dependent shader like “Particles/Alpha Blended”, a more suitable shader for something like smoke, then you have to start thinking about particle render-order and what Sort Mode option is most appropriate.
Let’s continue with a smoke effect as an example. For a cloud of relatively dense smoke particles, perhaps from a small explosion, the render-order of the smoke particles is still probably not an issue, however, if the smoke lingers for a while, you should still be concerned about whether the (possibly arbitrary) render-order of the particles remains consistent from frame to frame. If the render-order is not frame-to-frame coherent, you will likely see obvious “popping” glitches as particles suddenly appear in front of others that were previously covering it.
A Shuriken Sort Mode of None, is obviously not sorted, but it’s also (less obviously) not frame-to-frame coherent, at least, it loses frame-to-frame coherence when the particles have mixed-length lifetimes. When a particle in the middle of the particle-system’s array of active particles expires, it gets removed. To fill the array gap it leaves behind, Shuriken appears to use an algorithm which copies a particle from the end of the array into the gap. This is a fast algorithm, but it also breaks any frame-to-frame coherence. The visual “pop” you get when a particle suddenly jumps to a new location in the render-order can be real obvious, so if this problem arises, you’ll need to consider using one of the sorted options.
The additional options for Sort Mode are By Distance, Youngest First, and Oldest First. Based on my experiments, By Distance works great and does what you’d expect: particles closest to the camera are drawn last so that they appear in front of those that are farther away. The problem with By Distance is that it is most likely, by far, the most expensive choice. For each frame, a distance must be calculated for each particle and then the whole array sorted accordingly. Of course, it’s there if you need it, but if a cheaper sort works, you should probably use that instead.
So that leaves Youngest First, and Oldest First. Obviously, for Youngest First, older particles are rendered on top of younger ones and will appear closer. For Oldest First, the opposite ordering is used. But wait, what exactly do the words “Youngest” and “Oldest” mean? My first guess would be that they refer to the literal age of the particles. The oldest particles would be the ones that have been active the longest, those spawned the longest time ago. The youngest particles would be those most recently spawned. As it turns out, if your particles do not all have identical lifetimes, this is not how Shuriken interprets “Youngest” and “Oldest”. Where I prefer an “absolute-age” interpretation, Shuriken uses a “relative-age” interpretation. In other words, the particle “age” value used for the Youngest First, and Oldest First sort modes is calculated as a percentage progress through a particle’s lifetime. A particle with a 6 second lifetime that has been active for 4 seconds will be considered older than a particle with a 10 second lifetime that has been active for 5 seconds.
This is how the calculations look using the values stored in the ParticleSystem.Particle structure. (Note that startLifetime is the full-lifetime of a particle and lifetime is the remaining lifetime. They used to be named startEnergy and energy, respectively.):
absolute-age = Particle.startLifetime – Particle.lifetime
relative-age = (Particle.startLifetime – Particle.lifetime)/Particle.startLifetime
I personally find Shuriken’s relative-age sorting to be strange, and less useful, but I suppose it may have its uses. I would typically choose absolute-age Oldest First sorting for a smoke plume that will usually be observed from about the same level as the smoke emitter (looking up). A relative-age Oldest First sort might be preferred if the particle movement is linked to the lifetime somehow. Perhaps if a particle’s relative-age determined its position along a path or spline or something, but I haven’t run into these kinds of particle-systems very often.
Try out the Unity demo embedded in this post to get a feel for how the appearance of a smoke plume is affected by the chosen Sort Mode. The lifetime for these particles has a fairly wide range of 2-30. You should observe that a By Distance sort looks nice and consistent. With a setting of None, you should observe occasional popping glitches. The Oldest First sort is probably acceptable here, however, if an absolute-age sort was used, it would look more like the By Distance sort.


