2D Lighting with a Color-Swap shader

I’ve been scratching my head about how to implement light into my 2D pixel-art game, and the problem I’ve stumbled upon is the custom color-swap shader materials not being affected by Unity’s 2D Global Light, while everything having the Sprite-Lit-Default material is.

To explain the color swap shader: I have a lot of GameObjects dynamically generate in the scene, which use the same sprite, but we want some instances to use different colors for different parts of the body. The solution i found for this is a color swap shader online, which swaps a color (_OriginalColor1) with another color (_TargetColor1) based on float tolerance (_Tolerance1). Additionally, the color is multiplied with property _Color so I can modify it even further via a different script if need be.

Properties _OriginalColor1 and _Tolerance1 are set in the Inspector, while _TargetColor1 is set via a different script.

I am unsure of where to go from here, since I understand barely anything about shaders and have no clue how I could modify the shader to get affected by 2D lighting. Some posts online said that I’d need to have a reference to all light sources in the scene, which seems bizarre and unmanagable to me, since I plan to add a lot of light sources. A simpler solution surely exists, but I am just not educated enough in how shaders work. How would I go about achieving this?

Here’s the code I use for the shader:

Shader "Custom/NewColorSwap"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Color ("Color (RGBA)", Color) = (1, 1, 1, 1)

        _OriginalColor1("Original Color 1", Color) = (1,1,1,1)
        _TargetColor1("Target Color 1", Color) = (1,1,1,1)
        _Tolerance1("Tolerance 1", Range(0, 1)) = 0

        _OriginalColor2("Original Color 2", Color) = (1,1,1,1)
        _TargetColor2("Target Color 2", Color) = (1,1,1,1)
        _Tolerance2("Tolerance 2", Range(0, 1)) = 0
    }
 
    SubShader
    {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite Off
 
        Cull Off
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
 
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
 
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
 
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;

            float4 _OriginalColor1;
            float4 _TargetColor1;
            float _Tolerance1;

            float4 _OriginalColor2;
            float4 _TargetColor2;
            float _Tolerance2;
 
            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                half4 col = tex2D(_MainTex, i.uv);
                half4 newCol = _Color;
 
                if (col.a == 0)
                {
                    return half4(0, 0, 0, 0);
                }

                if (length(col.rgb - _OriginalColor1.rgb) < _Tolerance1)
                {
                    return half4(_TargetColor1.rgb * newCol.rgb, _TargetColor1.a * newCol.a);
                }
 
                if (length(col.rgb - _OriginalColor2.rgb) < _Tolerance2)
                {
                    return half4(_TargetColor2.rgb * newCol.rgb, _TargetColor2.a * newCol.a);
                }

                return half4 (col.rgb * newCol.rgb, col.a * newCol.a);
            }
            ENDCG
        }
    }
}

Thank you in advance!

You can have a global property that affects all shaders. Let’s say we call it “_WorldLight”. You can then call;

Shader.SetGlobalColor(“_WorldLight”, color);

Where color is the Light2D color.

In your custom shader you can then just multiply the output color with this global property’s color.

EDIT: I see that you’re going to have multiple light sources, not sure how you would go about with that buthopefully this puts you in the right track.

this shader doesn’t have any code that calculates the light’s result on the fragment, why would it be effected by any light?

You can do this shader easily with shader graph, try looking at some 2d shadergraph tutorials then implement the color swap. If your shader is 2d lit, it’ll automatically be effected by the 2d lights