GLSL Programming/Unity/Layers of Textures

This tutorial introduces multitexturing, i.e. the use of multiple texture images in a shader.

It extends the shader code of to multiple textures and shows a way of combining them. If you haven't read that tutorial, this would be a very good opportunity to read it.

Layers of Surfaces
Many real surfaces (e.g. the human skin illustrated in the image ) consist of several layers of different colors, transparencies, reflectivities, etc. If the topmost layer is opaque and doesn't transmit any light, this doesn't really matter for rendering the surface. However, in many cases the topmost layer is (semi)transparent and therefore an accurate rendering of the surface has to take multiple layers into account.

In fact, the specular reflection that is included in the Phong reflection model (see ) often corresponds to a transparent layer that reflects light: sweat on human skin, wax on fruits, transparent plastics with embedded pigment particles, etc. On the other hand, the diffuse reflection corresponds to the layer(s) below the topmost transparent layer.

Lighting such layered surfaces doesn't require a geometric model of the layers: they can be represented by a single, infinitely thin polygon mesh. However, the lighting computation has to compute different reflections for different layers and has to take the transmission of light between layers into account (both when light enters the layer and when it exits the layer). Examples of this approach are included in the “Dawn” demo by Nvidia (see Chapter 3 of the book “GPU Gems”, which is available online) and the “Human Head” demo by Nvidia (see Chapter 14 of the book “GPU Gems 3”, which is also available online).

A full description of these processes is beyond the scope of this tutorial. Suffice to say that layers are often associated with texture images to specify their characteristics. Here we just show how to use two textures and one particular way of combining them. The example is in fact not related to layers and therefore illustrates that multitexturing has more applications than layers of surfaces.



Lit and Unlit Earth
Due to human activities, the unlit side of the Earth is not completely dark. Instead, artificial lights mark the position and extension of cities as shown in the image. Therefore, diffuse lighting of the Earth should not just dim the texture image for the sunlit surface but actually blend it to the unlit texture image. Note that the sunlit Earth is far brighter than human-made lights on the unlit side; however, we reduce this contrast in order to show off the nighttime texture.

The shader code extends the code from to two texture images and uses the computation described in  for a single, directional light source:

$$I_\text{diffuse} = I_\text{incoming}\,k_\text{diffuse} \max(0,\mathbf{N}\cdot \mathbf{L})$$

According to this equation, the level of diffuse lighting  is max(0, N·L). We then blend the colors of the daytime texture and the nighttime texture based on. This could be achieved by multiplying the daytime color with  and multiplying the nighttime color with   before adding them to determine the fragment's color. Alternatively, the built-in GLSL function  can be used, which is likely to be more efficient. Thus, the fragment shader could be: Note that this blending is very similar to the alpha blending that was discussed in except that we perform the blending inside a fragment shader and use   instead of the alpha component (i.e. the opacity) of the texture that should be blended “over” the other texture. In fact, if  specified an alpha component (see ), we could use this alpha component to blend   over. This is actually what Unity's standard  shader does and it corresponds to a layer which is partially transparent on top of an opaque layer that is visible where the topmost layer is transparent.

Complete Shader Code
The names of the properties of the shader were chosen to agree with the property names of the fallback shader — in this case the  shader (note that the fallback   shade and the standard   shader appear to use the two textures in opposite ways). Also, an additional property  is introduced and multiplied (component-wise) to the texture color of the nighttime texture in order to control its overall brightness. Furthermore, the color of the light source  is multiplied (also component-wise) to the color of the daytime texture in order to take colored light sources into account.

When you run this shader, make sure that you have an activated directional light source in your scene.

Summary
Congratulations! You have reached the end of the last tutorial on basic texturing. We have looked at:
 * How layers of surfaces can influence the appearance of materials (e.g. human skin, waxed fruits, plastics, etc.)
 * How artificial lights on the unlit side can be taken into account when texturing a sphere representing the Earth.
 * How to implement this technique in a shader.
 * How this is related to blending an alpha texture over a second opaque texture.