Blast Wall

This deformation fragment shader simulates a shockwave with (ridiculous) chromatic aberration. Use this shader as a material in a canvas object (Sprite, ColorRect, etc.) on top of a scene (using a CanvasLayer or a back buffer) to apply the effect on the whole screen. This may also work on sprite content (use TEXTURE and UV instead of SCREEN_TEXTURE and SCREEN_UV).

Parameters are:

  • center : Center of the explosion in screen coordinate (be aware that you’ll need to scale the coordinate using (viewport_size / container_size) and revert the Y position using viewport_size.y – center.y)
  • force : Explosion force. Determines the deformation strenght.
  • size : Size of the blast wave.
  • blast : Size of the blast.
  • direction : 2D vector determining the direction of the blast.
  • aperture : Opening angle of the blast (in radians).
  • red_offset, green_offset, blue_offset : Chromatic aberration ratio. 1 = no aberration.

Of course, this shader is meant to be animated (see screenshot).

Update : Using FRAGCOORD instead to avoid deformation induced by container and/or screen ratio.

Shader code
shader_type canvas_item;

uniform vec2 center;

uniform float force;
uniform float size;
uniform float blast;

uniform vec2 direction;
uniform float aperture : hint_range(0.0, 3.141516, 0.001);

uniform float red_offset : hint_range(0.0, 2.0, 0.001);
uniform float green_offset : hint_range(0.0, 2.0, 0.001);
uniform float blue_offset : hint_range(0.0, 2.0, 0.001);

vec2 scale(vec2 coord, vec2 scale) {
	return coord * scale;

void fragment() {
	float dist = distance(FRAGCOORD.xy, center);
	vec2 norm = normalize(FRAGCOORD.xy - center);

	float angle = acos(dot(normalize(vec2(-direction.x, direction.y)), -norm));
	float mask = cos((angle * 1.5707963268) / (aperture + .00001)) * step(angle, aperture) * force;

	float blast_mask = smoothstep(blast - size/2., blast, dist);
	float total_size = blast + (size / 2.);

	vec3 offsets = vec3(red_offset, green_offset, blue_offset);
	vec3 forces = offsets * mask * blast_mask;
	vec3 raw_eases = total_size * offsets;
	raw_eases = clamp(dist / raw_eases, vec3(0.), vec3(1.));
	vec3 easings = pow(raw_eases, forces);
	vec3 deforms = easings * dist;

	COLOR = vec4(
		texture(SCREEN_TEXTURE, scale(center + (deforms.r * norm), SCREEN_PIXEL_SIZE)).r,
		texture(SCREEN_TEXTURE, scale(center + (deforms.g * norm), SCREEN_PIXEL_SIZE)).g,
		texture(SCREEN_TEXTURE, scale(center + (deforms.b * norm), SCREEN_PIXEL_SIZE)).b,
blast, deformation
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

Water-like wavelet

(Almost) Invisible Character

Shield with impact waves

Related shaders

Brick/tiled wall

Wall of Glyphs

Notify of

Newest Most Voted
Inline Feedbacks
View all comments
7 months ago

This is awesome looking. Is there any chance you could post what the code should look like for use on a SPRITE in GD4?