Palette swap based on light position

Hello!

I’m trying to create this type of art style where dark areas gets its color swapped to a different one preserving only the edge/silhouette color.

In this example you can see the brick being lit has a greenish color and the unlit area has a dark tone:

I’ve tried to apply the concepts from these articles but couldn’t get it to work :frowning:

Shaders Case Study - Pixel Art Palette Swapping -https://www.youtube.com/watch?v=u4Iz5AJa31Q
Prime31 - SpriteLightKit - GitHub - prime31/SpriteLightKit: Blended lighting system for Unity that works with standard Sprites
Stencil Buffer Using the Stencil Buffer for Sprite Occlusion - prime31 blog - Game dev tips, tricks and random thoughts

Hi,

As I understand you cant make palette swap? or you have other conceptual problems?
I have a fork from RedBlue Games “Palette Swap” that I personally use. Be aware, that workflow is far prom polished.
Here the links:

Hi @vhman ! Thanks for sharing the links!

I’m trying to apply a different palette outside the mask like the images bellow:



This is the code used in the video:

using UnityEngine;

[ExecuteInEditMode]
public class PaletteSwapMatrix : MonoBehaviour
{
    public Color Color0;
    public Color Color1;
    public Color Color2;
    public Color Color3;

    Material _mat;

    void OnEnable()
    {
        Shader shader = Shader.Find("Hidden/PaletteSwapMatrix");
        if (_mat == null)
            _mat = new Material(shader);
    }

    void OnDisable()
    {
        if (_mat != null)
            DestroyImmediate(_mat);
    }

    void OnRenderImage(RenderTexture src, RenderTexture dst)
    {
        _mat.SetMatrix("_ColorMatrix", ColorMatrix);
        Graphics.Blit(src, dst, _mat);
    }

    Matrix4x4 ColorMatrix
    {
        get
        {
            Matrix4x4 mat = new Matrix4x4();
            mat.SetRow(0, ColorToVec(Color0));
            mat.SetRow(1, ColorToVec(Color1));
            mat.SetRow(2, ColorToVec(Color2));
            mat.SetRow(3, ColorToVec(Color3));

            return mat;
        }
    }

    Vector4 ColorToVec(Color color)
    {
        return new Vector4(color.r, color.g, color.b, color.a);
    }
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Hidden/PaletteSwapMatrix"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
           
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
           
            sampler2D _MainTex;
            half4x4 _ColorMatrix;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed x = tex2D(_MainTex, i.uv).r;
                return _ColorMatrix[x * 3];
            }

            ENDCG
        }
    }
}

Hi,

I don’t have experience in Shaders. I assume it would be better to have two tilemaps with different palettes and use sprite mask

Good news!!! I’ve spent some time studying shaders and managed to get the effect

Using SpriteLightKit and make the RenderTexture full black and white we can compare the pixel color:

half4 frag( fragmentInput i ) : COLOR
{
    half4 main = tex2D( _MainTex, i.uv );
    half4 lights = tex2D( _LightsTex, i.uv );
        fixed x = tex2D(_MainTex, i.uv).r;
       
    return lights.r > 0.9 ? _MultiplicativeFactor * main * lights : _ColorMatrix[x * 3];
}

I’m checking if the current pixel from LightsText (Black/White) is white. In that case i’m going to render the original image. Otherwise I’ll apply the color swapping on black areas.

2 Likes