Toon Shader with shadows

Hi devs!!!

I have a shader that is the combination of two shaders. The first one make the material to a toon material and the second one allow that the material can draw shadows when you use a point light for example.

In addition, the first one allows tint the material with the light color.

The shader works perfectly: you can obtain a toon material that can draw shadows…but the problem is that the feature of tint the material is lost…

I’m not sure how to fix that…

hader "Unnamed Shaders/Toony Shadows"
{
    Properties
    {
        _Color ("Main Color", Color) = (1,1,1,1)
   
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Ramp ("Toon Ramp (RGB)", 2D) = "gray" {}
        _Brightness ("Brightness 1 = neutral", Float) = 1.0   
       
        _SColor ("Shadow Color", Color) = (0.0,0.0,0.0,1)
        _LColor ("Highlight Color", Color) = (0.5,0.5,0.5,1)
    }

    SubShader
    {
        //Pass
        //{
            Tags { "RenderType"="Opaque" }
            LOD 200
       
            CGPROGRAM
            #pragma surface surf ToonRamp addshadow
       
            sampler2D _MainTex;
            sampler2D _Ramp;
            float4 _LColor;
            float4 _SColor;
            float4 _Color;
       
            // custom lighting function that uses a texture ramp based
            // on angle between light direction and normal
            #pragma lighting ToonRamp exclude_path:prepass
            inline half4 LightingToonRamp (SurfaceOutput s, half3 lightDir, half atten)
            {
                #ifndef USING_DIRECTIONAL_LIGHT
                lightDir = normalize(lightDir);
                #endif
           
                //Calculate N . L
                half d = (dot (s.Normal, lightDir)*0.5 + 0.5)*atten;
                //Basic toon shading
                half3 ramp = tex2D(_Ramp, float2(d,d)).rgb;
                //Gooch shading
                ramp = lerp(_SColor,_LColor,ramp);
           
                half4 c;
                c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
                c.a = 0;
           
                return c;
            }
       
            struct Input
            {
                float2 uv_MainTex : TEXCOORD0;
            };
       
            void surf (Input IN, inout SurfaceOutput o)
            {
                half4 c = tex2D(_MainTex, IN.uv_MainTex);
           
                o.Albedo = c.rgb * _Color.rgb;
                o.Alpha = c.a;
            }
            ENDCG
   
        //}

        Pass
        {
            Tags {"RenderType"="Opaque" "LightMode" = "ForwardBase"}
            CGPROGRAM
               
                #pragma vertex vert
                #pragma fragment frag
                #pragma multi_compile_fwdbase
                #pragma fragmentoption ARB_fog_exp2
                #pragma fragmentoption ARB_precision_hint_fastest
               
                #include "UnityCG.cginc"
                #include "AutoLight.cginc"
               
                struct v2f
                {
                    float4    pos            : SV_POSITION;
                    float2    uv            : TEXCOORD0;
                    LIGHTING_COORDS(1,2)
                };

                float4 _MainTex_ST;

                v2f vert (appdata_tan v)
                {
                    v2f o;
                   
                    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
                    TRANSFER_VERTEX_TO_FRAGMENT(o);
                    return o;
                }

                sampler2D _MainTex;
                fixed _Brightness;

                fixed4 frag(v2f i) : COLOR
                {
                    fixed atten = LIGHT_ATTENUATION(i) * _Brightness;    // Light attenuation + shadows.
                    //fixed atten = SHADOW_ATTENUATION(i); // Shadows ONLY.
                    return tex2D(_MainTex, i.uv) * atten; //_Brightness;
                }

            ENDCG
        }

        Pass
        {
            Tags {"RenderType"="Opaque" "LightMode" = "ForwardAdd"}
            Blend One One
            CGPROGRAM
               
                #pragma vertex vert
                #pragma fragment frag
                #pragma multi_compile_fwdadd_fullshadows
                #pragma fragmentoption ARB_fog_exp2
                #pragma fragmentoption ARB_precision_hint_fastest
               
                #include "UnityCG.cginc"
                #include "AutoLight.cginc"
               
                struct v2f
                {
                    float4    pos            : SV_POSITION;
                    float2    uv            : TEXCOORD0;
                    LIGHTING_COORDS(1,2)
                };

                float4 _MainTex_ST;

                v2f vert (appdata_tan v)
                {
                    v2f o;
                   
                    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex).xy;
                    TRANSFER_VERTEX_TO_FRAGMENT(o);
                    return o;
                }

                sampler2D _MainTex;
                fixed _Brightness;

                #if _COLOR_ON
                fixed4 _Color;
                #endif

                fixed4 frag(v2f i) : COLOR
                {
                    fixed atten = LIGHT_ATTENUATION(i) * _Brightness;    // Light attenuation + shadows.
                    //fixed atten = SHADOW_ATTENUATION(i)* _Brightness; // Shadows ONLY.
                    return tex2D(_MainTex, i.uv) * atten;//_Brightness;
                }
            ENDCG
        }
    }
   
    Fallback "Diffuse"
}

Some idea?

Thanks!!!

Any screens you can share of your results? :eyes: And also, wouldn’t you just leave the shadows up to the toon shader? the atten variable in your lighting function already has shadows!

Your first pass multiplies _Color in your Albedo output. However your later passes simply use MainTex and atten. You probably want to return tex2D(_Maintex,i.uv) * _Color * atten;

Probably should have said this before but… I could post a solution I made together with someone a wile ago, if I can find it. :smile: It had a four-bar toon ramp, and shadows working. :slight_smile:

Oh, and I am sure color tinting (I assume for the shadows?) would be easy to add. You know what though? I might as well write one from scratch for you, if you like! :slight_smile: