Grid Shader

A grid shader. This shader can do impressive effects such as ripple and implosion. 

You can use it like that:

# — Ripple —
func trigger_ripple_effect(pos: Vector2, ripple_speed := 1200, thickness := 300, strength := 380):
    if not is_instance_valid(background_shader_material): return
    
    var current_time = Time.get_ticks_msec() / 1000.0
    
    background_shader_material.set_shader_parameter(“ripple_speed”, ripple_speed)
    background_shader_material.set_shader_parameter(“ripple_thickness”, thickness)
    background_shader_material.set_shader_parameter(“ripple_peak_strength”, strength)
    
    ripple_origins.push_front(pos)
    ripple_start_times.push_front(current_time)
 
    if ripple_origins.size() > MAX_PULSES:
        ripple_origins.pop_back()
        ripple_start_times.pop_back()
        
    background_shader_material.set_shader_parameter(“active_pulse_count”, ripple_origins.size())
    background_shader_material.set_shader_parameter(“ripple_origin_world”, ripple_origins)
    background_shader_material.set_shader_parameter(“ripple_start_time”, ripple_start_times)

# — Implosion —
func trigger_implosion_effect(pos: Vector2, speed := 1000, thickness := 800, strength := 900):
    if not is_instance_valid(background_shader_material): return
    
    var current_time = Time.get_ticks_msec() / 1000.0
    
    background_shader_material.set_shader_parameter(“implosion_speed”, speed)
    background_shader_material.set_shader_parameter(“implosion_thickness”, thickness)
    background_shader_material.set_shader_parameter(“implosion_peak_strength”, strength)
    
    implosion_origins.push_front(pos)
    implosion_start_times.push_front(current_time)
    
    if implosion_origins.size() > MAX_PULSES:
        implosion_origins.pop_back()
        implosion_start_times.pop_back()
        
    background_shader_material.set_shader_parameter(“active_pulse_count”, max(ripple_origins.size(), implosion_origins.size()))
    background_shader_material.set_shader_parameter(“implosion_origin_world”, implosion_origins)
    background_shader_material.set_shader_parameter(“implosion_start_time”, implosion_start_times)

You also need to set up its world.

Shader code
// Made by ZiexDev.

shader_type canvas_item;

// === GRID CONFIG ===
uniform vec4 grid_color : source_color = vec4(0.04, 0.05, 0.12, 1.0);
uniform float grid_spacing = 50.0;
uniform float line_thickness = 1.0;

// === GRID WORLD POS/BOUNDS ===
uniform vec2 grid_visual_world_pos = vec2(0.0, 0.0);
uniform vec2 grid_visual_world_size = vec2(1920.0, 1080.0);
uniform float global_time_sec;

// === MAX PULSES ===
const int MAX_PULSES = 3;
uniform int active_pulse_count;

// === PULSE DATA ===
uniform vec2 ripple_origin_world[MAX_PULSES];
uniform float ripple_start_time[MAX_PULSES];

uniform vec2 implosion_origin_world[MAX_PULSES];
uniform float implosion_start_time[MAX_PULSES];

// === SHARED PULSE CONFIG ===
uniform float ripple_speed = 1200.0;
uniform float ripple_thickness = 70.0;
uniform float ripple_peak_strength = 45.0;

uniform float implosion_speed = 1000.0;
uniform float implosion_thickness = 80.0;
uniform float implosion_peak_strength = 60.0;

void fragment() {
	vec2 world_pos = grid_visual_world_pos + (UV * grid_visual_world_size);
	vec2 displacement = vec2(0.0);
	float effect_strength = 0.0;

	for (int i = 0; i < MAX_PULSES; i++) {
		if (i >= active_pulse_count) break;

		// === RIPPLE ===
		float dt_ripple = global_time_sec - ripple_start_time[i];
		if (dt_ripple > 0.0) {
			float dist = distance(world_pos, ripple_origin_world[i]);
			float wave_front = dt_ripple * ripple_speed;

			if (dist >= (wave_front - ripple_thickness) && dist <= wave_front) {
				float t = (dist - (wave_front - ripple_thickness)) / ripple_thickness;
				float strength = (t * t) * (1.0 - t);
				float fade = max(1.0 - dist / 1500.0, 0.0);
				vec2 dir = normalize(world_pos - ripple_origin_world[i]);
				displacement += dir * (strength * ripple_peak_strength * fade);
				effect_strength = max(effect_strength, strength * fade);
			}
		}

		// === IMPLOSION ===
		float dt_impl = global_time_sec - implosion_start_time[i];
		if (dt_impl > 0.0) {
			float dist = distance(world_pos, implosion_origin_world[i]);
			float wave_front = dt_impl * implosion_speed;

			if (dist >= (wave_front - implosion_thickness) && dist <= wave_front) {
				float t = (dist - (wave_front - implosion_thickness)) / implosion_thickness;
				float strength = (t * t) * (1.0 - t);
				float fade = max(1.0 - dist / 1800.0, 0.0);
				vec2 dir = normalize(world_pos - implosion_origin_world[i]);
				displacement -= dir * (strength * implosion_peak_strength * fade);
				effect_strength = max(effect_strength, strength * fade);
			}
		}
	}
	
	vec2 grid_coord = world_pos + displacement;
	float x_mod = mod(grid_coord.x, grid_spacing);
	float y_mod = mod(grid_coord.y, grid_spacing);
	
	float alpha = 0.0;
	if (x_mod < line_thickness || grid_spacing - x_mod < line_thickness ||
	    y_mod < line_thickness || grid_spacing - y_mod < line_thickness) {
		alpha = 1.0;
	}

	alpha *= (1.0 - (effect_strength * effect_strength));
	alpha = clamp(alpha, 0.0, 1.0);
	vec4 color = grid_color * (1.0 + effect_strength * 3.0);

	COLOR = mix(vec4(0.0), color, alpha);
}

// Made by ZiexDev.
Live Preview
Tags
action grid
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.

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments