Projector creates multiple projections of the shadder

Hi!,

Im trying to build my own Fog of War, I’m doing it with a projector, I alredy have it, with a custom shader that acts as a mask and with a projector:

It works ok, but I have a problem, the projector repeats the shader over all the GameObjects, as you can see on the next image:

Another case:

Here is my shader code:

Shader "Custom/FOWShader"
{
    Properties
    {
        _Color("Color", Color) = (0,0,0,0.7)
        _MainTex("Canvas", 2D) = "white" {}
        _Smoothness("Feather", Range(0,0.1)) = 0.005
        _Rotation("Rotation", Range(0.0, 360.0)) = 0.0

    }

        SubShader
    {
        Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" "LightMode" = "ForwardBase" }
        Blend One One
        Lighting off
        ZWrite Off
       
       

        CGPROGRAM
#pragma surface surf NoLighting noambient alpha:blend 
#pragma vertex vert

        fixed4 _Color;
    sampler2D _MainTex;
    float _Smoothness;

    struct Input
    {
        float2 uv_MainTex;
    };
    float _Rotation;

    void vert(inout appdata_full v) {
        v.texcoord1 = v.texcoord; // copy uvs from texcoord to texcoord1 (aka uv2) before rotation

        float rot = _Rotation / (57.2957795131);
        float sinX = sin(rot);
        float cosX = cos(rot);
        float sinY = sin(rot);
        float2x2 rotationMatrix = float2x2(cosX, -sinX, sinY, cosX);
        v.texcoord.xy = mul(v.texcoord.xy - 0.5, rotationMatrix) + 0.5;


    }

    fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, float aten)
    {
        fixed4 color;
        color.rgb = s.Albedo;
        color.a = s.Alpha;
        return color;
    }


    void surf(Input IN, inout SurfaceOutput o)
    {

        half4 gaussianH = tex2D(_MainTex, IN.uv_MainTex + float2(-_Smoothness,0))*0.25;
        gaussianH += tex2D(_MainTex, IN.uv_MainTex)*0.5;
        gaussianH += tex2D(_MainTex, IN.uv_MainTex + float2(_Smoothness,0))*0.25;

        half4 gaussianV = tex2D(_MainTex, IN.uv_MainTex + float2(0,-_Smoothness))*0.25;
        gaussianV += tex2D(_MainTex, IN.uv_MainTex) *0.5;
        gaussianV += tex2D(_MainTex, IN.uv_MainTex + float2(0, _Smoothness))*0.25;

        half4 blurred = (gaussianH + gaussianV)*0.5;

        o.Albedo = _Color.rgb * blurred.g;
        o.Alpha = _Color.a - blurred.g;
    }

    ENDCG
    }
        FallBack "Diffuse"
}

I realy dont know what I must do to project only one texture over all the entire scene but not over each mesh.

Two things:
Never use a surface shader for something that is “unlit”. The “NoLighting” hack people like to use with the surface shader is still doing some lighting, and will mess up if there are multiple lights in the scene.
Don’t use a surface shader with a projector. Shaders used with projectors don’t receive any lighting information, and thus will render oddly.

Now, those two things end up kind of canceling each other out, but there are still unnecessary calculations being done when you use a surface shader that end up making them slower than they should be for this use case. You should be using a shader written specifically to be used with Unity’s projectors.

Here’s an example shader:

The texture using the uvShadow will be aligned to the projector’s projection direction. The texture using the uvFalloff is aligned along the projector’s facing stretching from the near to the far plane. You can remove either texture and it’s associated calculations if not needed.

1 Like

Wow it’s nice, thanks! I rly learned so much things from u :smile: