Shadow attenuation problems with "Transparent" queue

I’m trying to get shadows to work properly when cast onto an alpha blended material, but am running into trouble. My shader is below:

// Transparent diffuse alpha shader that supports shadow catching
// modified from: http://klakos.com/en/fully-shadowed-transparent-shader-for-unity-shadows-receiving-support-from-spotpoint-and-directional-lights/
// note that the original uses the "AlphaTest" queue whereas this one uses the "Transparent" queue to allow objects to be sorted properly, however this somehow prevents shadow attenuation from working properly

Shader "Transparent/ShadowCatcher/Diffuse" {

	Properties {
		_MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
	} 
	
	SubShader {
		Tags {
			"Queue"="Transparent" 
			"IgnoreProjector"="True" 
			"RenderType"="Transparent"
		}
		LOD 300

		// Main Surface Pass (Handles Spot/Point lights)
		// Simply diffuse with transparency
		CGPROGRAM
			#pragma surface surf Lambert nolightmap noambient vertex:vert fullforwardshadows alpha
			
			sampler2D _MainTex;
			
			struct v2f { 
				V2F_SHADOW_CASTER; 
				float2 uv : TEXCOORD1;
			};
		
			struct Input {
				float2 uv_MainTex;
				float4 color : COLOR; // vertex color
			};
		
			v2f vert (inout appdata_full v) {
				v2f o;
				return o;
			}
		
			void surf (Input IN, inout SurfaceOutput o) {
				fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
				o.Albedo = tex.rgb;
				o.Alpha = tex.a * IN.color.a; // texture and vertex alpha
			}
		ENDCG
	
		// Shadow Pass: Adding the shadows (from Directional Light)
		// by blending the light/shadow attenuation
		// Blended alpha shaders always use Forward mode
		Pass {
			Blend SrcAlpha OneMinusSrcAlpha
			Name "ShadowPass"
			Tags {"LightMode" = "ForwardBase"}
			
			CGPROGRAM
			#pragma exclude_renderers xbox360
			#pragma debug
			#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 { 
				float2 uv_MainTex : TEXCOORD1;
				float4 pos : SV_POSITION;
				LIGHTING_COORDS(3,4)
				float3 lightDir;
				float4 color : COLOR; // vertex color
			};
 
			float4 _MainTex_ST;
			sampler2D _MainTex;
 
			v2f vert (appdata_full v) {
				v2f o;
				o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
				o.lightDir = ObjSpaceLightDir( v.vertex );
				o.color = v.color; // copy vtx color to v2f
				TRANSFER_VERTEX_TO_FRAGMENT(o);
				return o;
			}

			float4 frag (v2f i) : COLOR {
				float atten = LIGHT_ATTENUATION(i);
				
				half4 c;
				c.rgb = 0;
				c.a = (1-atten) * (tex2D(_MainTex, i.uv_MainTex).a) * i.color.a;  // apply texture alpha and vertex alpha to allow for transparent areas in the shadow
				
				return c;
			}
			ENDCG
		}		
	}
	FallBack "Transparent/Cutout/Diffuse"
}

With this shader, I get no shadows whatsoever on the object. Based on my testing, the shadow pass IS blending with the surface shader correctly, but for some reason LIGHT_ATTENUATION(i) never returns any shadow attenuation.
If I change the subshader’s queue from “Queue”=“Transparent” to “Queue”=“AlphaTest”, suddenly shadows work, but this causes several other problems including depth fighting. (Using the AlphaTest queue seems to mean no depth sorting of the objects so you get all kind of depth fighting with other semi-transparent objects.) So I don’t think setting the Queue to AlphaTest is the correct course of action. (Edit: “AlphaTest” doesn’t even seem to be a standard Queue, and it seems it makes no difference whether the queue is set to “AlphaTest” or nothing at all.)

What I don’t understand is why there is no shadow attenuation data when the Queue is set to Transparent. Does Unity just toss out the shadow atten calculation because they don’t expect shadows to be supported on transparent shaders?

The reason it s not working is that transparent objects do not support shadows at all, as they don’t write to the depth buffer, which is necessary for shadows. However there are two shaders over at unifycommunity to support casting/receviing of shadows. http://unifycommunity.com/wiki/index.php?title=TransparentShadowCaster
There’s also a thread regarding possible issues using these shaders somehwere here in the shaderlab section (Sorry don’t have a link for that one, but the search might help).
The queue doesn’t work because it only defines when the object is drawn, not how. If i’m not mistaken the order is: Opaque, AlphaTest, Transparent, Overlay. I’m not quite sure if just changing the rendertype as well would fix this, but i’d think so.

Ahh, I see. That makes sense.

Actually that’s the exact same shader I got from another source which I listed in my first post. The only real difference is they used the AlphaTest render queue instead of Transparent, which does work but causes other problems as I mentioned.

Thanks for the explanation. I guess I won’t bang my head on the wall over this anymore and just do some design changes.

if you want use shadows here is the example, if you need on transparent you create a diferente pass with blend modes, in that way, you have the primary result and after a composite shadows.

Shader “Custom/shadows” {
Properties
{

}
SubShader
{
Tags {“Queue” = “Geometry” “RenderType” = “Opaque”}
pass{

Tags { “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 a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 texcoord: TEXCOORD0;
};

struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
LIGHTING_COORDS(2,3)

};

v2f vert (a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
o.normal = v.normal;
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}

float4 frag (v2f i) : COLOR
{
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
float atten = LIGHT_ATTENUATION(i) ;
float3 lambert = float(max(0.0,dot(i.normal,lightDirection)));;
return float4(lambert *atten,1);
}

ENDCG
}
}
FallBack “Diffuse”
}