+2 votes

How would be the best way to go about limiting my game's color palette to the NES one? I did this with an earlier build, but was curious to see if there was another way.

Palette Being Used

Shader Code

Godot version 3.5.1
in Engine by (236 points)

Completely unrelated this is the only thing i hate about Godot.
No uniform arrays in shaders

@Wakatta - I don't have much shader experience, but doesn't this provide the support you mention?

I'll give that a try to clean up the code a bit. I'm just curious if there's a way to limit the overall color palette of my game to the colors in the image above. Is there a way to check color range compared to X color?

1 Answer

+3 votes
Best answer

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!

3D Platformer Demo with NES palette

by (1,100 points)
selected by

That's amazing! Thank you so much!

If it helps don't forget to mark answer as accepted - it helps others to find relevant answers when they're having similiar issue :)

Like 9BitStrider said...
This is amazing!!!

In Godot 4 I was only able to get this to work by using hint_screen_texture like this:

shader_type canvas_item;
render_mode blend_mix;
// filter_nearest so you don't get weird ghost palette colors!!
uniform sampler2D palette: filter_nearest;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;

void fragment()
{
   vec3 source_col = texture(screen_texture, SCREEN_UV).rgb;
   //...everything else is the same
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.