Shader smooth transition
Asked Answered
R

7

0

Hey! I was trying shaders for the first time because I wanted to know how to invert the colors of my game.
The approach I came up with was including a ColorRect node to my HUD and then adding a material shader with the following code:

shader_type canvas_item;
render_mode unshaded;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture;

void fragment() {
	vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgba;
	c.rgb = 1.0 - c.rgb;
	COLOR = c;
}

That worked fine, but the change happens instantly and I don't quite like the sudden result. For that reason, I searched how to make a smooth transition with shaders and I found the smoothstep function, but when using it I don't see any changes. My idea was to smoothly change the alpha value making the shader visible. Like this:

c.a = smoothstep(0.0, 1.0, c.a);

Anyone that knows about this more than me could help? Thanks!

Rabia answered 12/1 at 0:52 Comment(0)
I
0

Rabia Linearly interpolate between two colors using some animated parameter. You can use either a custom uniform or built in TIME:

COLOR.rgb = mix(c.rgb, 1.0-c.rgb, clamp(TIME, 0.0, 1.0));
Ideal answered 12/1 at 2:48 Comment(0)
R
0

Ideal Okay, thanks! So now my shader code looks like

shader_type canvas_item;
render_mode unshaded;

uniform sampler2D SCREEN_TEXTURE : hint_screen_texture;

void fragment() {
	vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgba;

	COLOR.rgb = mix(c.rgb, 1.0 - c.rgb, clamp(TIME, 0.0, 1.0));
}

which seems to be what I wanted, but I've realized that maybe the problem was how I implemented it from the script.
In my HUD scene script I have, in essence, something along this lines:

if (condition):
	$InverseColor.visible = true

With $InverseColor being the ColorRect node. Having it this way is maybe why I doesn't notice the smooth transition.
But how could I do it then? It's necessary that the color change due to the shader occurs whenever the condition is true.

Rabia answered 12/1 at 10:39 Comment(0)
I
0

Rabia In shader, instead of TIME use a custom uniform as the interpolation parameter. Whenever you need a transition launch a tween from script that will animate that uniform going gradually from 0 to 1 (or in reverse).

Ideal answered 12/1 at 10:43 Comment(0)
R
0

Okay, I'll try that.

Rabia answered 12/1 at 10:45 Comment(0)
R
0

Ideal Sorry, I've been trying but I don't really know how to do that because I haven't use tweens before.
I searched in the documentation and declared a tween variable when the condition is true and then apply the change. I believe I'm close but I doesn't quite get it, I end up having this:

if (condition):
	invert_colors()

func invert_colors() -> void:
	var tween : Tween = create_tween()
	tween.tween_property($InverseColor, "interpolation", 1.0, 1)

In shader, I declared the interpolation parameter as uniform float interpolation : hint_range(0.0, 1.0) = 0.0; and used instead of TIME.

Thanks for your patience.

Rabia answered 12/1 at 11:33 Comment(0)
I
0

Rabia You need to tween it as material's shader parameter:

$InverseColor.material.set_shader_parameter("interpolation", 0.0) #start value
tween.tween_property($InverseColor.material, "shader_parameter/interpolation", 1.0, 1.0)
Ideal answered 12/1 at 12:27 Comment(0)
R
0

Ideal Now it works! Thank you very much.

Rabia answered 12/1 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.