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!

  • xyz replied to this.

    Zerfex 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));

      xyz 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.

      • xyz replied to this.

        Zerfex 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).

          xyz 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.

          • xyz replied to this.

            Zerfex 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)