Ignore alpha when casting shadows from standard shader

See below for my current shader. I have a separate input for alpha as I’m generating the alpha programmatically and I have a static texture that tiles and is visible where the alpha doesn’t cut out the object. What I’d like though, is for the shadows cast by this shader to behave as if there were no cutout, i.e. the entire object casts a shadow, not just the part that is left by the cutout. If I remove addshadow from the #pragma surface line, I get the full shadow as desired, but then no shadows are displayed behind the parts of the object that are cutout. As far as I can tell I think this should be possible with multiple passes, but I can’t figure out how to combine a pass that just displays a shadow with the standard surface pass that show the cutout object.

Shader "Custom/StandardAlphaCutout" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        [NoScaleOffset] _MainTex ("Base (RGB)", 2D) = "white" {}

        [Normal] [NoScaleOffset] _Normal ("Normal (RGB)", 2D) = "bump" {}
        _NormalScale ("Normal scale", Vector) = (1,1,1,0)

        [NoScaleOffset] _MetallicGlossMap("Metallic (R) Smoothness (A)", 2D) = "white" {}
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _Glossiness ("Smoothness", Range(0,1)) = 0.5

        _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5
        [Toggle(InvertAlpha)] _InvertAlpha("Invert alpha map?", Int) = 0
        _AlphaTex ("Alpha Map (RGB)", 2D) = "white" {}
    }

    SubShader {

        Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" }
       
        Cull Off
       
        CGPROGRAM

        #pragma shader_feature METALLICGLOSSMAP

        #pragma shader_feature InvertAlpha

        // Physically based Standard lighting model
        #pragma surface surf Standard alphatest:_Cutoff addshadow

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
       
        sampler2D _MainTex;
        sampler2D _MetallicGlossMap;
        sampler2D _AlphaTex;
        sampler2D _Normal;
       
        struct Input {
            float2 uv_MainTex;
            float2 uv_AlphaTex;
            float2 uv_MetallicGlossMap;
            float2 uv_Normal;
            fixed facing : VFACE;
        };
       
        fixed4 _NormalScale;
        fixed _Glossiness;
        fixed _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D ( _MainTex, IN.uv_MainTex ) * _Color;           
            o.Albedo = c.rgb;

            fixed3 normal = UnpackNormal ( tex2D ( _Normal, IN.uv_Normal * _NormalScale.xy ) );
            normal.xy *= _NormalScale.z;
            o.Normal = normalize ( normal );

            // If we're rendering a back face, flip the normal.
            if (IN.facing < 0.5)
                o.Normal *= -1.0;
           
            #if InvertAlpha
            o.Alpha = 1 - tex2D ( _AlphaTex, IN.uv_AlphaTex ).a;
            #else
            o.Alpha = tex2D ( _AlphaTex, IN.uv_AlphaTex ).a;
            #endif


            #if METALLICGLOSSMAP
            fixed4 mg = tex2D ( _MetallicGlossMap, IN.uv_MetallicGlossMap );
            o.Metallic = mg.r;
            o.Smoothness = mg.a;
            #else
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            #endif

        }
        ENDCG

    }

    FallBack "Transparent/Cutout/Diffuse"
    CustomEditor "StandardAlphaCutoutGUI"
}

The same shadow caster shader pass is used for both the shadow casting (via shadow maps) and main directional light shadow receiving by way of the depth texture. You can add some code to your surface function to see if it’s being used as part of the shadow caster pass, then there are some semi-hacky methods for testing if the shadow caster pass is being used as part of the shadow map or the depth.

Try adding this to the end of your surf function.

#ifdef UNITY_PASS_SHADOWCASTER
if (unity_LightShadowBias.z != 0.0) // is shadow map
o.Alpha = 1.0;
#endif

Perfect. Thanks! Sorry, I didn’t see the linked thread in my research.