# 3D Game Shaders For Beginners

Cel shading is a technique to make 3D objects look 2D or flat. In 2D, you can make an object look 3D by applying a smooth gradient. However, with cel shading, you're breaking up the gradients into abrupt transitions. Typically there is only one transition where the shading goes from fully lit to fully shadowed. When combined with outlining, cel shading can really sell the 2D cartoon look.

## Diffuse

``````    // ...

float diffuseIntensity = max(dot(normal, unitLightDirection), 0.0);
diffuseIntensity = step(0.1, diffuseIntensity);

// ...``````

Revisiting the lighting model, modify the `diffuseIntensity` such that it is either zero or one.

The `step` function returns zero if the input is less than the edge and one otherwise.

``````  // ...

if      (diffuseIntensity >= 0.8) { diffuseIntensity = 1.0; }
else if (diffuseIntensity >= 0.6) { diffuseIntensity = 0.6; }
else if (diffuseIntensity >= 0.3) { diffuseIntensity = 0.3; }
else                              { diffuseIntensity = 0.0; }

// ...``````

If you would like to have a few steps or transitions, you can perform something like the above.

``````  // ...

diffuseIntensity = texture(steps, vec2(diffuseIntensity, 0.0)).r;

// ...``````

Another approach is to put your step values into a texture with the transitions going from darker to lighter. Using the `diffuseIntensity` as a U coordinate, it will automatically transform itself.

## Specular

``````
// ...

float specularIntensity = clamp(dot(normal, halfwayDirection), 0.0, 1.0);
specularIntensity = step(0.98, specularIntensity);

// ...``````

Using the `step` function again, set the `specularIntensity` to be either zero or one. You can also use one of the other approaches described up above for the specular highlight as well. After you've altered the `specularIntensity`, the rest of the lighting calculations are the same.

### Source

(C) 2020 David Lettier
lettier.com