Issue receiving shadow on transparent object

Hi, I am trying to create 2D billboard grass that could be shaded. Texture contains pixels that are transparent and not. I want to shadow appear only on not transparent pixels but i get strange outcome. If I look on other objects they are also shaded:
7388951--902039--upload_2021-8-4_18-44-36.png
Looking at sky works well:
7388951--902045--upload_2021-8-4_18-46-19.png
Shader code:

Shader "PixelEngine/Grass"

{

    Properties

    {

        _MainTex("Texture", 2D) = "white" {}

        _Normal("Normal", Vector) = (0.0, 0.0, 0.0, 0.0)

        _Position("Normal", Vector) = (0.0, 0.0, 0.0, 0.0)

        _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)



        _SemiShadowThreshold("Semi-Shadow Threshold", Range(0.0, 1.0)) = 0.4

        _SemiShadowColor("Semi-Shadow Color", Color) = (0.5, 0.5, 0.5, 0.5)



        _ShadowThreshold("Shadow Threshold", Range(0.0, 1.0)) = 0.0

        _ShadowColor("Shadow Color", Color) = (0.0, 0.0, 0.0, 0.0)

    }

    SubShader

    {

        Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" "LightMode"="ForwardBase" }

        Blend SrcAlpha OneMinusSrcAlpha

        AlphaToMask On

        Pass

        {

            CGPROGRAM

            #pragma vertex vert

            #pragma fragment frag

            #pragma multi_compile_fwdbase

            #pragma multi_compile_instancing



            #include "UnityCG.cginc"

            #include "AutoLight.cginc"



            uniform fixed4 _LightColor0;



            uniform sampler2D _MainTex;

            uniform float4 _MainTex_ST;



            uniform fixed4 _Color;

            uniform fixed4 _ShadowColor;

            uniform fixed4 _SemiShadowColor;

            uniform fixed _ShadowThreshold;

            uniform fixed _SemiShadowThreshold;



            UNITY_INSTANCING_BUFFER_START(Props)

              

            UNITY_DEFINE_INSTANCED_PROP(float3, _Normal)

            UNITY_DEFINE_INSTANCED_PROP(float3, _Position)



            UNITY_INSTANCING_BUFFER_END(Props)



            struct vertexInput

            {

                float4 vertex : POSITION;

                float2 uv : TEXCOORD0;

                float3 normal : NORMAL;

                UNITY_VERTEX_INPUT_INSTANCE_ID

            };



            struct vertexOutput

            {

                float4 pos : SV_POSITION;

                float2 uv : TEXCOORD0;

                float3 worldPos : TEXCOORD1;

                float3 normal : TEXCOORD2;



                LIGHTING_COORDS(3, 4)

                UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.

            };



            vertexOutput vert(vertexInput v)

            {

                vertexOutput o;



                UNITY_SETUP_INSTANCE_ID(v);

                UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.



                o.pos = mul(UNITY_MATRIX_P,

                    mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))

                    + float4(v.vertex.x, v.vertex.y, 0.0, 0.0));

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                o.normal = normalize(UnityObjectToWorldNormal(UNITY_ACCESS_INSTANCED_PROP(Props, _Normal)));

                o.worldPos = mul(unity_ObjectToWorld, v.vertex);



                TRANSFER_VERTEX_TO_FRAGMENT(o);



                return o;

            }



            fixed4 frag (vertexOutput i) : SV_Target

            {

                UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.



                // Calculate light

                float attenuation = LIGHT_ATTENUATION(i);

                fixed3 lightDir;

                if(_WorldSpaceLightPos0.w == 0.0)

                {

                    lightDir = normalize(_WorldSpaceLightPos0.xyz);

                }

                else

                {

                    float3 objToLight = _WorldSpaceLightPos0.xyz - i.worldPos;

                    lightDir = normalize(objToLight);

                }



                // Calculate shadow

                fixed3 diffuse = saturate(dot(lightDir, i.normal)) * attenuation;



                // Color ramp

                fixed4 color;

                color = diffuse.r <= _SemiShadowThreshold ? _SemiShadowColor : _Color;

                color = diffuse.r <= _ShadowThreshold ? _ShadowColor : color;



                // Add light color

                color = color * _LightColor0;



                // Apply grass texture and light color

                color = fixed4(color.rgb, tex2D(_MainTex, i.uv).a);

                return color;

            }

            ENDCG

        }

    }

    Fallback "VertexLit"

}

Maybe someone will advise me how to do that better. I am trying to achive simillar results to that shown in this video (but shadow receiving got me):

You need a shadow caster pass for this shader that uses clip(color.a - 0.5). Unity’s directional shadows cast onto the camera depth texture, which is generated by rendering opaque objects with a shadow caster pass from the camera’s view.

1 Like

Hey bgolus what would you suggest to someone less experienced in code, working in shader graph and also experiencing no shadows on objects using alpha masks?

8407569--1110612--upload_2022-9-1_14-15-51.jpg

8407569--1110615--upload_2022-9-1_14-17-20.png