Shader Programming, Volume 6

A Lambertian Diffuse Shader and a Toon Shader

Sebastian Monroy
3 min readJun 28, 2016

In the previous chapter we explored how we can change physical properties to simulate different materials using Surface Shaders. A lighting model is responsible for taking these properties and calculating the final shade of each pixel.

We’ll start with a really simple one that we can build upon, a Lambertian lighting model.

Chapter 3.1

Understanding Lighting Models, Creating a custom diffuse lighting model

Using the same concept as the holographic surface shader we created in Chapter 2, the intensity of light a surface reflects in a Lambertian lighting model depends on the normal of a surface. A surface parallel to a light source should reflect no light that it receives, whereas a surface orthogonal to a light source should reflect all of it. That is, the intensity of the light reflected by a surface is as follows:

Reflection Intensity = Surface Normal * Light Direction

Create a new shader and material and apply it to a sphere with a directional light on it. Here’s the code for the shader:

Note that when the dot product is negative the light is coming from the opposite side of the triangle. This isn’t a problem for opaque geometries because the triangles that are not facing the camera frontally are culled.

Check out this totally unremarkable shader.

But it works!

And it’s a great starting point for us to start building custom lighting models.

Chapter 3.1

Understanding Lighting Models, Creating a toon shader

Toon shading, or cel shading, is a non-photorealistic rendering technique that makes 3D models appear flat. Recreating the look of a toon shader using only surface functions would be extremely expensive. Additionally, because toon shading requires that we change the way light reflects, we need a custom lighting model instead.

To those unfamiliar with toon shading, note that it is a great way to make your game look quirky without putting much energy into developing an original art style. I too am guilty of this.

Link is not pleased. (from The Legend of Zelda: The Windwaker)

But, as you can see, it can look great too!

To start, create a new shader and material using our previous Lambertian shader as a base. Attach the material to a 3D model — toon shading works best on curved surfaces.

Some Toon shader implementations use a texture called a Ramp Map to define the way we remap the Lambertian light intensity (NdotL) to another value. In the implementation above, the _CelShadingLevels variable is used to snap the light intensity so that it can only assume a given number of values equidistantly sampled from 0 to 1.

In this demonstration I used a value of 5 for the _CelShadingLevels input variable. You might notice that as a result there are 5 distinct steps dividing the 6 different bands of light intensity.

In the next section we’ll cover Phong Specular lighting, a very common photorealistic lighting model used in many applications, from games to movies. It’s a bit more complicated though!

--

--