Transparency map
Contents
Transparency Map
A transparency map creates per-pixel transparency. Also called Opacity or Alpha.
A grayscale bitmap can be used for transparency, but in order to reduce texture fetches usually transparency is done with the alpha channel of the DiffuseMap.
Vertex alpha can also be used for per-vertex transparency, either instead of a bitmap, or in combination with one.
Transparency Techniques
There are a bunch of methods available for real-time transparency, each with their own benefits and drawbacks. Below are a few of the most common methods.
<<Anchor(AlphaBlend)>>
Alpha Blend
Alpha blend is a soft transparency technique, where you can use a full gradient of transparency values, for soft-edged transparency and partial translucency. Usually you get 256 levels of gray, white being totally solid and black being totally transparent. Some textures use less grays to compress the file size in order to save memory (see).
Alpha blend is fill-rate expensive. There's an increasing cost for using multiple overlapping alpha blend meshes, like particles or tree leaves or grass. The fill rate increases, because the renderer can't use the usual methods for discarding hidden pixels, so the same screen pixels are drawn over and over again. An expensive fill-rate means the framerate gets slower.
Sorting problems often happen with this method.
<<Anchor(AlphaTest)>>
Alpha Test
Alpha test is a totally-hard transparency technique, the pixels are either completely solid or completely clear, there are no soft edges. Each screen pixel is tested by the shader to tell if it should be on or off, using a threshold value. Alpha pixels darker than the threshold are clipped out, brighter alpha pixels are left solid.
Even though it's only on vs. off, if you use a smooth grayscale in your alpha you get a smoother result when it's clipped. If you use an alpha that's only black vs. white you tend to get large stairsteps when it is alpha tested.
There are no depth sorting problems with alpha test, but there's also no anti-aliasing so it can get very pixelly at a distance. Alpha test is much faster to render in real-time than alpha blend.
<<Anchor(ScreenSpaceStipple)>>
Screen Space Stipple
Screen space stipple uses the alpha test method but tries to fake the soft edge of alpha blend by drawing/not drawing pixels in dither patterns, at the resolution of the screen pixels. It writes depth and doesn't blend, so it's cheap and sorts automatically. The downside is that at low screen resolutions it looks horribly pixellated.
<<Anchor(AlphaToCoverage)>>
Alpha To Coverage
Alpha-to-coverage is similar to alpha test in that it requires no depth sorting, but it uses multisampling to give a softer edge. It allows for about 9 levels of transparency, though these are dithered together to give more apparent levels of transparency. It renders in a single pass, but you need at least 4x MSAA (multisampled anti-aliasing) which is not available on all hardware (NVIDIA GeForce 7 and later). Humus has a demo on his site, with sample code. Marmoset Toolbag also has alpha-to-coverage support.
<<Anchor(SignedDistanceAlphaTest)>>
Signed Distance Alpha Test
Signed distance alpha test is also similar to alpha test, except it allows the texture size to be extremely small and still get decent results. Valve Software has a paper from SIGGRAPH 2007, Improved Alpha-Tested Magnification for Vector Textures and Special Effects. Gamedev.net has a thread with a demo app and pics.
Hybrid Approaches
- Rendering Plants with Smooth Edges from the Wolfire Blog shows various tests and a hybrid alpha-test/alpha-blend approach.
<<Anchor(SortingProblems)>>
Sorting Problems
If you use alpha blend, and multiple transparent surfaces are overlapping in the same mesh (like hair pieces) then the depth sorting will probably be bad. Parts of the background will show through, instead of the rest of the transparent faces.
Most surfaces in a game are sorted using the z buffer (a rendering of the depth of the scene). This allows the renderer to draw each pixel the least amount of times, by not rendering any pixels that are overlapped by others. However with translucency each pixel needs to be drawn more than once, and each of those "draws" has to be sorted in the right order or you get errors. Unfortunately the z buffer disregards translucency completely and only renders all polygons completely opaque, so it generally can't be used for sorting them.
To draw a transparent surface the renderer has to figure out all the things to render behind it, so it has a final color that it can blend the partially-transparent pixel with. The renderer basically needs two colors for each blending operation, the source (the surface's pixel) and the destination (whatever is behind).
For speed usually a game renderer tries to find the destination color the fastest it can. To sort separate surfaces, the renderer will compare the center of one surface with the center of another, to figure out what's in front (source) vs. behind (destination). As long as the two surfaces don't intersect each other, they'll be rendered in the right order.
The real problem comes when trying to render multiple transparent triangles within the same surface. Because it's usually too slow to compare the centers of all the triangles, a game typically just renders the triangles in the order it receives them. Which is usually the order the artist has modeled them.
The solution for perfect per-pixel transparency would be to sort per-pixel, or if sorting per-triangle then to subdivide the mesh at every internal intersection so there are no interpenetrating triangles. However this has the potential to increase the vertex count of a model to prohibitive levels very quickly. Both these methods are still way too slow for real-time framerates.
<<Anchor(SortingFixes)>>
Sorting Fixes
Because a game renderer typically renders transparent triangles in the order they were made, an artist can often fix sorting errors by manually re-ordering the vertices.
A renderer usually draws vertices in the order it receives them; this can be exploited to help it draw alpha blended surfaces in the order that's desired. The behind-most faces are drawn first, and the front-most faces are drawn last, with the rest drawn in order between those.
Simply detach each overlapping transparent element into a separate object, then re-attach them in the order you want them to draw. As long as the elements do not interpenetrate themselves (or others) then they should sort correctly. This doesn't need to be done for each triangle, typically it can be done for multiple-triangle elements, like hair pieces. The trick is to figure out which angle the overlapping elements will most commonly be seen from, and work towards that.
3ds Max has three quality settings for viewport transparency: None (alpha blend or off), Simple (alpha test), and Best (alpha blend). However the settings do not affect DirectX Shader materials, they only seem to affect Hardware Shaders.
Maya supports per-polygon sorting with transparent CgFX shaders. In the Maya viewport under Shading, turn off object transparency sorting and turn on polygon transparency sorting. This tells Maya to sort each polygon by its center, rather than each object. Maya detects whether the blending state is enabled in the first pass. If blending is enabled, Maya uses the Object Transparency Sorting or Polygon Transparency Sorting options in the viewport to correctly render the transparent shader.
Blending Operations
Usually the transparency map combines the surface's color (source) with the background color (destination) in a linear way like the "Normal" blending mode in Photoshop. The most common transparency blending methods in games are Normal (aka Lerp), Additive, and Multiply, however there are many others available as well.
- An Explanation of Photoshop Blend Modes - from an artist's perspective
- Photoshop Blend Mode Math - from an coder's perspective