Godot 4: Texture alpha that is modulated by a Tweener doesn't get passed into attached shader.

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

I am trying to fade out a Sprite2D by using tween:

@onready var tween

func _ready():
texture = load("res://Player/Sprites/Player.png")

tween = create_tween()
tween.tween_property(self, "modulate.a", 0, 0.25)
tween.set_trans(Tween.TRANS_QUART)

This in itself works perfectly fine and delivers the desired effect.

However, I want to change the color of the texture at the same time using a shader.

shader_type canvas_item;

uniform bool whiten = true;
uniform float mix_weight = 1.0;

void fragment() {
	vec4 texture_color = texture(TEXTURE, UV);
	if (whiten) {
		vec3 white = vec3(1,1,1);
		vec3 whitened_texture_rgb = mix(texture_color.rgb, white, mix_weight);
		COLOR.rgb = whitened_texture_rgb;
		COLOR.a   = texture_color.a;
	} else {
		COLOR = texture_color;
	}
}

When this shader is loaded into the sprite, it does apply the white coloring effect to it but the fade from the tween does not appear to work anymore. I assume the alpha value, modulate:a, during the tweening does not actually get picked up by the texture_color.a in the shader script. And I just cannot figure out why. I’d highly appreciate some help!

Disclaimer: I got the code from a youtube video about character dash ghosts. And it seems simple enough for me to think I understand it all. But I am also very new to shaders and might be missing something trivial here.

Hey Nhayge. I am running into the same issue. I think I followed the same tutorial as you :smiley:

Did you manage to get the fade effect working with the shader?

Mel4rk | 2023-03-28 19:41

:bust_in_silhouette: Reply From: Mel4rk

I digged around a bit and found this issue on github that explains this behavior.

So to get this working, I needed to change one line in the shader.

shader_type canvas_item;

uniform bool whiten = false;
uniform float mix_weight = 1.0;

void fragment() {
	vec4 texture_color = texture(TEXTURE,UV);
	if (whiten) {
		vec3 white = vec3(1,1,1);
		vec3 whitened_texture_rgb = mix(texture_color.rgb, white, mix_weight);
		COLOR = vec4(whitened_texture_rgb.rgb, COLOR.a);
	} else {
		COLOR = texture_color;
	}
}

The magic line was this
COLOR = vec4(whitened_texture_rgb.rgb, COLOR.a);

Setting the COLOR to the vec4 with the COLOR.a already included worked for me

EDIT: I also saw you only passed whitened_texture_rgb. At first I thought it was only me, but then I saw you did it as well. I guess it came like that from the tutorial. If you look closely at my code snippet, you will see I added whitened_texture_rgb.rgb. The .rgb seems to be missing as well from the initial code.

Hope it helps

1 Like