Extensible Color Palette (Uniform Colors)
NOTE:
By default, this shader is set up for Godot 3.x, for Godot 4.x (Vulkan), change the uniform hints from
“hint_color” to “source_color”.
-That’s it!
This shader allows you to turn greyscale colors (based on highest value of red, green, or blue) into defined colors in the shader parameters.
By default, it uses 9 colors, and can be programmed for more or fewer designated colors.
When adding more colors in the variables, (ie color0, color1, etc.) each variable’s name must be “color#”, where the # denotes its number. the variables must be numbered from 0 to “max-1” where “max” is the number of colors you have.
The second part of adding colors is by editing the vec4 array named “colors”. Each “color#” variable needs to be present in this list for that color to appear in the shader.
(All of the multiplication and division is based on the array’s length).
The order in which the “color#” variables are listed in the array is the same order in which they will appear on their respective greyscale value.
If you want to define 12 colors that you want to use, make sure you have variables “color0” to “color11”, and list them in the array named “colors[]”
I made this shader for its flexibility through gdscript
GDScript Examples for 3.x:
for index in range( 0, x ):
get_material().set_shader_param(“color”+str(index), new_color)
Example 2 (How I use it in 3.x):
for index in range(0,len(new_palette)):
tween.parallel().tween_property(get_material(), NodePath(“shader_param/color”+str(index)), new_pal[index], duration)
GDScript Examples for 4.x:
get_material().set_shader_param(“color0”, new_color)
Example 2 (How I use it in 4.x):
for index in range(0, len(new_palette)):
var tween = get_tree().create_tween().bind_node(self)
tween.parallel().tween_property(get_material(), NodePath(“shader_parameter/color”+str(index)), new_pal[index], duration)
-June 18, 2023-
Merged Both the Vulkan and GLES versions of this shader into one webpage to declutter my presence (from 3 to 2) shaders on the GodotShaders Website.
Shader code
shader_type canvas_item;
render_mode blend_mix, unshaded;
uniform vec4 color0: hint_color;
uniform vec4 color1: hint_color;
uniform vec4 color2: hint_color;
uniform vec4 color3: hint_color;
uniform vec4 color4: hint_color;
uniform vec4 color5: hint_color;
uniform vec4 color6: hint_color;
uniform vec4 color7: hint_color;
uniform vec4 color8: hint_color;
void fragment() {
// 1: Define the color list
vec4 colors[] = {color0,color1,color2,color3,color4,color5,color6,color7,color8};
// 2: Grab the junk off of the screen
vec3 scrn_uv = vec3(UV, 0.0);
vec3 color_input;
float alpa_input;
{
vec4 _tex_read = textureLod(TEXTURE, scrn_uv.xy, 0.0);
color_input = _tex_read.rgb;
alpa_input = _tex_read.a;
}
// 3: Turn that junk into the superior "Grey"
float grey_value;
{
vec3 c = color_input;
float max1 = max(c.r, c.g);
float max2 = max(max1, c.b);
grey_value = max2;
}
// 4: Multiply the superior "Grey" into the ultimate "Multiplied Grey"
float multiplier = float(colors.length()-1);
float multiplied_grey = grey_value * multiplier;
// 5: Round the ultimate "Multiplied Grey" to integer-like values; Achieve god-like "Rounded Multiplied Grey"
float round_mult_grey = round(multiplied_grey);
// 6: Use the power of your new god to pick your output colors based on their color index.
vec4 out_color = colors[int(round_mult_grey)];
// 7: Meet your new friends: the output colors.
COLOR = out_color;
COLOR.a = alpa_input;
// 8: Profit.
}
Hi, this works great, but if I were to apply this to a label, the text is always the lightest color, no matter what it was originally. Any ideas how to solve this?
I’m not usually here to reply, but if you want the right behavior from control nodes, or at least a label like I tried, you’ll need to apply the material to the label’s parent, and let the label use the parent’s material.