Projector onto surface that has alpha cutout

Hi
Please sea attached, I need to mod either the projector shader or the surface it’s projecting onto shader!

The projector is projecting onto mesh that should be invisible, I need to add the alpha from the surface into the projection somehow, please help.

I have tried render queue orders but no luck.

Projector shader:

// Upgrade NOTE: replaced '_Projector' with 'unity_Projector'
// Upgrade NOTE: replaced '_ProjectorClip' with 'unity_ProjectorClip'
Shader "Projector/LightWithIntensity" {
     Properties {
         _Color ("Main Color", Color) = (1,1,1,1)
         _ShadowTex ("Cookie", 2D) = "" {}
         _FalloffTex ("FallOff", 2D) = "" {}
         _Intensity ("Intensity",Float) = 1
     }
   
     Subshader {
         Tags {"Queue"="Transparent" "RenderType"="Transparent"}
         Pass {
             ZWrite Off
             ColorMask RGB
             Blend DstColor One
             Offset -1, -1


             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #pragma multi_compile_fog
             #include "UnityCG.cginc"
           
             struct v2f {
                 float4 uvShadow : TEXCOORD0;
                 float4 uvFalloff : TEXCOORD1;
                 UNITY_FOG_COORDS(2)
                 float4 pos : SV_POSITION;
             };
           
             float4x4 unity_Projector;
             float4x4 unity_ProjectorClip;
           
             v2f vert (float4 vertex : POSITION)
             {
                 v2f o;
                 o.pos = UnityObjectToClipPos(vertex);
                 o.uvShadow = mul (unity_Projector, vertex);
                 o.uvFalloff = mul (unity_ProjectorClip, vertex);
                 UNITY_TRANSFER_FOG(o,o.pos);
                 return o;
             }
           
             fixed4 _Color;
             sampler2D _ShadowTex;
             sampler2D _FalloffTex;
             float _Intensity;
           
             fixed4 frag (v2f i) : SV_Target
             {
                 fixed4 texS = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
                 texS.rgb *= _Color.rgb;
                 texS.a = 1.0-texS.a;
   
                 fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
                 fixed4 res = texS * _Intensity * texF.a;
                 UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(0,0,0,0));
                 return res;
             }
             ENDCG
         }
     }
}

Surface shader:
Shader “Standard (Double Cutout)” {

Properties {
_Color (“Color”, Color) = (1,1,1,1)
_MainTex (“Albedo (RGBA)”, 2D) = “white” {}
_MaskTex (“Mask (RGBA)”, 2D) = “white” {}
_Glossiness (“Smoothness”, Range(0,1)) = 0.5
_Metallic (“Metallic”, Range(0,1)) = 0.0
//_Cutoff (“Alpha cutoff”, Range(0,1)) = 0.5
//_BumpMap (“Normal Map”, 2D) = “bump” {}
}

SubShader {
Tags {“Queue”=“Transparent” “IgnoreProjector”=“False” “RenderType”=“Transparent”}
//Tags {“Queue”=“AlphaTest” “Ignore Projector” = “True” “RenderType”=“Transparent”}
ZWrite Off
//Blend SrcAlpha One
//Blend OneMinusSrcAlpha SrcAlpha
//Offset -1, -1

LOD 200

CGPROGRAM

#pragma surface surf Standard fullforwardshadows alpha:fade

//#pragma surface surf Standard alpha : fade

#pragma target 3.0

sampler2D _MainTex;
sampler2D _MaskTex;
sampler2D _BumpMap;

struct Input {
float2 uv_MainTex;
float2 uv2_MaskTex;
float2 uv_BumpMap;
};

half _Glossiness;
half _Metallic;
fixed4 _Color;

void surf (Input IN, inout SurfaceOutputStandard o) {

fixed4 main = tex2D (_MainTex, IN.uv_MainTex) * _Color;
fixed4 mask = tex2D (_MaskTex, IN.uv2_MaskTex);

//Multiplied by the mask.rgb in this case, because if you use a white texture as your mask,
//you can color it black to add burn marks around the damage.
o.Albedo = main.rgb * mask.rgb;

//For most cases, you’d probably just want:
//surface.Albedo = main.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;

o.Alpha = main.a * mask.a;
//o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
}

ENDCG
}
FallBack “Diffuse”
}

There is no solution to this issue with projectors.

The way projectors work is they re-render each mesh the projector’s frustum overlaps with, just using the Projector’s material instead of the one assigned on the mesh’s renderer component. This means if you have a shader that’s using alpha testing or transparency, the projector has no way to know that. It is just going to blindly render the entire mesh.

Unity’s solution to this problem was to just punt on it. If you look at Unity’s internal Alpha Cutout and Transparent shaders, they all have this line in the shader:

"IgnoreProjector"="True"

You can probably guess what that does. The Standard Shader released with Unity 5 doesn’t even bother with that and will have the same issues as your shader does.

The only solution is to not use projectors. Instead have your Surface Shader add the caustics on it’s own.

1 Like

Understood, many thanks for the reply.