Get values from sampler2D gradient in shader code

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By quackedup

Hey all, I’ve been working on a shader that reduces the colors on the screen but ran into a bit of a problem, I can add what colors to show on screen but only manually in the code. I want to make a sampler2D and a gradient choose the colors there but I don’t know how to get the values from it.

shader_type canvas_item;

//originally I have to manually create a new color
uniform vec4 color_1 = vec4(0.5, 0.5, 0.5, 1);
uniform vec4 color_2 = vec4(0, 0, 0, 1);

//what I want, to use a sampler2D and get the values from a gradient texture
uniform sampler2D sampler;

void fragment() {

//originally
vec4 colors[] = {color_1, color_2};

//what I want
//vec4 colors[] = {sampler.PoolColorArray}
float min_diff = -1.0;
vec4 min_color = vec4(0.0, 0.0, 0.0, 1.0);
//float test = PickColorArray[]

vec2 uv = SCREEN_UV;

vec4 temp = textureLod(SCREEN_TEXTURE, uv, 0.0);

min_diff = 1000.0;
for (int i = 0; i < colors.length(); i++) {

	float curr_dist = distance(colors[i], temp);
	if (curr_dist < min_diff) {
		min_diff = curr_dist;
		min_color = colors[i];
	}
}

COLOR.rgb = min_color.rgb;
}

enter image description here

:bust_in_silhouette: Reply From: USBashka

Function texture(sampler2D, vec2) returns a color from given position of image. In your case you can make this function

vec4 get_gradient_color(float position) {
    return texture(sampler, vec2(position, 0.5));
}

And then get colors with get_gradient_color(0.8), where 0.8 is position on image between 0 and 1.

well this is a bit better but this doesn’t solve my problem, I would like to just select a new color in the gradient and it automatically puts it into the colors array without having to add it manually every time.

because this is how I have to add colors now, I have to manually add get_gradient_color() every time

vec4 colors = {get_gradient_color(1), get_gradient_color(0.8), get_gradient_color(0.6)};

in the original picture I included in the gradient under colors theres a PoolColorArray, is there no way to use that? And reference the all the colors in there? like:

vec4 colors = {sampler.PoolArrayColor};

also sorry if this is something really basic and im just being dumb but I’m new to shader language and godot all together, and I didn’t find anything in the documentation.

quackedup | 2022-07-31 09:53

Sorry, but sampler2D is just an image and doesn’t have array of used colors. You can generate it manually, but it’s not good since shader runs for every pixel for every frame. It would be cool to add hint_color to array elements, but as I know, it’s not possible yet, so you better stick to your solution and write something like this:

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;

This will let you use palette in the editor

USBashka | 2022-07-31 11:04

Can you add the vec4 color directly from the editor? Because like this I still have to go into the code editor and if I want to add a lot more colors it will become a little annoying.

quackedup | 2022-07-31 11:20

Sorry, no.​​​​

USBashka | 2022-07-31 11:25

Well alright thanks for the help tho.

quackedup | 2022-07-31 11:28

:bust_in_silhouette: Reply From: thomas_laverne

I think you can use the static size of the texture to iterate on it.
For instance, if you texture is 46 pixel wide, it would give something like this:
Best Regards,
Tom

shader_type canvas_item;
uniform sampler2D gradient : hint_black;

void fragment(){
vec3 input_color = texture(TEXTURE, UV).rgb;
vec3 final_color;
float min_diff = 1000.0;
// find the closest color
for (int i = 0; i < 46; i++) {
vec3 palette_color = texture(gradient,vec2(float(i)/46.0,0.5)).rgb;
float curr_dist = distance(palette_color, input_color);
if (curr_dist < min_diff) {
min_diff = curr_dist;
final_color = palette_color;
}
}
COLOR.rgb = final_color;
}