An advanced toon shader in Godot

The built-in toon shader in Godot isn’t bad. It’s integrated, quick to set up, and built into the standard material. You can set the diffuse and specular to Toon, and change the Roughness.

But it doesn’t give the user much control. For example, you can’t independently control how crisp the light transitions into dark without changing the specular highlight. You can’t change the shadow color from black without introducing a secondary light, or control the light and shadow color on a per-object basis. You also can’t cast shadows on other objects without artifacts.

This advanced series will introduce a fully-featured toon shader that provides as much control as possible.

Credit where credit is due

A Blender shader developed by Lightning Boy Studios inspired large amounts of the shader code. If you want to recreate a version of this shader for use in Blender, you can follow the series by David Forest.

But the detail is in the pudding, and implementing it in Godot needs work and attention.

Deferred light rendering

The shader should be able to function with minimal chatter using shader parameters or scripts. But we need to get the light direction, position, and shape information. To avoid constantly telling it where the lights are using uniforms, we use Godot’s renderer to do the work for us.

We use deferred rendering: render all the light information onto textures. We then sample the pixels that line up with the 3D model and extract the light information.

Lighting

We set up a three-light model:

Synchronizing Viewports

Like the post-processing we did in earlier lessons, we have to keep objects in sync using RemoteTransform nodes and transparent ViewportContainers. With animations, this can also entail connecting animation players together with signals.

There’s extra labor involved as a result, but the next tutorial covers how to write a plugin to automate these tasks and get around the pitfalls of deferred rendering.