How to create a simple dissolve shader

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

I am learning about shaders and want to implement a simple dissolve shader in my 2D game that looks like this:

This is the first step of implementing a more complex shader found here.

So far, all I’ve been able to come up with is this:

shader_type canvas_item;

// DISSOLVE SHADER

uniform sampler2D noise_img : hint_albedo;
uniform float dissolve_value : hint_range(0,1);

void fragment(){

	vec4 main_texture = texture(TEXTURE, UV);  // TEXTURE is texture of the sprite the shader is attached to
	vec4 noise_texture = texture(noise_img, SCREEN_UV);
	// modify the main texture's alpha using the noise texture
    main_texture.a *= floor(dissolve_value + min(0.99, noise_texture.x));
	COLOR = main_texture;
}

I am using this noise image:

For dissolve_value = 0.7, I get:

enter image description here

It seems like I am on the right track, but I have a few questions.

First, am I really on the right track?

Second, how does one go about getting the effect to progress over time? The effect should dissolve the sprite over time, but right now, because dissolve_value is static, the effect is just static. How do you add a temporal dimension into the shader?

Third, how do you start and stop shaders? I want to initiate this effect on a node when the node’s enter_death() method is called. How does one go about initiating a shader, and, later, stopping or removing it?

:bust_in_silhouette: Reply From: LeoKyle

got an idea from your code. i am new to shaders but i tried with abs(sin(TIME)) to test your code and wacth it fade and out and in again 4 testing pruposes.

it wont help in the end … but is somthing u can use.

shader_type canvas_item;

// DISSOLVE SHADER

uniform sampler2D noise_img : hint_albedo;
//uniform float dissolve_value : hint_range(0,1);

void fragment(){

    vec4 main_texture = texture(TEXTURE, UV);  // TEXTURE is texture of the sprite the shader is attached to
    vec4 noise_texture = texture(noise_img, SCREEN_UV);
    // modify the main texture's alpha using the noise texture
    main_texture.a *= floor( abs(sin(TIME)) + min(0.99, noise_texture.x));
    COLOR = main_texture;
}
:bust_in_silhouette: Reply From: splite

You can look at my implementation of Dissolve shader at GitHub - kondelik/Godot-3.1-Dissolve-shader-with-OpenSimplexNoise: Godot 3.1 Dissolve shader with OpenSimplexNoise (using godot 3.1 alpha2, but only for OpenSimplexNoise, you can use shader in older godot, but you have to provide your own noise texture)

  1. You are on right track :wink:

  2. Your uniform float dissolve_value is static but not constant, its uniform :slight_smile:

You can set it via $your_sprite.material.set_shader_param("dissolve_value", value) (doc) - everything else is just timing issue.

# NOT TESTED
var _time = 0.0
var _is_dissolving = false
var is_dead = false setget _set_is_dead

func _process(delta):
  if (_is_dissolving):
    _time += delta;
    $your_sprite.material.set_shader_param("dissolve_value", _time)
    // or for slower dissolving something like
    // $your_sprite.material.set_shader_param("dissolve_value", _time / 5.0)
    if(_time > ???):
      _remove_or_something()
      _is_dissolving = false

func _set_is_dead(value):
  is_dead = value
  if (value):
    enter_death()

func enter_death():
  _is_dissolving = true

func _remove_or_something():
  pass
  1. You can replace shaders by replacing whole material like $your_sprite.material = xy.new() (doc) (or $your_sprite.material = preload("res://path/to/your/material.material"); depends on your logic)

BUT - your target should be “THE ONE BIG CanvasItem shader that can handle anything”, not “lots of small specialised shaders”. Not becouse swapping shaders is performance costly (no, it is not), but becouse its not a simple task (afaik not even possible without multiple viewports - i can be wrong with this) to chain your CanvasItemShaders. And when you wrote one shader for dissolving and second for moving UV to handle different clothing, sooner or later you will need ‘dissolve alternate clothing’ - and you are out of luck, you can only dissolve or move UV… (Sry for my engrish, hope you understand what i am trying to say)

  1. i noticed you are using vec4 noise_texture = texture(noise_img, SCREEN_UV); - really SCREEN_UV? One line before you are using UV, so, if your sprite will move (rotate or scale or translate) across screen, your dissolve will be… Lets say interesting :slight_smile: But maybe thats what you want, idk :slight_smile:

Have fun!