Draw order and the z-buffer

I’m working on a 2D game. To get the proper draw ordering I use an orthographic camera, and draw objects at different depths. I have depth-ranges for different types of objects, for example all characters have a certain range, and all items have another range, so that characters always appear above items. The ranges are necessary because I can’t have all characters or items at the exact same depth because they will flicker when they collide. This works alright, but when I have too many items in a certain range the z-buffer issues kick in and I get flickering. This problem seems to be magnified in a windows executable.

What I would prefer is that everything is drawn in the order it appears in the object hierarchy, or some other definable order. So is there a way to turn off the z-buffering and draw objects in a predetermined sequence?

You likely have several options:

  1. You’re probably wasting a lot of your zbuffer precision… try making the near clip and far clips bracket your scene depth as closely as your able… this should get rid of all the zfighting you’re seeing. (Moving out your near clip should be particularly effective)

  2. You could probably use a transparency shader, transparency gets sorted by the app from farthest to closest because it doesn’t set the z, so it needs to draw this way in order to look right. Doing this though will be a performance hit since foreground pixels don’t occlude background ones, thus allowing the hardware to early out during the ztest.

  3. You could set objects using layers to render to specific cameras, and then use the “depth” setting on the cameras to force an order on them (set a camera mask to match a layer mask and only objects in that layer will draw). If you don’t clear the buffers with each camera then they’ll build up, one on top of another. Again, you lose performance because you won’t occlude deeper pixels in the buffer (cameras draw in order of low numbers first to high numbers later)

  4. Lastly, if you want to get really fancy, you could write your own shader, and include a member variable that sets a depth offset in the opaque pass: see info in the user manual here on tags and render queues (maybe Aras or one of the other more knowledgeable types can validate if this would work per object, or if it would only work by creating seperate materials):

http://unity3d.com/support/documentation/Manual/SL-NameAndTags.html

Hope that helps.

Tz

You could also use an static var for every range you have so you move that value a little every time you create an object for that range.

For example:

  • From 10.0f to 20.0f are your enemies
  • Set value for Static variable to 10.0f
  • Every time you create and enemy, assign the z component of his position to the static variable, and add 0.1f to this static variable afterwards.
  • If the variable reach 20.0f, then reset to 10.0f

By the time you reset the variable, the enemy in that depth will certainly be dead, so the flickering is not probable to happen.

Hope this helps.

.ORG

I’m now using Tz’s transparency shader idea and it seems to work just fine. Thanks guys!