Intersection of multiple projectors

Hello everyone,

simple question, hard answer:
in my 3D isometric strategy game, several units have projectors on top of them to indicate their area of effect.
The projected image is a simple circle.
I want the projectors to “unite” between them, when intersecting.

This is the shader i’m currently using:

Shader "Projector/AdditiveTint" {
    Properties {
        _Color ("Tint Color", Color) = (1,1,1,1)
        _Attenuation ("Falloff", Range(0.0, 1.0)) = 1.0
        _ShadowTex ("Cookie", 2D) = "gray" {}
    }
    Subshader {
        Tags {"Queue"="Transparent"}
        Pass {
            ZWrite Off
            ColorMask RGB
            Blend SrcAlpha One // Additive blending
            Offset -1, -1

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
           
            struct v2f {
                float4 uvShadow : TEXCOORD0;
                float4 pos : SV_POSITION;
            };
           
            float4x4 unity_Projector;
            float4x4 unity_ProjectorClip;
           
            v2f vert (float4 vertex : POSITION)
            {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, vertex);
                o.uvShadow = mul (unity_Projector, vertex);
                return o;
            }
           
            sampler2D _ShadowTex;
            fixed4 _Color;
            float _Attenuation;
           
            fixed4 frag (v2f i) : SV_Target
            {
                // Apply alpha mask
                fixed4 texCookie = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
                fixed4 outColor = _Color * texCookie.a;
                // Attenuation
                float depth = i.uvShadow.z; // [-1 (near), 1 (far)]
                return outColor * clamp(1.0 - abs(depth) + _Attenuation, 0.0, 1.0);
            }
            ENDCG
        }
    }
}

What you want is basically not possible, not the way you’re thinking about it. Two projectors simply have no way of working together like you want. After the first one is drawn it will have already drawn its circle, and then the second one will draw and has no way of removing the line already drawn.

Some methods of doing this:
A single shader & projector that draws multiple circles. Basically you have to have a script based system that detects overlaps and sets up a single material with the relevant positions and a single projector that encompasses the entire area. This is probably the “simplest” method. This tutorial from Alan Zucconi is mildly related to how to setup the shader:

Another method is rendering a distance map using a render texture and multiple passes of a shader using a max blend op. Then you would use a projector or a full screen pass to translate that distance map to an outline. This is similar to the above option and has a lot of similar work required from the script side but uses simpler shaders so was common in older games. I would suggest the above option unless you really want to get into the nitty gritty of graphics rendering.

One last option I’ll give you is to not use the built in projectors at all, but instead generate outline meshes yourself in script. This offers the most control, and is how a lot of RTS games do it. This option requires a bit more math, and is best if only applied to a flat plane or a known ground mesh.

1 Like

Thanks bgolus,
the article you’ve linked is very interesting… i’ll work on that.
Since i have very little knowledge of shaders, i hope to get some results :roll_eyes: