Toon Lighting
Toon shading replaces a smooth diffuse gradient with a small number of flat bands. One line does it:
How the banding works
diff starts as a smooth value from 0 to 1 (computed with dot(n, l)). To create toon bands:
diff * 4.0— scale from [0,1] to [0,4], so the range now has 4 segmentsfloor(...)— snap to the nearest integer (0, 1, 2, or 3), dropping everything else/ 3.0— scale back to [0,1] so colors stay in range
Result: a value that can only be 0, 0.33, 0.67, or 1.0 — four flat brightness bands.
Why divide by 3.0 instead of 4.0
Dividing by 4.0 would give values 0, 0.25, 0.5, 0.75. Dividing by 3.0 makes the top band reach 1.0 (full brightness), which produces a more punchy highlight. The number of bands is controlled by the 4.0 multiplier; the divisor determines the brightness of the top band.
Diffuse before and after
Without banding, baseCol * (0.12 + 0.88 * diff) is a smooth gradient from dim to bright. With banding, the sphere shows three or four distinct shading zones separated by hard edges — the classic cel-shaded look.
Try changing it
| Change | Effect |
|---|---|
4.0 → 2.0 and / 1.0 | Two bands: lit and unlit |
4.0 → 8.0 and / 7.0 | Eight bands, fine staircase shading |
floor → ceil | Bands shift — dark areas slightly lighter |
Add + smoothstep(0.49, 0.51, diff) * 0.05 after banding | Subtle soft edge at band boundaries |
Exercise
Add diff = floor(diff * 4.0) / 3.0; after the diffuse computation to quantize the smooth gradient into flat toon shading bands.
Answer Breakdown
Starting state: diff is a smooth 0–1 Lambert gradient — the sphere shades continuously from dark to light.
The fix: floor(diff * 4.0) / 3.0 quantizes the gradient into four discrete steps. The sphere now shows clear hard-edged bands instead of a smooth gradient, giving it a hand-drawn or cartoon appearance.
Try floor(diff * 3.0) / 2.0 for a simpler two-tone look with just a lit side and a shadow side.