GLSL Programming/Unity/Transparent Textures

This tutorial covers various common uses of alpha texture maps, i.e. RGBA texture images with an A (alpha) component that specifies the opacity of texels.

It combines the shader code of with concepts that were introduced in  and.

If you haven't read these tutorials, this would be a very good opportunity to read them.

Discarding Transparent Fragments
Let's start with discarding fragments as explained in. Follow the steps described in and assign the image  to the material of a sphere with the following shader:

The fragment shader reads the RGBA texture and compares the alpha value against a user-specified threshold. If the alpha value is less than the threshold, the fragment is discarded and the surface appears transparent.

Alpha Testing
The same effect as described above can be implemented with an alpha test. The advantage of the alpha test is that it runs also on older hardware that doesn't support GLSL. Here is the code, which results in more or less the same result as the shader above:

Here, no explicit  instruction is necessary but the alpha test has to be configured to pass only those fragments with an alpha value of more than the   property; otherwise they are discarded. More details about the alpha test are available in Unity's ShaderLab documentation.

Note that the alpha test and the  instruction are rather slow on some platforms, in particular on mobile devices. Thus, blending is often a more efficient alternative.

Blending
The described how to render semitransparent objects with alpha blending. Combining this with an RGBA texture results in this code:

Note that all texels with an alpha value of 0 are black in this particular texture image. In fact, the colors in this texture image are “premultiplied” with their alpha value. (Such colors are also called “opacity-weighted.”) Thus, for this particular image, we should actually specify the blend equation for premultiplied colors in order to avoid another multiplication of the colors with their alpha value in the blend equation. Therefore, an improvement of the shader (for this particular texture image) is to employ the following blend specification in both passes:



Blending with Customized Colors
We should not end this tutorial without a somewhat more practical application of the presented techniques. is an image of a globe with semitransparent blue oceans, which I found on Wikimedia Commons. There is some lighting (or silhouette enhancement) going on, which I didn't try to reproduce. Instead, I only tried to reproduce the basic idea of semitransparent oceans with the following shader, which ignores the RGB colors of the texture map and replaces them by specific colors based on the alpha value:

Of course, it would be interesting to add lighting and silhouette enhancement to this shader. One could also change the opaque, green color in order to take the texture color into account, e.g. with:

which emphasizes the green component by multiplying it with 2 and dims the red and blue components by multiplying them with 0.5. However, this results in oversaturated green that is clamped to the maximum intensity. This can be avoided by halving the difference of the green component to the maximum intensity 1. This difference is ; half of it is   and the value corresponding to this reduced distance to the maximum intensity is:. Thus, in order to avoid oversaturation of green, we could use (instead of the opaque green color):

In practice, one has to try various possibilities for such color transformations. To this end, the use of numeric shader properties (e.g. for the factors 0.5 in the line above) is particularly useful to interactively explore the possibilities.

Summary
Congratulations! You have reached the end of this rather long tutorial. We have looked at:
 * How discarding fragments can be combined with alpha texture maps.
 * How the alpha test can be used to achieve the same effect.
 * How alpha texture maps can be used for blending.
 * How alpha texture maps can be used to determine colors.