Toon Shading

Johan Svensson
dotcrossdot
Published in
2 min readAug 12, 2018
Toon shader (models downloaded from Unity Asset Store)

So I’ve been working on a toon shader for a while. It was mostly an experiment where I wanted to do my own per pixel light calculations for diffuse, specular and rim light. However, I think the end result ended up quite ok. The image above shows the final result.

The complete source code can be found at the bottom of this article, but first I’ll try to go through the different parts of the shader.

Diffuse light

The shader takes a main texture and a albedo color (multiplier). It also takes a toon ramp texture, which controls the diffuse light falloff.

The shadow color can also be set, and it will affect the shadows received from other objects as well.

Specular highlight

The specular highlight can be turned on or off using a checkbox. First, a shininess value can be set to control how big the highlight should be (yes, it should probably be named ‘Spec size’ or something more sensible). A specular intensity value can then be set in order to control the intensity of the highlight. Finally, the highlight falloff is controlled by a ramp texture.

The specular light is calculated with respect to the light source and the view direction (like all specular highlights). However, I think the setup described above allowed for it to fit better with the “toony” diffuse light compared to the more traditional Blinn-Phong specular setup.

Rimlight

The rimlight can also be toggled with the “Enabled” checkbox. This is really nothing special, just a standard rim light. I do think it complemented the rest of the light model quite well though.

Shadows

The materials will of course have darker areas due to the diffuse light calculations. The ‘Receive Shadows’ checkbox will also allow it to be shadows by other objects (that are set to case shadows). However, the standard Unity shadows tend to have quite smooth edges, which doesn’t really fit with the rest of the sharp/cellular light falloff. I therefore added a ramp texture for the received shadows as well. It turned out I couldn’t use the diffuse ramp (haven’t really figured out why), so there is a separate texture for the shadow ramp.

Here is the final source code!

--

--