I was busy implementing basic transparency in a prototype I'm working on when something occurred to me.

In order for a given texture's transparency to work as expected, the (semi-)transparent texture must be drawn after whatever is behind it, right?

Well, if we take for example a tree or shrub in a game like Skyrim, the texture(s) that make up the foliage on that tree or shrub must include some transparency somewhere, right? A vertex-perfect leaf model would be far too resource-intensive. But the player can move around, and sometimes through, any plant at will, thus changing the relative position of all textures to the camera.

Doesn't this mean that the game has to constantly Z-sort all textures, both between models and even within a single plant model, whenever the player moves (so potentially every single frame)? Isn't that very resource-intensive? How do games with lots of partially transparent textures deal with this?

  • 1
    \$\begingroup\$ Games usually use alpha testing for foliage, which can be handled by the hardware Z-buffer, rather than full alpha blending, which requires intensive sorting as you describe. For more information see this similar question. \$\endgroup\$ Jun 4, 2013 at 17:43

1 Answer 1


For general transparency handling, you could use some form of order-independent transparency.

Typically, though, you sort by Z-distance along the camera view vector before rendering (you can get a "good enough for most uses" approximate with dot(camera.view, object.worldpos - camera.worldpos)). A high-powered rendering pipeline will sort all of its objects by constructing an integer key (Wolfire has a nice article on this I can't for the life of me find right now, sorry) and then radix sorting on that. The key would be something like [alpha flag, depth, material index, mesh index] all packed into a 32-bit or 64-bit integer. The depth should be reversed for opaque objects. The idea is to make it so that after sorting, objects are in the order to be drawn (opaque in a closest-first order, transparent in a farthest-first order, objects with identical materials or meshes grouped together).

The advantage of sorting everything is three-fold. First, it allows transparency to function without advanced order-independent techniques (most of which have their own significant downsides) by ensuring that transparent objects are always drawn after opaque objects and drawn in the correct order.

Second, it allows objects with similar or identical states to be batched together easily. E.g. if two scene nodes need the same shader it's more efficient to draw them together than to draw one, switch to another object/shader, and then switch back to the first shader to draw another object.

Third, it's can be highly beneficial on some hardware to draw opaque objects in a closest-first order. The reason being that hierarchical-Z and early-Z techniques commonly implemented in hardware will ensure that fragment shaders are not run for hidden geometry and hence will drastically cut down compute overhead and overdraw. Some hardware implicitly sorts fragments itself or has more GPU power available than the CPU has capability to sort objects, so as always, profile and test on target hardware.

For foliage specifically, as Nathan Reed commented, you can avoid all the extra work by just not doing real transparency. When you have enough similar objects like a ton of foliage textures you really can't tell the difference between "proper" blended transparency and just alpha-tested transparency. Same goes for things like hair and fur. Some transparent particle effects can also use different blending techniques and get away without being sorted especially.

It's not uncommon to have multiple passes to your renderer, say one that does the object sorting/batching for "normal" objects and then an entirely separate pass for quickly rendering large amounts of foliage or the like (where the sorting might be too expensive due to the sheer number of objects). Likewise you can avoid needing to get too fancy with the sorted key generation by simply putting all opaque and all transparent objects into separate render queues where the opaque queue is always sorted and rendered first.

  • 1
    \$\begingroup\$ "Faking it" is important for deferred shading, as it has difficulty with rendering transparent objects. \$\endgroup\$ Jun 5, 2013 at 3:56
  • 1
    \$\begingroup\$ Yeah, deferred shading is not automatically superior to forward shading, for that and other reasons. Inferred lighting and some other advanced deferred techniques can deal with transparency, though. \$\endgroup\$ Jun 8, 2013 at 1:35
  • \$\begingroup\$ I'd be interested to see if we (Wolfire) actually have an article on integer keys for sorting. I joined after the deluge of blog posts, so I can't find such a post myself. As far as I can see, we just used std::sort with a custom comparison function, and only one of those sorts (particles) even uses camera distance as a sort criteria. I think we just did an article that included alpha testing: blog.wolfire.com/2009/02/rendering-plants-with-smooth-edges \$\endgroup\$ Apr 27, 2019 at 18:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .