It sounded like a fun challenge, so I made a post processing shader for this. I haven't done one earlier, so it was good exercise.
Step 1: make a viewportcontainer with viewport as it's child (and everything you need to render as a child of viewport). Follow this if unsure.
Step 2: Add shader material and put this in your shader:
shader_type canvas_item;
render_mode blend_mix;
uniform sampler2D palette;
void fragment()
{
vec3 source_col = texture(TEXTURE, UV).rgb;
vec3 closest_col = vec3(0.0);
float smallest_error = 10.0;
int palette_size = textureSize(palette, 0).x;
float palette_pixel_size = 1.0 / float(palette_size);
for (int x = 0; x < palette_size; x++)
{
vec3 palette_col = texture(palette, vec2(float(x) * palette_pixel_size, 0.0)).rgb;
float error = distance(source_col, palette_col);
if (error < smallest_error)
{
closest_col = palette_col;
smallest_error = error;
}
}
COLOR.rgb = closest_col;
}
Step 3: In shader params, add your palette texture. It should have all the colors in one row. I tried downloading palettes from lospec in 1x png format, works well. Set filtering off from import settings!
