Shader Not Working at Runtime

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

I’m writing a simple shader that changes a single color based on interpolation. It works in-editor but not at runtime and I’m not sure why.

Even if I am mistaken about how editor changes for shaders work at runtime, I made an animation using an AnimationPlayer that modifies the interpolation field at runtime as well with no noticeable changes, and I know I did that right because it works in-editor as well.

I’ve only found a couple really old issues for Godot 2.x that were similar, and the solutions either didn’t seem applicable (largely due to 2.0 deprecation) or I didn’t quite understand how I could apply it to my particular case.

I’m sure I’m missing something minuscule based on that nobody seems to have this issue but any help sorting this out would be appreciated.

Edit: my shader code for reference:

shader_type canvas_item;

uniform float eye_cutoff : hint_range(0.0, 1.0);
uniform vec4 curr_eye_color : hint_color;

vec4 changeEyes(vec4 curr_color)
{
	if(curr_eye_color == curr_color)
	{
		float r = 12.0/255.0;
		float g = 123.0/255.0;
		float b = 30.0/255.0;
		
		float r2 = 90.0/255.0;
		float g2 = 145.0/255.0;
		float b2 = 255.0/255.0;
		
		float r_int = r * (1.0 - eye_cutoff) + r2 * eye_cutoff;
		float g_int = g * (1.0 - eye_cutoff) + g2 * eye_cutoff;
		float b_int = b * (1.0 - eye_cutoff) + b2 * eye_cutoff;
		
		return vec4(r_int,g_int,b_int,1);
	}
	else
		return curr_color;
}

void fragment() {
	vec4 curr_color = texture(TEXTURE,UV); // Get current color of pixel
	
	COLOR = changeEyes(curr_color);
}

What are you talking about?

karlessayhelp | 2019-12-24 06:59

I’m not sure how to elucidate further. The colors I’m trying to switch are the eyes if that wasn’t clear. I show how it’s working in the linked video.

tyo | 2019-12-24 13:23

:bust_in_silhouette: Reply From: estebanmolca

Changing if(curr_eye_color == curr_color) to if (round (curr_eye_color) == round (curr_color)) works for me, but of course I lose color presicion. It seems that the problem is in the selection of the color of the hint_color or that ingame the color changes slightly and no longer detects them as equals. I comment if I find a better way to solve it.

How very strange. I’m using the exact hex value for the hinted color. I’ll keep messing with it too in the meanwhile.

tyo | 2019-12-24 13:24

adding this function:

vec4 trunc_vec(vec4 v, float n){
	v.x=floor(pow(10,n) * v.x) / pow(10,n);
	v.y=floor(pow(10,n) * v.x) / pow(10,n);
	v.z=floor(pow(10,n) * v.x) / pow(10,n);
	return v;
}

and then:

if(trunc_vec(curr_eye_color,5) == trunc_vec(curr_color,5) )

n would be the precision after the floating point. It seems that this matches colors better.

https://en.wikipedia.org/wiki/Truncation

…and sorry mi english

estebanmolca | 2019-12-24 13:40

Yes, this seems to work. I also slept on this thread that was subtly mentioned in the OP and found I was over-thinking how to use the threshold values, I got it to work by applying a small threshold as well:

if(orig_eye_color.r + threshold >= curr_color.r && orig_eye_color.r - threshold <= curr_color.r )

where threshold is an arbitrarily small number (0.01 works in this case).

It’s somewhat strange you have to apply such workarounds but I guess it’s not too big a deal. Thanks for your help, think I’ll go with your solution since it sounds more precise.

tyo | 2019-12-24 13:50

Ok, remember that you can also increase or decrease the n function parameter for more or less presicion.

estebanmolca | 2019-12-24 13:55