Old shader broke with 3.1 update. Help?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By 9BitStrider
shader_type canvas_item;

//Set target colors.
uniform vec4 target_color_1 : hint_color;
uniform vec4 target_color_2 : hint_color;
uniform vec4 target_color_3 : hint_color;

//Set replacement colors.
uniform vec4 replace_color_1 : hint_color;
uniform vec4 replace_color_2 : hint_color;
uniform vec4 replace_color_3 : hint_color;

void fragment() {
    if (COLOR == target_color_1)
    {
        COLOR = replace_color_1
    }
    if (COLOR == target_color_2)
    {
        COLOR = replace_color_2
    }
    if (COLOR == target_color_3)
    {
        COLOR = replace_color_3
    }
}

Basically I want to be able to change the color of specific target colors for the player and replace them with another color during gameplay. Using the above, while it worked before, now only shows a large white box in place of the player’s sprites. How would I get this working again?

You are comparing vec4s with floating point values. So much can go wrong here.
I’d begin by assigning a default color when all matches fail so you see if the compare just goes wrong but the shader still works.

Why a vec4 comparison goes wrong?
When the values are just slightly differen (even the alpha value) then the comparison might fail. Even if the precisions of COLOR and (default precision) vec4 are different this may fail. If onced looked closer at binary reprentations of floating points you might understand.

Anyway perhaps there’s a more “tolerant” way to compare these values.
I.e. if ( length( COLOR.rgb - target_color_1.rgb )<0.01 )
I didn’t check this but length should be the length of a vector. If you take the length of the difference then you might get a value that is close to 0.0 when all values match. I limited this to rgb which is optional but often you don’t want to compare alpha. Alternatively you could compare each value separately if ( (abs(COLOR.r-target_color_1.r)<0.01) && (abs(COLOR.g-target_color_1.g)<0.01) && (abs(COLOR.b-target_color_1.b)<0.01)) or you probably also can use if ( distance(COLOR.rgb,target_color_1.rgb) < 0.01 )

wombatstampede | 2019-05-29 10:42

Got MOST of this working using the following:

shader_type canvas_item;

uniform vec4 t_col1 : hint_color;
uniform vec4 t_col2 : hint_color;
uniform vec4 t_col3 : hint_color;

uniform vec4 r_col1 : hint_color;
uniform vec4 r_col2 : hint_color;
uniform vec4 r_col3 : hint_color;

void fragment() {
	vec4 color = texture(TEXTURE, UV);
	
	if (color == t_col1) COLOR = r_col1;
	else if (color == t_col2) COLOR = r_col2;
	else if (color == t_col3) COLOR = r_col3;
}

However, this leaves what should be transparent pixels visible. I’ve attempted to compare the alpha of those pixels, but to no avail. Any suggestions?

9BitStrider | 2019-05-29 18:09

Where are these pixels transparent. In the TEXTURE ? If that’s the case then check the import format. If you use the GLES2 renderer the ETC format (VRAM Compression) can’t do transparency. You’d have to use “Lossless” or “Lossy” compression on import. (Not true for GLES3/ETC2)

wombatstampede | 2019-05-30 10:56