I started working on a game that will have similar graphics to Wind Waker. I’ve googled quite a bit and it seems many developers are aiming for a similar style. Strangely enough I wasn’t able to find a solution for my issue. Due to having $0 budget, I’m forced to develop my own shaders. So I’ve been fully dedicated to learning CG lately. I’ve managed to write a simple Toon fragment shader that’s nearly identical to the Unity “Toon Lit” shader you can download from their archive page. I’ll be using Unity “Toon Lit” shader in this example to make things easier.
I’m trying to create a fragment shader that’s able to both, receive shadows as well as cast them on the floor and surrounding objects. Using the Toon Lit shader, I can receive beautiful Toon shadows with a custom grayscale ramp, however there are no shadows being cast on the floor. I’ve been researching a lot and so far the only way I’ve managed to cast shadows was to add a fallback shader which in this case is the Unity Diffuse shader. The problem with this is that Diffuse shadows are more aimed towards a realistic look which is the opposite of what I want to achieve. What ends up happening is the Diffuse shadows are cast on top of the Toon shader, creating double layered shadows (shadow on shadow). I’d like for the shadows to fully blend together with the Toon shader so it looks like it’s just one shadow and also have shadows cast on the floor. Additionally, I’d like to have control of the sharpness of the shadows that are cast on the floor and surrounding objects.
This may be a bit confusing so I put together an image to better visualize what I’d like to achieve.
I learn best by example so I can examine the code. I would really appreciate if someone would give me an example and maybe explain a little bit how it works.
I’ve copy pasted the Toon Lit shader code here so you can take a look at it. I undid most of my changes I had there for testing. It should be near to default except for the rendertype which I believe used to be set to “Opaque”. The fallback shader is commented out since I don’t want to use it due to unwanted results.
Shader "Toon/Lit" {
Properties {
_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_Ramp ("Toon Ramp (RGB)", 2D) = "gray" {}
}
SubShader {
Tags { "RenderType"="TransparentCutout" }
LOD 200
CGPROGRAM
#pragma surface surf ToonRamp fullForwardShadows
sampler2D _Ramp;
// custom lighting function that uses a texture ramp based
// on angle between light direction and normal
#pragma lighting ToonRamp
inline half4 LightingToonRamp (SurfaceOutput s, half3 lightDir, half atten)
{
#ifndef USING_DIRECTIONAL_LIGHT
lightDir = normalize(lightDir);
#endif
half d = dot (s.Normal, lightDir)*0.5 + 0.5;
half3 ramp = tex2D (_Ramp, float2(d,d)).rgb;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 1);
c.a = 0;
return c;
}
sampler2D _MainTex;
float4 _Color;
struct Input {
float2 uv_MainTex : TEXCOORD0;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
//Fallback "Diffuse"
}
EDIT: After posting, I realized the Toon Lit is a surface shader. I just wanted to clarify that I’m interested in writing this using fragment shaders. Although I wouldn’t mind a temporary solution using a surface shader.


