We've been experimenting with generating cel-shaded graphics to give some of our games a more cartoon-style feel to them. Cel-shading is a technique employed by cartoon animators to make a cartoon scene look 3D whilst restricting the number of colours in it. Back when colour was added to cartoons manually (it is now mostly a digital process), it was far easier to fill an area with a solid colour than a colour gradient, such as a lighter shade
of a colour going into a darker one. And it was easier to split colour boundaries with a black line, which gives cartoons their distinct outlines.
Why are we essentially reducing the quality of our graphics by going out of our way to change automatically generated smooth shading calculated by
applying 3D lights to a scene to restrict it to distinct bands of colour? Because it gives the scene a more cartoony feel and it looks rather
cool! Essentially there are two steps to cel-shading:
Firstly, lighting is applied to a 3D object, and the amount the light affects the object it split into four bands - for example:
- Band 1 (dark) - between 0% and 25% light.
- Band 2 (a bit lighter) - between 25% and 50% light.
- Band 3 (lighter still) - between 50% and 75% light.
- Band 4 (lightest) - between 75% and 100% light.
These bands are then filled with a solid colour that is the average of the intensity across each band. Taking this example of a 3D model of an apple:
||Lit with a 3D light
||Lighting split into 4 bands
Secondly, a black outline is added at any point where two different colours touch. This includes the edges of the image, but doesn't include the
boundaries between the colours bands:
||Black outline added
Anyone familiar with our games might recognise that particular apple from The Food Run
. All sprites in that game are
cel-shaded, but they are 2D sprites generated from 3D pre-rendered scenes. In other words, we made a 3D model of an apple, ran it through a program
to render a cel-shaded image, saved it as a 2D sprite them imported that sprite into the game. Simple enough for a basic 2D puzzler, but what
about a more complex 3D scene with real-time generation of cel-shaded models?
That's our current challenge. In theory it is simple enough to generate a 3D shader which performs a cel-shading algorithm. It can take an existing
3D model and details of a light source and generate the cel-shaded output image. But it requires checking the light intensity of every pixel once to
check which band of colour it belongs to, and twice to check if it should be part of a black outline. The black outline check potentially must
test neighbouring pixels too. With pixel operations in shaders being notoriously slow, this is a difficult operation to perform without the
framerate of the game being affected.
That said, we have succeeded to a certain extent with The Penguin Factory - a game we haven't released yet but may be familiar to any of you who have
followed us on Steam Greenlight in the past. Here is a cel-shaded scene from the game, rendered at full HD in real-time:
The bands of light are clearly visible, as are the black outlines. There's more to come from that game next year, but there's much cel-shader optimisation to be done first!