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?
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;
}
Your uniform float dissolve_value is static but not constant, its uniform
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
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)
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 But maybe thats what you want, idk