Sunday, July 25, 2010

The Dreaded PNG Draw Error

For years in the virtual world, few things have plagued builders more consistently than the PNG Draw error. It rears its ugly head whenever we place PNG textures in front of other PNG textures in the virtual world and manifests as objects rendering in front of closer objects even though they are clearly farther way and should be occluded or drawn behind it.

Take for example, some trees that use PNGs with partial transparency in the Alpha map to create the leaves. under normal circumstances the leaves should sort perfectly fine and that would be the end of it, but ever since I could remember, the PNG Draw Error would foil that consistently for builders. PNGs rendering in front of closer semi-transparent objects, completely ruins the ambiance of a well constructed environment, when you look out a window and see the trees rendering in front of the window instead of behind it.

This goes for other uses of PNG as well in the virtual world, whereby partially transparent PNGs will ghost against other PNGs even if both are opaque with limited transparency (maybe the edges).

So what's going on here?

I remember this being a long standing issue in ActiveWorlds for many years (and still to this day), and was surprised to see the dreaded PNG Draw Error bug rear its ugly head in SecondLife. Years ago when I inquired about this PNG Draw Error Bug, I was told that it's a common bug and every game engine has it. No solution was available, and even commercial games (I was told) had the bug but that the level designers literally designed the levels around this bug to minimize or eliminate it to the player.

This essentially meant that multi-million dollar productions were rearranging entire levels to make sure that as little as possible in the way of PNG transparency overlapped, because it would trigger this bug.

I'm not fool, but the thought of major game brands like Square Enix being terrified of this bug amuses me, and more so that they would go to great lengths to work around it without actually having a solution for it.

After some testing in Second Life, I finally got fed up and decided to dig deeper into this infamous bug, and what could possibly be the issue. In the beginning, I simply thought that the programmers at Linden Lab and Active Worlds were simply chained to a certain Alpha Rendering algorithm and could not change it, but then I realized during testing that they actually aren't chained to the Alpha rendering algorithm.

Instead, it would seem that it's not a matter of there being no solution for this bug, but that a majority (if not all) game engine programmers simply are using the default Alpha rendering algorithm chain. The default for game engines would be excellent blending of the textures, but apparently horrible at sorting the depth of the textures to the camera, and while this is fairly quick, there exists another Alpha sorting algorithm in the SecondLife viewer - RenderFastAlpha.

RenderFastAlpha (in your Debug settings) is actually the Alpha Rendering algorithm known as Clip Alpha or Binary Alpha, whereby it doesn't take into account partial transparency for PNGs, and instead renders as completely transparent or completely opaque. When enabled in SecondLife, the blending is obviously gone (the textures don't look as nice) but the benefit is that the PNG textures suddenly snap to proper depth sorting like magic.

After seeing this in action, I cross referenced the behavior of RenderFastAlpha to known Alpha Rendering Algorithms and found that it's a perfect match for Binary Alpha (Clip Alpha). So now I understand what exact type of algorithm is being used for RenderFastAlpha in the debug options, but the task was figuring out what rendering algorithm was being used as the default Alpha Rendering in Second Life.

A little bit of digging yielded the answer I was looking for: The default Alpha Rendering in Second Life is actually the Default Alpha Rendering Algorithm for the 3D engine. It's the industry preferred default because it blends the textures nicely and looks good, and has a negligible rendering cost on the pipeline, even though it is notorious for causing PNG Draw Errors for depth.

Now that I've sorted out the two known Alpha Rendering algorithms in use, it was time to sit down and figure out how to solve the PNG Draw Order Error.

This part seemed to be the easiest, and I was quite surprised at how fast I found the solution. Where most game engines default to Alpha which has draw order issues, and they also have an easy way to enable Clip Alpha (Binary Alpha), there is a third and more powerful Alpha Rendering Algorithm at our disposal.

This is known as Alpha + Sort

Alpha + Sort essentially does what Alpha normally does with the blending, but then it takes an extra step and runs a sorting algorithm in order to make sure the items are rending in proper depth in relation to the camera (user). This is also an algorithm which is supposedly a bit more costly on the computation side of things and as such is normally disabled by default, leaving the programmer to manually turn it on to use it.

Could the solution to this problem that has plagued virtual environments since the mid 1990's be as simple as enabling a single option in the code?

I would assume so at this point, although it is possible that with custom engines (like what SecondLife uses) there wasn't coded in the ability to use Alpha + Sort as a rendering pipeline to handle the partial transparency of textures properly. The same could be said for ActiveWorlds whereby it can be noted that the Alpha rendering default seems to be just that; the Alpha Rendering Default in the engine, which then brings into the equation the PNG Draw Order Error bug.

But let's say that the Alpha + Sort option still isn't a total solution, because I've seen quite a bit about how it will still have the bug in certain circumstances. So if Alpha + Sort isn't the holy grail, then what is?

Enter the idea of making a new algorithm called Binary Alpha + Sort Transparency Algorithm for Rendering Defaults. As the name implies, it's a combination of techniques and not solely from a single approach. It also makes a great acronym :)

In any event, the point of this idea is that Binary Alpha seems to have no problem with sorting properly, but the looks could be better. If Binary Alpha can figure out where the order is supposed to be most of the time (properly) then why not use a combination of Binary Alpha and Alpha to really hammer it down and eliminate the bug?

We know Binary Alpha can sort it correctly, so why not just use Binary Alpha and then add an extra step by using the sort information of Binary Alpha (which is more reliable for sorting) then doing the Alpha blend (default) to make it look good on screen, while ignoring the default Alpha pass sorting in favor of the Binary Alpha sorting information from the prior pass?

In short, the best of both worlds.

I'm still a bit biased, though, and believe that Alpha + Sort would take care of the problem.

Still confused about what this whole Alpha Rendering Algorithm stuff is all about? Luckily I've included an educational video for you below:





No comments:

Post a Comment