In my first material tutorial, I mentioned the methods used in rendering by OpenGL/DirectX programs, including Phong specular shading. Whilst diffuse colour depended on the angle between the surface normal and the light surface, and specular colour depended on the reflective angle between the light source and the viewer, emissive colour is constant, regardless of all environmental properties, it is similar to ambient colour in that regard.
The lighting components for such 3D programs could be summarised as:
Resultant Pixel Colour = Ambient + F(Diffuse) + G(Specular) + Emission
where F and G are complex functions which calculate the attenuation due to surface angles.
Don’t worry if you didn’t quite follow any of that, suffice it to say that Emission should be used for materials that, as suggested in the name, would emit light if they were their real-world counterparts. Therefore you’ll mostly be using emission for light bulbs, fluorescent tubes and neon lights. Today, we’re going to desecrate a medieval building by turning it into a fast food vendor, complete with garish neon signage.
I used this texture for this tutorial, you can find more choices here. I recommend picking a texture that shows the illuminated surface turned on, with as dark a background as possible, as this will make the next step easier. You’ll need to create a Diffuse texture, as normal, as well as an emission map.
The emission map should have the illuminated surfaces in white (you can do coloured emission, but white looks better in this instance). You can paint this manually, but for me, I copied the green colour channel and increased its brightness. It should be obvious for your textures which channel will make the best emission map.
My textures, as used in NL2 look like:
Create a texture in the standard way (with standard lighting), you’ll need to enable alpha test if you’re using a transparent texture like mine, and you’ll need to load the emission map into an empty texture slot, and make note of the Texture unit number you’ve loaded each texture into.
You should load this texture into to your scene at this point, to test it’s working as normal. Because we haven’t set the shading method for the second texture, the colours will look odd right now, but as long as the transparency is working as expected, you’re ready to continue.
Open your material back up, and go to the Shading tab, switching the mode to Custom.
Once you’re in custom shading model, ‘standard’ texture units are no longer automatically combined into the diffuse color of the material. This allows use to use each texture for whatever purpose we want, but that does mean we need to manually state that texture unit 0 is our diffuse texture. Therefore, our first line in our shader will be
Result = Tex0;
‘Result’ is the diffuse colour of the material. We’ll do more interesting things with this in later tutorials, but in this case, we just want it to be our diffuse texture, so we’ve directly assigned texture unit 0. If your diffuse texture was placed in another texture unit, simply replace Tex0 with Tex1, Tex2 or Tex3.
For those of you who don’t program: Assignment is the way we move data about in computer programming. Data is moved from the right-hand side of the equation to the left, so in this instance, we took our diffuse texture, and set it as the resulting colour for our texture. We place the semicolon at the end of each line, for the benefit of the compiler.
Result is known as an “output register”, which I don’t want to go into too much detail here, suffice to say they allow us to modify various aspects of rendering by outputting textures to them. They consist of:
Result Specular Ambient Emission
We’ll be using more of these in future tutorials, including a set of temporary registers which we can use for more complex shader calculations. For now, we want to set the Emission register to our Emission map in texture unit 1. Have a go at doing this yourself, the solution is below the image.
//Diffuse color Result = Tex0; //Emission Map Emission = Tex1;
Those //comment lines do nothing in terms of the shader, they’re just there to label your code, you can use them as much or as little as you’d like.
Your texture should now look a fair bit brighter. Because of the way emission lighting works, it’s going to look a lot more noticeable with less ambient & diffuse lighting, i.e. in a dark ride or at night. One final touch, emission lighting only affects the material, not objects around it. To sell the effect, garnish with omni lights, and serve.
If you didn’t use a transparent texture in your version, you can store the emission map in the alpha channel of your diffuse texture, and then you can achieve the same effect with one texture file:
the .rgb and .a select specific colour channels to affect both in Result and Tex0. In this case, we don’t want to change the result colour alpha, and we want to select the alpha channel as the source of our emission map.
In my case, we can do one better! I said that my emission map was created by just increasing the brightness of my green channel. Rather than saving that as a separate texture, we can do the brightness modifier within the shader. With my original Diffuse texture providing the correct transparency.
Result=Tex0; Emission=Mul(Tex0.g, 2);
This takes the colour in the green channel, and doubles the value, making it twice as bright. We’ll look more into these mathematical operators in the next few tutorials. Just remember that often, clever use of shaders will reduce the number of texture files you need to include in your project.