How do I sample a shadowmap in a custom shader?

Hi guys,

I just signed up with Unity 3 Pro and am writing custom shaders for my game.

Unity shadows work for stock shaders: you just have to set all shadow casters and receivers in your scene and shadows magically work. But how about custom shaders? I would like to tap the shadow map myself to apply shadows to receivers, does anyone know how to do this? I tried sampling _ShadowMapTexture but this texture is always white.

For the sake of anyone else who is trying to write a fragment shader that receives shadows, I figured it out.

You must do these things:

  1. #include “AutoLight.cginc”’
  2. #include “Lighting.cginc”’
  3. Add "Tags {“LightMode” = “ForwardBase”}
  4. #pragma multi_compile_fwdbase’
  5. Add the Unity macros to your VSOut struct, VS and PS: LIGHTING_COORDS, TRANSFER_VERTEX_TO_FRAGMENT, LIGHT_ATTENUATION.

None of this is documented in the Unity manual.

To access the primary directional light color, unity_LightColor[0] works as long as you don’t add “Tags {“LightMode” = “ForwardBase”}”. If you do add that line, then it doesn’t work: use _LightColor0.rgb instead. Why? Who knows… probably makes sense to someone with access to the Unity source code. Which means no one.

Good luck!

-Peter

Shader "Custom/PeterShader2" {
Properties
{
	_MainTex ("Base (RGB)", 2D) = "white" {}
}

CGINCLUDE

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

uniform sampler2D _MainTex;

ENDCG

SubShader
{
	Tags { "RenderType"="Opaque" }
	LOD 200

	Pass
	{
		Lighting On

		Tags {"LightMode" = "ForwardBase"}

		CGPROGRAM

		#pragma vertex vert
		#pragma fragment frag
		#pragma multi_compile_fwdbase

		struct VSOut
		{
			float4 pos		: SV_POSITION;
			float2 uv		: TEXCOORD1;
			LIGHTING_COORDS(3,4)
		};

		VSOut vert(appdata_tan v)
		{
			VSOut o;
			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
			o.uv = v.texcoord.xy;

			TRANSFER_VERTEX_TO_FRAGMENT(o);

			return o;
		}

		float4 frag(VSOut i) : COLOR
		{
			float3 lightColor = _LightColor0.rgb;
			float3 lightDir = _WorldSpaceLightPos0;
			float4 colorTex = tex2D(_MainTex, i.uv.xy * float2(25.0f));
			float  atten = LIGHT_ATTENUATION(i);
			float3 N = float3(0.0f, 1.0f, 0.0f);
			float  NL = saturate(dot(N, lightDir));

			float3 color = colorTex.rgb * lightColor * NL * atten;
			return float4(color, colorTex.a);
		}

		ENDCG
	}
} 
FallBack "Diffuse"
}

MAKE NOTE that you can’t do this if Tags {“Queue”=“Transparent”} !

You can, if you add

#pragma multi_compile_fwdadd_fullshadows

- equally undocumented :slight_smile:

How do i detect if shadows are activated or compatible with current platform ?
I would like to use another sub-shader if it’s not the case. And can’t find a right way to do that.