in this devlog we are going to discover
the ideas and process behind the cartoon
look
used in the first unity open project
open projects are small open source
games where the community of creators
is free to collaborate and contribute
actively to the entire game development
journey
you can have an impact in your area of
expertise try out new skills
or sit back and learn for this first
project
we chose a classic game genre the action
adventure
you can find a link to the github
project and all the relevant links to
learn more and get involved
in the video description we are
developing this game with unity 2019.4
lts
which is going to guarantee the best
stability as we tackle this process
but since we wanted to make the contents
of this video available to you in the
latest unity version
we upgraded the toon shader to work on
unity 20 20.2
the latest version available at the time
that we're recording this devlog you can
find this 2020.2 version of the tune
shader on a git branch of the original
repository
called devlog 1 toon shading
in this branch you'll find the
stripped-down version of the project
that you see in this video as soon as we
approved the art concepts
it was clear which unity scriptable
render pipeline best suited our needs
the graphic style was not realistic and
didn't require high fidelity visuals
what we needed was a clean simple and
stylized graphic style
which we decided to pursue with the
universal render pipeline
with this pipeline we could achieve a
cartoon style and keep the unity project
performant and able to run on a wide
range of hardware
we chose to build our shader using
shader graph for two main reasons
the first is that we wanted to keep
everything inside the project as
accessible
and understandable as possible for
everyone
the second is that by using shader graph
once we had achieved the look we wanted
we could easily expand the base shader
with extra effects
such as a wind effect using vertex
displacement a dissolve effect using
transparency and so on
toon shading also known as cell shading
is a rendering style characterized by a
non-photorealistic
illumination model the look is achieved
by representing shadows and highlights
as blocks of uniform color instead of
the typical shading gradients
in addition to the lighting
customization we chose to add an extra
shading pass
to create a black outline this outline
brings out the model's details
making it look like a moving comic book
or hand-drawn animation
this is our toon shader in action
we use the outline only on the
characters to make them stand out from
the environment
as you can see the 3d model came out
quite similar to the original concept
art drawing
to achieve the final results we knew we
wanted to include all of the aspects of
lighting
and we wanted them to be controllable
from inside shader graph
during this phase we didn't concentrate
on the cartoon shading effect
instead we wanted to focus on making
sure the shader provided support for the
following
a custom lighting model with lights
shadows and specular contribution
shadow cascades bait global illumination
for static objects
ambient light additional lights and
shadows
and light probes the starting point was
to add support for the main light
by default the main light in urp is the
strongest directional light present in a
scene
through a custom function node and
shader graph we were able to collect all
the lighting data from this light
the code contained in this node calls a
function that is already present in urp
called get main light which gives us
access to relevant data like direction
color and the shadow map which we
exposed here as shadow attenuation
then we use the dot product between the
normal vector of the geometry surface
and the light direction to set up our
custom lighting model
we clamp the result between zero and 1
and multiplied it by the shadow
attenuation value
using this value and the light color we
obtained the basic diffuse lighting
besides taking input from the main light
we wanted to make sure our shader could
accept lighting from all the
other lights present in the scene like
before
we used a custom function thanks to the
built-in function
get additional lights count we were able
to loop through all the other lights
available
and use the get additional light to
collect each light's data
here's when things start to get
interesting
if you look closely at the shader you'll
notice we also use the main light shadow
attenuation
when the shader is used for static
geometry this allows us to manipulate
real-time shadows on big geometry
basically recreating a technique that in
unity is called
mixed lighting mode this real-time
shadow is multiplied for the output of
the baked gi node
obtaining the final shadow contribution
now our tune characters can cast a black
shadow on our toon big scenery
just like in the concept art the baked
gi node
also allows the shader to support light
probes in the case of dynamic geometry
to test the shader's functionality we
created a scene with
all of the possible lighting situations
we added a directional light
real time point lights mixed point
lights and both static
and non-static spheres casting real time
and big shadows
on each other with this shader as a
starting point
we were ready to create our tuned shader
effect
since all the lighting features of the
shader were logically divided
we were able to introduce extra steps
between them to manipulate their values
and create the look we wanted the most
traditional characteristic of toon
shading
is that smooth color transitions are
converted to hard color bands
using a technique known as ramp shading
to achieve this
we added some sample gradient nodes
converting all of the light's
contributions
to a new color defined by a custom color
ramp
the idea is to confine the gradient
values of light hitting a surface
to a fixed smaller number of colors
in this way we achieve clear divisions
between lit
and shadowed areas by changing the ramp
colors
we will be able to obtain different
styles
to create the outline effect we needed
access to the normals and the depth
information
obtained from the camera's buffers we
needed a texture that combines both of
them
this texture has only recently been
introduced to urp
to enable screen space ambient occlusion
but
it is not available in the version of
your peak compatible with 19.4
luckily urp is a scriptable render
pipeline and can be modified to our
needs
in fact we adapted this solution from a
great example
available online by technical artist
alexander amayi
in order to generate the normals and
depth texture we created a custom
scriptable render feature
and then we simply added it to the
renderer asset
with a new texture available using a
custom function node again
we were able to sample it and collect
normals and depth information
using both of these values we draw the
outline
we can now modify the thickness of the
outline and the depth and normal
sensitivity per material
which allows us to customize how and
where the outline is drawn on different
geometry
to better match their shape
as the last step we brought the outline
logic into the tune shader
we multiply the outline value to the
color of the toon shading model
to get the final contribution and
achieve our result
as we mentioned this shader is being
made as part of the first
open project as we develop the project
we will keep adding to it and modifying
it to the game's changing needs
now that we've seen behind the scenes of
how we created it let's talk about
what's next in this ongoing process
and how we are tackling the current
challenges
one of the improvements we're working on
is to get rid of the shadow flickering
that happens when objects move
this issue doesn't affect self-shadowing
but only shadows cast from
other objects and is a direct
consequence of the hard transition that
we apply to the shadow map when we
approximate its grayscale values to just
black or white
increasing the shadow map's resolution
decreases the flickering
but it's not the ideal solution a quick
and easy solution to make it less
noticeable
is to render shadows with a tune ramp
rather than a hard step
this gives a buffer zone in the ramp
where the original light values can move
from black to white in a fluid movement
rather than jumping between the two
final values
another feature we might implement is a
tinting system that handles the exposed
tune shader color properties
and automatically swaps between
different color palettes based on the
context
for example tinting all the objects that
use the shader with a ramp of blue
colors when it's night
or using a ramp in the hues of orange
and purple to simulate a sunset
by tinting the colors on the dark side
of the ramp we can effectively tint the
shadows to any color we like
and for the outline specifically we want
to address the jagged aliasing
which is somehow visible when the game
is played at low resolutions
you're free to download use an adapted
tune shader in your projects
we hope that after watching this video
you will know where to intervene
and how also we'd like to invite you to
participate in the development of this
open project
and of the toon shader as we improve the
look of the game by solving the
challenges we just mentioned
keep yourself updated on the first open
project by following the roadmap
daily changes in the github repository
and the bi-weekly live streams
the tune shader may change during
development but remember that you can
always find this 2020.2 version
in a branch in the repository called
devlog 1 toon shading
we can't wait to see your contributions
thanks for watching
you