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?