_Projector, Projector shader and CG

Trying to improve the visual quality of our projectors, I wanted to modify the shader we use for the projectors material.

This is what we and probably most people are using:

Shader "Projector/Projector Multiply"
{ 
Properties
{
    _Color ("Main Colour", Color) = (1,1,1,0)
    _ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
}

Subshader
{
    Tags { "RenderType"="Transparent"  "Queue"="Transparent+100"}
    Pass
    {
        ZWrite Off
        Offset -1, -1

        Fog { Mode Off }

        //AlphaTest Greater .1
        AlphaTest Less 1
        ColorMask RGB
        Blend One SrcAlpha

        SetTexture [_ShadowTex]
        {
            constantColor [_Color]
            combine texture * constant, One - texture
            Matrix [_Projector]
        }
    }
}
}

We slightly modified it so that it can take a color and removed the falloff texture, but that's pretty much what you'll find in the Projectors package BlobShadow prefab shader.

alt text

Since I want way better control about the way this is all rendered, and since like every sane person I hate fixed-functions shader programming, I wanted to move it to CG code. My puny and failed attempt at simply reproducing what the fixed function shader was doing looks like this:

Shader "Projector/Projector Multiply"
{ 
Properties
{
    _Color ("Main Colour", Color) = (1,1,1,0)
    _ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
}

Subshader
{
    Tags { "RenderType"="Transparent"  "Queue"="Transparent+100"}
    Pass
    {
        ZWrite Off
        Offset -1, -1

        Fog { Mode Off }

        //AlphaTest Greater .1
        AlphaTest Less 1
        ColorMask RGB
        Blend One SrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

struct v2f
{
float4 pos : SV_POSITION;
float2  uv_Main     : TEXCOORD0;
};

sampler2D _ShadowTex;
float4 _Color;
float4x4 _Projector;

v2f vert(appdata_tan v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv_Main = mul (_Projector, v.texcoord).xy;
return o;
}

half4 frag (v2f i) : COLOR
{
half4 tex = tex2D(_ShadowTex, i.uv_Main) * _Color;
tex.a = 1-tex.a;
return tex;
}
ENDCG

    }
}
}

This doesn't work, it looks like the projection is being done wrong, as it seems to take only a very little part of the texture I'm passing in:

alt text

(I didn't use the same texture since the other one was simply giving invisible results, whereas this one shows a little gradient on the right coming from the texture, God knows from what part of it though) (The receiving geometry in the back is a Terrain in both cases)

Anyone knows projectors in great details?

Thanks.

Your Cg version is missing the fixed function texture generation - note "TexGen ObjectLinear" in the fixed function shader. Which means the UV used by the projector is object-space vertex position. So, typing out of my head (might not work):

half2 uv = mul (_Projector, v.vertex).xy;

Also, if you need a perspective projector, you'll need to compute half4 UV in the vertex shader, and then use something like this in the pixel shader:

half4 col = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uv));