Order-Independent Transparency using Per-Pixel Linked Lists

Here is a minimal implementation of Order-Independent Transparency using Per-Pixel Linked Lists in Panda3D, a technique for handling transparency and blending in a pixel-perfect manner.

It works by rendering the scene with a fragment shader that stores all transparent fragments in an external linked-list, with the head of that linked-list associated with the current framebuffer pixel. Then, in a post-processing shader, this list is sorted and blending is performed back-to-front. It needs advanced shader features such as SSBOs and atomic image load/store, and as such requires OpenGL 4.3. It cannot work on macOS for that reason.

There are two things that limit this implementation, which are also its biggest downfalls:

  • You need to size the buffer such that it can accommodate all transparent fragments. This could easily be a multiple of the number of pixels in the framebuffer if you are zooming in on a bunch of transparent cards that are behind each other.
  • For sorting the list efficiently, the fragments are copied to temporary registers, which is sized in my implementation to contain 8 fragments (which means there can be 8 transparent fragments behind each other). However, this implementation deals with this gracefully, by only considering the front-most 8 fragments, so this will not be noticeable, and this value can be tweaked if needed.

This is an inefficient proof of concept, it should be improved as follows:

  • Rendering all the opaque pixels first, without this shader, similar to how M_dual mode works. Then, the scene can be rendered again with this shader, with depth test enabled, only storing the transparent pixels that are for sure in front of any opaque pixels. This would significantly reduce memory pressure.
  • Optimizing memory by packing the fragment colours more efficiently into the buffer. They could be packed into a single uint even, using rgb9e5 encoding, with the alpha value packed as 8-bit together with 24-bit depth value.

glsl-oit-ppl.zip (4.7 KB)