Nolimits 2 (materials part 4): Specular maps

Specular Maps & Reflection

Before you start this tutorial, I’d recommend taking a look at my first tutorial on specularity. (Blog) Note that since writing that, the NL2MAT editor has changed slightly, the shininess box has been changed to a slider named glossiness, however, it still has the same behaviour.


Download the park package with assets

Continuing the theme of ruining a medieval building, I have littered the nearby area with hazardous materials containers. Using the guidelines I set in that first tutorial, I have created a basic material for this new crate.

It looks pretty good right now, with the specularity conveying the look of painted metal quite well. However, some areas of the texture don’t quite match what I had in mind. I wanted the grey handles on the side to be a mirrored chrome finish, and I wanted the decals on the faces to a plasticised sticker, with more of a sheen than the paint.

We could get the chrome handle finish by separating the crate into two materials, but this wouldn’t work with the decals. We can instead achieve these multiple layers of specularity with specular maps, which specify the specular colour for every pixel on the texture.

How to use specular mapping

If you’re a Crazybump user, it’s very easy to generate specular maps for all of your textures. However, I’d personally recommend using specular mapping on as few materials as you can get away with. If you’re simply running your texture through Crazybump and outputting a specular map, you’ve probably not correctly set up your specular colour and glossiness settings. Instead, specular mapping should be used to represent different physical materials. This makes our crate a good candidate for specular mapping.

For our texture, we’ll basically be working with 3 levels of specularity. Our blue paint is the lowest specularity, with the chrome handles being the highest. The decals lie somewhere in between. In comparison to a Crazybump generated specularity map on the left, our specular map on the right is far simpler.

I’ve simply drawn over the decals in medium grey and the UV areas of the chrome in white. A PSD for this texture is included in the park package if you want to try doing this yourself, It also has the full UV wireframe. The metal is currently black, meaning there would be no specularity, but we’ll fix this by modifying the texture within the shading language.

Shading: Diffuse Textures

The material for this asset is slightly more complex that the previous tutorial, as we have a detail texture included. This is a common technique in games, where we have a “base” texture, which is tiled more times than the main texture (Using a Texture Coordinate Modifier in NL2) to give it more detail when observed up close. In this case, our detail texture is a slightly blemished metal. The normal map for the material also corresponds to this texture, as we don’t need a normal map for the main texture (all the details are in the mesh)

Therefore, the textures we are interested in for the shader are:
Diffuse – Texture unit 0
Specular – Texture unit 0 (alpha channel)
Detail Diffuse – Texture unit 1

Result.rgb = Mul(Tex0, Tex1);

This first line replicates the default behaviour of NL2 materials that have more than one diffuse texture. They’re combined by multiplication, producing the same effect as a multiply layer blend in Photoshop. This is to apply the detail texture on top of our main texture.

Mul (Multiply) is one of the several functions available to you in the shader language. The rest, along with all of the other documentation on the shader language, is available in the NL2 help page titled “NL2MAT Programmable Shader Core Language”. For now, functions take a number of parameters inside the parentheses, separated by commas, this function multiplies each pixel of the textures with the other texture as stated within the parentheses. In this case, we store this resulting texture in “Result”, our diffuse colour for our material. (Read more about this storing in the first shading tutorial)

Colour Values

A necessary tangent here. Calling this blending technique a multiplication operation may seem confusing to any of you who are familiar with Photoshop and digital colour. Multiplying the colour value {128, 128, 128} (50% grey) by itself would surely produce the horrendously unrepresentable {16384, 16384, 16384}, but if you try this in photoshop, the resulting colour value is {64, 64, 64}. (25% grey)

Inside a graphics library such as OpenGL – or in NL2s case, DirectX – colour values are converted from 0..255 ranges into 0..1 ranges. Therefore, 0.0 is black, 0.5 is medium grey and 1.0 is white. Mathematical operations on colours are now much more useful, with an effect being that multiplying two non-HDR images together will always produce a darker (or equal) result. For our example above, rather than calculating 128 x 128, we actually calculated 0.5 x 0.5, resulting in 0.25. When converted back into the 0..255 range, that gave us the result of {64, 64, 64}.

Just bear in mind that in the shading language in NL2, you have to specify all of your colour values in 0..1 ranges. To convert to 0..1 range, just divide the RGB value by 255, and multiply the 0..1 range by 255 to get back to RGB. (You don’t need to convert anything between these two ranges in your shaders, this is just to help you pick colours)

Shading: Specularity

Once your happy with how the two diffuse texture were combined, applying our specular map is straightforward. I’ve stored the specular map in the alpha channel of our main diffuse texture, so all we need to do is assign that channel to “Specular”, another register like Result.

Result.rgb = Mul(Tex0, Tex1);
Specular = Tex0.a;

In my specular map, the metal currently has zero specularity, I can increase that by adding a value across the whole texture. each pixel value is increased by 0.1, and in the case of materials that were already at 1.0, such as the chrome areas, values that exceed 1.0 are clipped back to 1.0 when rendered.

Result.rgb = Mul(Tex0, Tex1);
Specular = Add(Tex0.a, 0.1);

Specularity effects are a lot easier to discern in motion, but you can instantly see an improvement in the metal handles, which look far shinier than the rest of the model. You may also to be able to see that the decal is now more specular that the surrounding metal on the face that is catching the sun.


A cool thing about reflections is that their strength is also mapped to the Specular registers, therefore the specular map is also a reflection map, as long as we have reflections enabled in NL2MAT. You should set the reflection properties for the most reflective physical material in your texture. Becuase I have a chromed handle, I have set the fresnel to 1.0, fully reflective.


One of the great features of NL2 Pro that doesn’t seem to be used that often is the ability to capture cubemap screenshots. These can be fed straight back into the game for improved reflections. NL2 generates a default cubemap based on the environment and terrain, but to include objects and other details, you’ll need to create a custom cubemap, and import it into the box in the interface shown above. (ensure the ordering is the same as listed)

The custom cubemap gains a lot of detail, but because it is captured from a static viewpoint, it becomes incorrect as you move around the scene. You should therefore either use the cubemap on a material where the reflections are heavily distorted by the normal map, or you should blur the cubemap by capturing them with the “Cube-screenshot Filter-Passes” Picture export option set to a high number. (range 0-100 accepted, around >30 for significant blur)

Cubemaps will be a requirement in interior scenes or areas with strong lighting cues. For example, this tile floor in Point solitude uses a custom cubemap reflection: