Anti-alias Color Swapper
There are quite a few color swapping shaders but mine works with higher res drawings that aren’t pixel art.
Every color key should have a matching replacement color to work properly. Adjust the threshold until the desired color is matched.
There is by default a max of 8 colors, but you can increase this in the code if need be.
Shader code
shader_type canvas_item;
uniform vec3[8] color_keys : source_color;
uniform vec3[8] replacement_colors : source_color;
uniform float threshold : hint_range(0.0, 1.0, 0.01) = 0.14;
vec3 rgb_to_hsv(vec3 col) {
float cmax = max(col.r, max(col.g, col.b));
float cmin = min(col.r, min(col.g, col.b));
float diff = cmax - cmin;
float h = 0.0;
float s = 0.0;
if (cmax != cmin) {
if (cmax == col.r) h = mod(60.0 * ((col.g - col.b) / diff) + 360.0, 360.0);
else if (cmax == col.g) h = mod(60.0 * ((col.b - col.r) / diff) + 120.0, 360.0);
else if (cmax == col.b) h = mod(60.0 * ((col.r - col.g) / diff) + 240.0, 360.0);
}
if (cmax > 0.0) s = (diff / cmax) * 100.0;
float v = cmax * 100.0;
return vec3(h, s, v);
}
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec3 col = original_color.rgb;
vec3 oc = rgb_to_hsv(col);
for (int i = 0; i < color_keys.length(); i++) {
if (color_keys[i] == replacement_colors[i]) continue;
vec3 rc = rgb_to_hsv(color_keys[i]);
float hue_diff = rc.r - oc.r;
float sat_diff = rc.g - oc.g;
float val_diff = rc.b - oc.b;
// Check if we have a match
if (hue_diff > -100.0 * threshold && hue_diff < 100.0 * threshold && sat_diff > -100.0 * threshold && sat_diff < 100.0 * threshold) {
// Calculate how dark the original pixel is (0 = black, 1 = full brightness)
float brightness = oc.z / 100.0;
// Replace color and keep brightness
col = replacement_colors[i].rgb * brightness;
break;
}
}
COLOR = vec4(col, original_color.a) * COLOR;
}

