Help with adding alpha cutout to toon shader.

so, I’ve recently gotten a project in university to make a game, in my group I’m the 3d artist, so im making all of the 3d models, textures, animations etc… but i’m also responsible in making the shader for the game, i followed a pretty nice tutorial to this point, but as someone who really doesn’t know what he’s doing i need some help in adding a alpha cut out to my shader, we have a lot of foliage and assets using alphas so any help is appreciated !

the tutorial I’m following : Unity Toon Shader Tutorial

I’m using unity version 2018.3.14f1

Shader "Test/Toon"
{
	Properties
	{
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Main Texture", 2D) = "white" {}
	
	[HDR]
	_AmbientColor("Ambient Color", Color) = (0.4,0.4,0.4,1)
		[HDR]
	_SpecularColor("Specular Color", Color) = (0.9,0.9,0.9,1)
		
		_Glossiness("Glossiness", Float) = 32
		[HDR]
	_RimColor("Rim Color", Color) = (1,1,1,1)
		_RimAmount("Rim Amount", Range(0, 1)) = 0.716
		
		_RimThreshold("Rim Threshold", Range(0, 1)) = 0.1
	}
		SubShader
	{
		Pass
	{
	
		Tags
	{
		"LightMode" = "ForwardBase"
		"PassFlags" = "OnlyDirectional"
	}

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
		
#pragma multi_compile_fwdbase

#include "UnityCG.cginc"

#include "Lighting.cginc"
#include "AutoLight.cginc"

		struct appdata
	{
		float4 vertex : POSITION;
		float4 uv : TEXCOORD0;
		float3 normal : NORMAL;
	};

	struct v2f
	{
		float4 pos : SV_POSITION;
		float3 worldNormal : NORMAL;
		float2 uv : TEXCOORD0;
		float3 viewDir : TEXCOORD1;
	
		SHADOW_COORDS(2)
	};

	sampler2D _MainTex;
	float4 _MainTex_ST;

	v2f vert(appdata v)
	{
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.worldNormal = UnityObjectToWorldNormal(v.normal);
		o.viewDir = WorldSpaceViewDir(v.vertex);
		o.uv = TRANSFORM_TEX(v.uv, _MainTex);

		TRANSFER_SHADOW(o)
			return o;
	}

	float4 _Color;

	float4 _AmbientColor;

	float4 _SpecularColor;
	float _Glossiness;

	float4 _RimColor;
	float _RimAmount;
	float _RimThreshold;

	float4 frag(v2f i) : SV_Target
	{
		float3 normal = normalize(i.worldNormal);
		float3 viewDir = normalize(i.viewDir);

		float NdotL = dot(_WorldSpaceLightPos0, normal);

		float shadow = SHADOW_ATTENUATION(i);
	
		float lightIntensity = smoothstep(0, 0.01, NdotL * shadow);
		
		float4 light = lightIntensity * _LightColor0;

		float3 halfVector = normalize(_WorldSpaceLightPos0 + viewDir);
		float NdotH = dot(normal, halfVector);
		
		float specularIntensity = pow(NdotH * lightIntensity, _Glossiness * _Glossiness);
		float specularIntensitySmooth = smoothstep(0.005, 0.01, specularIntensity);
		float4 specular = specularIntensitySmooth * _SpecularColor;


		float rimDot = 1 - dot(viewDir, normal);

		float rimIntensity = rimDot * pow(NdotL, _RimThreshold);
		rimIntensity = smoothstep(_RimAmount - 0.01, _RimAmount + 0.01, rimIntensity);
		float4 rim = rimIntensity * _RimColor;

		float4 sample = tex2D(_MainTex, i.uv);

		return (light + _AmbientColor + specular + rim) * _Color * sample;
	}
		ENDCG
	}


		UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
	}
}

Also how could i add double facing to this shader ? since most of these assets are 1 polygon only…

Thank you for the help in advance!

This question isn’t the most complicated to answer, but seeing as it has multiple parts at various places throughout the shader, I figured I would go through and add them for you. I’ve left comments wherever I’ve added/modified things that also explain what the changes do. The shadowcaster pass was the most complicated, but that’s simply because there’s no documentation, so you can’t really learn how they work without dissecting Unity’s internal shaders (I did that liberty for you a while ago, so I already knew how they worked).

Shader "Test/Toon"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Main Texture", 2D) = "white" {}
     
		[HDR]
		_AmbientColor("Ambient Color", Color) = (0.4,0.4,0.4,1)
        [HDR]
		_SpecularColor("Specular Color", Color) = (0.9,0.9,0.9,1)
         
        _Glossiness("Glossiness", Float) = 32
        [HDR]
		_RimColor("Rim Color", Color) = (1,1,1,1)
        _RimAmount("Rim Amount", Range(0, 1)) = 0.716
         
        _RimThreshold("Rim Threshold", Range(0, 1)) = 0.1

		//How far along we want to clip pixels
		_AlphaThreshold ("Alpha Cutoff", Range(0,1)) = 0.5
    }
	SubShader
    {
		Pass
		{
			Tags { "LightMode" = "ForwardBase" "PassFlags" = "OnlyDirectional" }

			//This makes the shader double sided, but we will need to make some 
			//vertex shader adjustments so that both sides look right
			Cull Off
 
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
         
			#pragma multi_compile_fwdbase
 
			#include "UnityCG.cginc"
 
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
 
			struct appdata
			{
				float4 vertex : POSITION;
				float4 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};
 
			struct v2f
			{
				float4 pos : SV_POSITION;
				float3 worldNormal : NORMAL;
				float2 uv : TEXCOORD0;
				float3 viewDir : TEXCOORD1;
     
				SHADOW_COORDS(2)
			};
 
			sampler2D _MainTex;
			float4 _MainTex_ST;
 
			v2f vert(appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.viewDir = WorldSpaceViewDir(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				
				//This makes sure that the normals are facing the right way on both sides of the object
				o.worldNormal *= lerp (1.0, -1.0, dot (o.viewDir, o.worldNormal) < 0.0);

				TRANSFER_SHADOW(o)
				return o;
			}
 
			float4 _Color;
 
			float4 _AmbientColor;
 
			float4 _SpecularColor;
			float _Glossiness;
 
			float4 _RimColor;
			float _RimAmount;
			float _RimThreshold;

			//Also declare down here
			half _AlphaThreshold;
 
			float4 frag(v2f i) : SV_Target
			{
				//Move the texture sample up here
				float4 sample = tex2D(_MainTex, i.uv);

				//Check if our alpha is lower than the threshold;
				//If it is, then discard this pixel and return early.
				if (sample.a < _AlphaThreshold)
				{
					discard;
					return 0;
				}

				float3 normal = normalize(i.worldNormal);
				float3 viewDir = normalize(i.viewDir);
 
				float NdotL = dot(_WorldSpaceLightPos0, normal);
 
				float shadow = SHADOW_ATTENUATION(i);
     
				float lightIntensity = smoothstep(0, 0.01, NdotL * shadow);
         
				float4 light = lightIntensity * _LightColor0;
 
				float3 halfVector = normalize(_WorldSpaceLightPos0 + viewDir);
				float NdotH = dot(normal, halfVector);
        
				float specularIntensity = pow(NdotH * lightIntensity, _Glossiness * _Glossiness);
				float specularIntensitySmooth = smoothstep(0.005, 0.01, specularIntensity);
				float4 specular = specularIntensitySmooth * _SpecularColor;
 
 
				float rimDot = 1 - dot(viewDir, normal);
 
				float rimIntensity = rimDot * pow(NdotL, _RimThreshold);
				rimIntensity = smoothstep(_RimAmount - 0.01, _RimAmount + 0.01, rimIntensity);
				float4 rim = rimIntensity * _RimColor;
 
				return (light + _AmbientColor + specular + rim) * _Color * sample;
			}
			ENDCG
		}

		//We will have to use our own shadowcaster pass now that we are discarding pixels
		//UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"

		//Don't worry too much about this pass; shadowcaster passes are completely undocumented in Unity, 
		//but it basically just renders the bare minimum so that the shadow functions can see the object as it is in the scene
		Pass
		{
			Name "ShadowCaster"
			Tags { "LightMode" = "ShadowCaster" }

			Cull Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 2.0
			#pragma multi_compile_shadowcaster
			#pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;

			half _AlphaThreshold;

			v2f vert (appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
				o.uv = (v.uv * _MainTex_ST.xy) + _MainTex_ST.zw;
				return o;
			}

			float4 frag (v2f i) : SV_Target
			{
				float a = tex2D (_MainTex, i.uv).a;
				if (a < _AlphaThreshold)
					discard;

				return 0;
			}
			ENDCG
		}
    }
}

Good luck with the project.