So lately I wanted to use the Z buffer in opengl to order my 2D sprites in my program. Now I didn;t relaize that if you use the Z buffer then you cant blend these sprites. And some of these sprites are translucent.

My question is what can I do to fix this, by still using the handly Z buffer?


You don't, at least not for writes. Z-buffer writing/ordering and transparency is not really something you can do easily. Most techniques require significantly more work than you're likely prepared for, like using depth peeling.

Sort your objects. Typically you would sort opaque (or alpha cutout) objects front-to-back with Z-buffering enabled, then do a second pass of any translucent objects sorted back-to-front with Z-buffer writes disabled (but Z-testing still enabled!). Doing the opaque front-to-back typically helps performance when you have a lot of overdraw (overlapping objects/sprites) by avoiding drawing the same pixel fragment more than once.

The problem with Z-buffering is that there is no way for the Z-buffer to both know what the closest opaque (occluding) pixel is (in a hardware-friendly way, at least), and even if it could, transparency order matters for some blending modes. If you blend A onto B you will get a different color than if you blend B onto A in many common blending modes. You must sort the objects to get the correct output, with or without Z-buffering issues. You also need to draw the opaque objects first to blend over them.

Larger 3D engines typically handle this by having multiple render queues that sort and batch objects separately. Opaque objects can end up in one queue with Z-buffering on, and maybe with front-to-back sorting on. Translucent order-dependent objects end up in a different queue with Z writes off but reads on (you don't want to blend in translucent objects that are behind the opaque scenery!). Translucent order-independent objects (additive-blending particles most often) can be put in yet another queue with no sorting at all, Z-writes off (Z-reads still on). You can also have multiple render queues for things like UI overlays and such.

  • \$\begingroup\$ I'm sorry to ask this now, but how do you decide that which texture is opaque and which is transparent? I mean do we have to mark them? If yes, I haven't seen any of the game engines to ask you to do this. Does this mean they recognize this themselves? \$\endgroup\$ – MahanGM Jan 5 '15 at 22:50
  • \$\begingroup\$ @MahanGM: Most engines determine this by the material (specifically, whether the alpha-blending render state is enabled for the material) rather than from the image itself. \$\endgroup\$ – Sean Middleditch Jan 5 '15 at 23:38
  • \$\begingroup\$ One more question, would this sorting turn into an overhead over time? I mean in case of an engine with orthographical camera when you bring more objects to draw and they're constantly changing their z axis to make depth, you need to reorder your opaque and transparent objects every frame. Will this turn into an overhead? \$\endgroup\$ – MahanGM Jan 6 '15 at 11:21
  • \$\begingroup\$ @MahanGM: obviously it's an overhead. Will it be problematic? Depends on your game. You don't have a ton of choice: either you sort, you implement some kind of order-independent transparency (which have many limitations or their own massive perf problems), or you avoid the kinds of translucency that need sorting. A high-quality sort of render queue items can be extremely efficient and naive implementations (even just std::sort) will be quite good enough for most non-AAA games. \$\endgroup\$ – Sean Middleditch Jan 6 '15 at 19:22
  • \$\begingroup\$ I hope that's good enough for my application because that's what I'm doing now. Thank you for sharing your information, really helpful. \$\endgroup\$ – MahanGM Jan 6 '15 at 19:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.