1
\$\begingroup\$

Does anyone know of a good strategy to make point lights with no falloff, eg. anything in the radius of the light will be 100% illumination while anything outside the radius will be 0% illumination.

I want to use this as a sort of 3D line of sight drawing. The line of sight is a big sphere originating from the character's head that I thought would be a clever idea to have that represented as a point light, however with the falloff it doesn't correctly show where the edge of the line of site is.

I've tried a few solutions, such as a custom falloff package (doesn't seem to have the options I want) and a few shaders, but I am terrible at shaders so it's difficult for me to debug. I'll post the shader here in case somebody can tell me if I'm being dumb, otherwise if someone can point me to a different solution that would be great. Thanks!

Here's a shader I tried, but it just turns everything invisible and it's not immediately obvious to me why:

Shader "Custom/No Falloff v2"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        Tags{ "Queue" = "Transparent" }

        Pass
    {
        Blend SrcAlpha OneMinusSrcAlpha

        Tags{ "LightMode" = "ForwardAdd" }
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"
        #include "Lighting.cginc"

        // compile shader into multiple variants, with and without shadows
        #pragma multi_compile_fwdadd_fullshadows
        // shadow helper functions and macros
        #include "AutoLight.cginc"

        sampler2D _MainTex;
    float4 _MainTex_ST;

    fixed4 _Color;

    struct v2f
    {
        float2 uv : TEXCOORD0;
        SHADOW_COORDS(1) // put shadows data into TEXCOORD1
            float4 pos : SV_POSITION;
    };

    v2f vert(appdata_base v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
        TRANSFER_SHADOW(o)
            return o;
    }

    fixed4 frag(v2f i) : SV_Target
    {
        fixed4 col = tex2D(_MainTex, i.uv) * _Color;

    // compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed)
    fixed shadow = SHADOW_ATTENUATION(i);

    if (shadow < 0.5)
    {
        return fixed4(0.0156862745, 0, 0.23529411764,1.0); //or any other color for shadow
    }

    return col;
    }
        ENDCG
    }

        // shadow casting support
        UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
    }
}
\$\endgroup\$
  • \$\begingroup\$ If it's just a big sphere, you could also use a sphere collider and use a semi-transparent mesh as your "line of sight" to go along with it. It should take fewer resources than a point light too. Is there a specific reason you're picking a point-light? This old answer of mine might be of use to you as a shader with a few modifications. \$\endgroup\$ – John Hamilton Nov 13 at 11:24
  • 1
    \$\begingroup\$ @JohnHamilton Well I guess it's a bit deceptive to say it's a sphere. It's a sphere under ideal circumstances with no obstructions but the main point of having it be a point light rather than a sphere collider is that line of sight will be blocked by other objects in the way. Does that make sense? Also there will only ever be a small number (under 10 generally) of these in a scene at any time so resources aren't the biggest priority. \$\endgroup\$ – William Miles Nov 14 at 23:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.