Palette Swap (no recolor / recolor)

Okay, so you want to a palette swap. First, let’s get a sprite. Let’s use a sprite from Pixel Adventure by Pixel Frog because it was the first thing I saw on itch.io. I’ll be using the slime since it has five colors.

First, let’s do the version that doesn’t require you to recolor the sprite. Let’s start by getting the colors of the sprite. Shader colors are vec4s of floats, so you have to convert them to a float between 0 and 1.

Next, get the colors that you want to convert the colors to. You can make them uniforms so that you can edit them easier and so you can just use the color picker instead of trying to convert colors to float vectors.

Now, compare the color of the current pixel to the colors that you’re looking to swap to. Note that float comparison is imprecise so you can’t use ==. You can use the distance() function instead.

shader_type canvas_item;


uniform vec4 original_0: hint_color;
uniform vec4 original_1: hint_color;
uniform vec4 original_2: hint_color;
uniform vec4 original_3: hint_color;
uniform vec4 original_4: hint_color;
uniform vec4 replace_0: hint_color;
uniform vec4 replace_1: hint_color;
uniform vec4 replace_2: hint_color;
uniform vec4 replace_3: hint_color;
uniform vec4 replace_4: hint_color;

const float precision = 0.1;


vec4 swap_color(vec4 color){
	vec4 original_colors[5] = vec4[5] (original_0, original_1, original_2, original_3, original_4);
	vec4 replace_colors[5] = vec4[5] (replace_0, replace_1, replace_2, replace_3, replace_4);
	for (int i = 0; i < 5; i ++) {
		if (distance(color, original_colors[i]) <= precision){
			return replace_colors[i];
		}
	}
	return color;
}


void fragment() {
	COLOR = swap_color(texture(TEXTURE, UV));
}

Okay, now let’s do the method that requires you to require to recolor the sprite. Here, we’ll be using UV coordinates to determine what color to set the current pixel to.

First, make a palette. Okay – now that you have the palette made, note the UV coordinates of the top-left corner of each color. The UV coordinates are floats that correspond to how far the pixel is from the origin – so a U coordinate of 0.5 is halfway across the image’s width.

Now, for each color you want to recolor, change the RED value to the U-coordinate of the color you want to replace it with in the palette, and the GREEN value to the V-coordinate (BLUE value can be whatever you want, I guess). The result should look pretty weird but don’t worry, the shader will fix it!

Now you also need to make a uniform for your palette. Its type should be sampler2D.

shader_type canvas_item;


uniform sampler2D palette;


void fragment() {
	COLOR = texture(palette, texture(TEXTURE, UV).rg);
}

If you want to preserve the alpha channel you can use this code instead:

void fragment() {
	vec4 color = texture(TEXTURE, UV);
	vec4 result_color = texture(palette, color.rg);
	result_color.a = color.a;
	COLOR = result_color;
}

And there you have it! Two different ways to do a palette swap with a Godot shader!

Shader code
// No recolor

shader_type canvas_item;


uniform vec4 original_0: hint_color;
uniform vec4 original_1: hint_color;
uniform vec4 original_2: hint_color;
uniform vec4 original_3: hint_color;
uniform vec4 original_4: hint_color;
uniform vec4 replace_0: hint_color;
uniform vec4 replace_1: hint_color;
uniform vec4 replace_2: hint_color;
uniform vec4 replace_3: hint_color;
uniform vec4 replace_4: hint_color;

const float precision = 0.1;


vec4 swap_color(vec4 color){
	vec4 original_colors[5] = vec4[5] (original_0, original_1, original_2, original_3, original_4);
	vec4 replace_colors[5] = vec4[5] (replace_0, replace_1, replace_2, replace_3, replace_4);
	for (int i = 0; i < 5; i ++) {
		if (distance(color, original_colors[i]) <= precision){
			return replace_colors[i];
		}
	}
	return color;
}


void fragment() {
	COLOR = swap_color(texture(TEXTURE, UV));
}

// Recolor

shader_type canvas_item;


uniform sampler2D palette;


void fragment() {
	vec4 color = texture(TEXTURE, UV);
	vec4 result_color = texture(palette, color.rg);
	result_color.a = color.a;
	COLOR = result_color;
}
Tags
pallette-swap, pixel-art, sprite

More from Exuin

Gaussian Blur

Scrolling background

Box Blur

Related shaders

Color Range Swap [UPDATED]

Palette Filter For 3D and 2D

Palette Shader

The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.
guest
0 Comments
Inline Feedbacks
View all comments