[SOLVED] Need help with Custom Toon Shader

Hello.
I’m struggling on making a Custom Shader.

Here is what I have right now.

And here is the shader code:

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// WATCH FULL EXPLANATION ON YOUTUBE-VIDEO: https://www.youtube.com/watch?v=3qBDTh9zWrQ
 
Shader "Custom / Cel Shading / Diffuse" {
   Properties {
    _Color ("Diffuse Material Color", Color) = (1,1,1,1)
    _UnlitColor ("Unlit Color", Color) = (0.5,0.5,0.5,1)
    _DiffuseThreshold ("Lighting Threshold", Range(-1.1,1)) = 0.1
    _SpecColor ("Specular Material Color", Color) = (1,1,1,1)
    _Shininess ("Shininess", Range(0.5,1)) = 1 
    _OutlineThickness ("Outline Thickness", Range(0,1)) = 0.1
    _MainTex ("Main Texture", 2D) = "AK47" {}
    _TextureColor ("Texture Color", Color) = (1,1,1,1)
       
    }
   
     SubShader {
     Pass {
    Tags{ "LightMode" = "ForwardBase" }
        // pass for ambient light and first light source
     
        CGPROGRAM
       
        #pragma vertex vert
        //tells the cg to use a vertex-shader called vert
        #pragma fragment frag
        //tells the cg to use a fragment-shader called frag
       
        //== User defined ==//
       
        //TOON SHADING UNIFORMS
        uniform float4 _Color;
        uniform float4 _UnlitColor;
        uniform float _DiffuseThreshold;
        uniform float4 _SpecColor;
        uniform float _Shininess;
        uniform float _OutlineThickness;
     
       
        //== UNITY defined ==//
        uniform float4 _LightColor0;
        uniform sampler2D _MainTex;
        uniform float4 _TextureColor;
        uniform float4 _MainTex_ST;        
       
        struct vertexInput {
           
        //TOON SHADING VAR
        float4 vertex : POSITION;
        float3 normal : NORMAL;
        float4 texcoord : TEXCOORD0;
             
        };
       
        struct vertexOutput {
           
            float4 pos : SV_POSITION;
            float3 normalDir : TEXCOORD1;
            float4 lightDir : TEXCOORD2;
            float3 viewDir : TEXCOORD3;
            float2 uv : TEXCOORD0;
        };
       
        vertexOutput vert(vertexInput input)
        {
            vertexOutput output;
           
            //normalDirection
            output.normalDir = normalize ( mul( float4( input.normal, 0.0 ), unity_WorldToObject).xyz );
           
            //World position
            float4 posWorld = mul(unity_ObjectToWorld, input.vertex);
           
            //view direction
            output.viewDir = normalize( _WorldSpaceCameraPos.xyz - posWorld.xyz ); //vector from object to the camera
           
            //light direction
            float3 fragmentToLightSource = ( _WorldSpaceCameraPos.xyz - posWorld.xyz);
            output.lightDir = float4(
                normalize( lerp(_WorldSpaceLightPos0.xyz , fragmentToLightSource, _WorldSpaceLightPos0.w) ),
                lerp(1.0 , 1.0/length(fragmentToLightSource), _WorldSpaceLightPos0.w)
            );
           
            //fragmentInput output;
            output.pos = UnityObjectToClipPos( input.vertex );  
           
            //UV-Map
            output.uv =input.texcoord;
           
            return output;
         
        }
       
        float4 frag(vertexOutput input) : COLOR
        {
 
    float nDotL = saturate(dot(input.normalDir, input.lightDir.xyz));
           
    //Diffuse threshold calculation
    float diffuseCutoff = saturate( ( max(_DiffuseThreshold, nDotL) - _DiffuseThreshold ) *1000 );
           
    //Specular threshold calculation
    float specularCutoff = saturate( max(_Shininess, dot(reflect(-input.lightDir.xyz, input.normalDir), input.viewDir))-_Shininess ) * 1000;
           
    //Calculate Outlines
    float outlineStrength = saturate( (dot(input.normalDir, input.viewDir ) - _OutlineThickness) * 1000 );
       
           
    float3 ambientLight = (1-diffuseCutoff) * _UnlitColor.xyz; //adds general ambient illumination
    float3 diffuseReflection = (1-specularCutoff) * _Color.xyz * diffuseCutoff;
    float3 specularReflection = _SpecColor.xyz * specularCutoff;
       
    float3 combinedLight = (ambientLight + diffuseReflection) * outlineStrength + specularReflection;    
    return float4(combinedLight, 1.0) + tex2D(_MainTex, input.uv); // DELETE LINE COMMENTS & ';' TO ENABLE TEXTURE
       
 
        }
       
        ENDCG
     
      }
 
   
   }
    Fallback "Diffuse"
}

The code was obtained from here:

I’m trying to get Zelda BOTW kind of shader and this result isn’t exactly as I expected.

Currently the “shadow” is the actual texture and the lighted parts are the textures with higher brightness.
What I need is simply the actual texture with shadow which is its darker counterpart.

I had tried the tutorial from here:

But it threw an error about it has to has 2 passes.

I tried googling but couldn’t find any answers.
I tried doing the coding myself but I’ve never touched custom shaders before and MonoBehaviour doesn’t pops available syntax for it like it does for C#.
I’d just buy it from asset store but I want to try it myself first.
I tried darkening the texture itself, but I felt like it was just a work around, not the right solution.

What I’m thinking is, I need to know how to code the shader so it multiplies the texture color with a color I can input so I can set how dark the shadow is.
Also the texture need to change color depending on light color.
And I’d be very grateful if you’d also tell me how to do cutout for the hair and remove backface culling.

Thank you.

In case someone stumble across this in the future, I’ve figured out the answer.

I used the answer from Bodhid found here:

but instead of 3, I used 2.

I also combined it Diffuse Wrap script found here:

Finally I added _ShadowThreshold to control the shadow area. Higher value equals less shadow.

For the Backface Culling, I simply duplicate the faces and flip the normals in Blender.
For the Cutout I made a separate shader with similar script with Alpha Cutoff added.

The following is the script without cutoff:

Shader "Custom/Custom Toon" {
	Properties {
            _MainTex ("Texture", 2D) = "white" {}
            _ShadowTreshold ("Shadow Treshold", Float) = 1
        }
        SubShader {
        Tags
        {
        "RenderType" = "Opaque"
        }
        CGPROGRAM
          #pragma surface surf WrapLambert

          float _ShadowTreshold;

          half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
              half NdotL = dot (s.Normal, lightDir);
              half diff = NdotL * 0.5 + 0.5;
              half4 c;
              c.rgb = s.Albedo * _LightColor0.rgb * (round(saturate (diff * (atten * _ShadowTreshold))*2)/2);
//		 	c.rgb = s.Albedo * _LightColor0.rgb * (diff.atten);
              c.a = s.Alpha;
              return c;
          }
  
        struct Input {
            float2 uv_MainTex;
        };
        
        sampler2D _MainTex;
        
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        ENDCG
        }
        Fallback "Diffuse"
    }

And this is with cutoff:

Shader "Custom/Custom Toon Cutout" {
	Properties {
            _MainTex ("Texture", 2D) = "white" {}
            _ShadowTreshold ("Shadow Treshold", Float) = 1
            _CutOff("Alpha Cutoff", Range(0,1)) = 0.5
        }
        SubShader {
        Tags
        {
        "RenderType" = "Opaque"
        }
        CGPROGRAM
          #pragma surface surf WrapLambert alphatest:_Cutoff addshadow

          float _ShadowTreshold;

          half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
              half NdotL = dot (s.Normal, lightDir);
              half diff = NdotL * 0.5 + 0.5;
              half4 c;
              c.rgb = s.Albedo * _LightColor0.rgb * (round(saturate (diff * (atten * _ShadowTreshold))*2)/2);
//		 	c.rgb = s.Albedo * _LightColor0.rgb * (diff.atten);
              c.a = s.Alpha;
              return c;
          }
  
        struct Input {
            float2 uv_MainTex;
        };
        
        sampler2D _MainTex;
        
        void surf (Input IN, inout SurfaceOutput o) {
        	fixed4 c =  tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
        }
        Fallback "Diffuse"
    }

Also, I almost forgot.
I changed the Ambient Setting in Lighting Tab to Color and put it around gray. Then changed the sun color to gray to balance it. This is to remove the black shadows that appear around the model. Or more like, changed the shadow’s color.