Professional Documents
Culture Documents
Introduction
Introduction 1
Getting Started 2 In this tutorial we will create a Unity3d
Surface shader which tries to achieve a
Implementing the lightingmodell
cartoony look beyond simply using a ramp
How lighting works 4 texture in the lighting function.
Implementation of our own Lighting Model 6
Getting the UV to the Lightingfunction 9 Instead I will try to create the look by
Finally Shading 10 determing the shading of the area
Some improvements to the lighting 12 between bright and dark areas with a
Finalizing the Lighting 13 greyscale mask. Thats what the main part
of this tutorial will be about. Later on we
The rim-lighting will add a rim-effect to further improve the
visual appeal. I will also try to explain the
Explanation 15 concepts behind the things we will be
Implementing 16 doing.
Sources 17
By calculating the dot product of two vectors we get the angle between two vectors as a
scalar between 0 and 1. While dot(v1, v2) returns 1 when both vectors are facing towards
each other.
Half4 means that this function will return a four-component vector (which will be used as half4 LightingCartoon(SurfaceOutput s, half3 dir, half attend){
color (Red,Green,Blue,Alpha)
}
When naming the function LightingCartoon we tell Unity that this function may be used
to compute lighting void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
SurfaceOutput provides all the data previously calculated in the surf function o.Albedo = c.rgb;
o.Alpha = c.a;
Dir is the light direction }
ENDCG
}
FallBack "Diffuse"
}
Actually return a color, first we declar it.Then the Albedo (diffuse) Color
from the surface shader gets multiplied with our light-angle. And finally we
let the Lightcolor have a shot to modify or final color. _LightColor0 is a
global value, describing the currently rendered lightcolor
Also add this line to the surf function this will write the UV values to our struct so
we can access is it in the lighting.
step 5 Getting the UV to the Lightingfunction
We do not have access to the uv-coordinates of the current rendered surface piece in o.UV = IN.uv_MainTex;
the lighting function. We will code our own struct which gets passed on through all the
functions and use this one instead of the SurfaceOutput struct. Lets declare the
SurfaceOutputCustom struct right after the Input-struct declaration.
Add this line to the LightingCartoon funcion, right after the NdotL declaration.
We will use the treshold to determine which color for the light based shading we will use.
half3 ShadowColor = NdotL < _Threshold1 ? _DarkColor : NdotL < _Threshold2 ?
lerp(_DarkColor, _BrightColor, tex2D(_TransitionTexture, s.UV)) : _BrightColor;
and multiply our previously calculated ShadowColor to the output color by changing it to this:
In code it looks like this (Ive left out the texturing for _BrightColor and _DarkColor for
now)
ShadowColor = NdotL < _Threshold1 ? _DarkColor : NdotL < _Threshold2 ? lerp(_DarkColor,
_BrightColor, tex2D(_TransitionTexture, s.UV)) : _BrightColor; Lighting Model - Cartoon Shader Tutorial 10
Shader "Custom/CartoonShader" {
Step 6 |CODE Lets wrap it. Properties { c.a = s.Alpha;
_MainTex ("Base (RGB)", 2D) = "white" {} return c;
_BrightColor("Bright Color", Color) = (1,0,0)
The code should look like this at the moment. _Threshold1("Threshold Bright to Dark", range(0,1)) = 0.2 }
_DarkColor("Dark Color", Color) = (0,1,0)
_Threshold2("Threshold Middle to Dark", range(0,1)) = 0.9 void surf (Input IN, inout SurfaceOutputCustom o) {
_TransitionTexture("Transition Texture", 2D) = "white" {} half4 c = tex2D (_MainTex, IN.uv_MainTex);
Assign tex1 to the transition texture slot in the material which should } o.UV = IN.uv_MainTex;
produce something like this: SubShader {
o.Albedo = c;
o.Alpha = c.a;
Tags { "RenderType"="Opaque" } }
LOD 200 ENDCG
}
CGPROGRAM FallBack "Diffuse"
#pragma surface surf Cartoon }
sampler2D _MainTex;
sampler2D _TransitionTexture;
half4 _BrightColor;
half4 _DarkColor;
half _Threshold1;
half _Threshold2;
struct Input {
float2 uv_MainTex;
};
struct SurfaceOutputCustom{
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
fixed viewFallof;
half2 UV;
};
dir = normalize(dir);
half NdotL = saturate( dot (s.Normal, dir));
half3 ShadowColor = NdotL < _Threshold1 ? _DarkColor : NdotL <
_Threshold2 ? lerp(_DarkColor, _BrightColor, tex2D(_TransitionTexture, s.UV)) :
_BrightColor;
half4 c;
c.rgb = ((NdotL * 0.4f)+0.6f) * s.Albedo * _LightColor0 * ShadowColor;
And the shader variable.. Just after half Treshhold1 Whenever we look up the _BrightColor or _DarkColor. We will multiply it
with a value from its texture. We Also want to set the intensity of the
half _TransitionTextureSize;
_BrightTexture. We need to change a lot of stuff in our LightingCartoon
function. Between the NdotL and _Shadowcolor declaration!
Now we will use this value to scale the transition texture. By changing the texture ADD
half4 darkColor = _DarkColor * tex2D(_DarkTexture, s.UV * _DarkTextureSize);
lookup in our ternary expresion half4 brightColor = _BrightColor * ( tex2D(_BrightTexture, s.UV * _BrightTextureSize) * _BrightTextureIntensity +
half3 ShadowColor = NdotL < _Threshold1 ? _DarkColor : NdotL < _Threshold2 ? (1-_BrightTextureIntensity));
lerp(_DarkColor, _BrightColor, tex2D(_TransitionTexture, s.UV *_TransitionTextureSize)) :
_BrightColor; With these lines we declare a new Color-Vector and multiply the Colors from the properties with the values from the
texture at that spot. While the darkColor is a simple multiplication. We craft in the _BrightTextureIntensity as a sort of
Now we will use this value to scale the transition texture. By changing the texture weight for the TextureValue of the brightColor.
lookup in our ternary expression. Now we only need to add the new colors to the ternary expression.
half3 ShadowColor = NdotL < _Threshold1 ? darkColor : NdotL < _Threshold2 ? lerp(darkColor,
brightColor, tex2D(_TransitionTexture, s.UV * _TransitionTextureSize)) : brightColor;
Step 7.1 Adding Textures
To have more artistic control over the shading to make the colors look painted for
example, we are going to multiply the shades with a texture. Again, first the
properties. Add those:
BrightColor:
(255,215,178)
BrightTexture:
Pencil_stroke_02
DarkColor::
(99,79,66)
DarkTexture:
Pencil_stroke_01
TransitionTexture:
Pencil_strokes_03
DOWNLOADS
Tutorial Package the stuff you need to start with this tuorial
https://dl.dropboxusercontent.com/u/28326381/shader%20download%20package.unitypackage
The maker of the awesome model were using through the tutorial:
http://www.parkparkin.com/