Water-like wavelet

This effect can be applied to a ColorRect or any other canvas item. It will simulate a water wavelet. The effect itself is mostly translucent so it can be applied easily on top of anything.

However, it needs some information about its position and size in the viewport. Use the following script to set those uniforms right :

# "target" is the Canvas item which material contains the shader.

func set_shader_params() -> void:
	var viewport_size : Vector2 = get_viewport_rect().size
	var target_size : Vector2 = target.get_global_rect().size
	var target_size_uv : Vector2 = target_size / viewport_size
	var target_pos : Vector2 = target.get_global_rect().position
	var target_pos_uv : Vector2 = target_pos / viewport_size
	
	target.material.set_shader_param("screen_pos", target_pos_uv)
	target.material.set_shader_param("screen_size", target_size_uv)

The displayed example is driven by an animation player acting on the uniforms to change progression, thickness and wavelet factor.

Shader code
shader_type canvas_item;

uniform float progression : hint_range(0.0, 1.0) = 0.5;

uniform float fade : hint_range(0.0, 1.0) = 0.9;

uniform float thickness : hint_range(0.01, 1.0) = 0.1;

uniform float wavelet_factor : hint_range(.1, 4.) = 4.;

// In pixels.
uniform float deformation_length = 16;

uniform vec2 screen_pos;

uniform vec2 screen_size;

uniform vec4 tint : hint_color = vec4(.5, .5, .9, 1.);

const float PI = 3.1415926535897932384626433832795;

void fragment() {
	vec2 norm = normalize(UV - vec2(.5));
	float dist = distance(UV, vec2(.5)) * 2.;
	float prog = progression * (1. - thickness - 0.01);
	float distortion = clamp((dist - prog) / thickness, -1., 1.);
	distortion = mix(cos(distortion * (PI / wavelet_factor)), 0., step(0.99, abs(distortion)));
	vec2 def = distortion * deformation_length * SCREEN_PIXEL_SIZE;
	vec2 offset_vector = norm * def;
	vec2 target_id = screen_pos + ((UV + offset_vector) * screen_size);
	target_id.y = 1.0 - target_id.y;
	COLOR = mix(vec4(0.),
				vec4(texture(SCREEN_TEXTURE, target_id).rgb, mix(1.0, smoothstep(1., 0., (progression - fade) / (1. - fade)),
				step( fade, progression ))), step(0.01, distortion));
}
Tags
water, wave
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from CasualGarageCoder

Shield with impact waves

(Almost) Invisible Character

Swirl/Sink

Related shaders

Earthbound-like battle background shader w/scroll effect and palette cycling

HQ4X Shader (like in Emulators)

RotSprite-Like Algorithm for Cleaner Pixel Art Rotation

guest

0 Comments
Inline Feedbacks
View all comments