Skip to content

Instantly share code, notes, and snippets.

@ChrisPritchard
Created October 11, 2025 04:16
Show Gist options
  • Select an option

  • Save ChrisPritchard/81a994b5a909fa425f5e975a3349ec6d to your computer and use it in GitHub Desktop.

Select an option

Save ChrisPritchard/81a994b5a909fa425f5e975a3349ec6d to your computer and use it in GitHub Desktop.
A godot shader that generates a moving circuit like pattern.
shader_type canvas_item;
uniform float aspect_ratio: hint_range(0.1, 1.9, 0.1) = 1.0;
group_uniforms line_characteristics;
uniform float line_width: hint_range(0.001, 0.1) = 0.01;
uniform int segment_count: hint_range(0, 10, 1) = 5;
uniform float segment_length: hint_range(0.1, 1.0, 0.01) = 0.2;
uniform float tail_lag: hint_range(0.1, 1.0, 0.01) = 0.4;
uniform vec4 line_colour: source_color = vec4(1.0, 1.0, 0, 1.0);
uniform float head_size_multiplier: hint_range(0.0, 10.0, 0.1) = 5.0;
group_uniforms spawn_characteristics;
uniform int line_count: hint_range(0, 200, 1) = 10;
uniform float line_lifetime: hint_range(0.5, 10.0) = 5.0;
uniform vec2 top_left_margin = vec2(0.2, 0.2);
uniform vec2 bottom_right_margin = vec2(0.8, 0.8);
float rand(int seed) {
float fseed = float(seed);
return fract(sin(dot(vec2(fseed, fseed * 0.66), vec2(12.9898, 78.233))) * 43758.5453);
}
float get_start(int seed) {
float rand_dir = floor(rand(seed) * 4.0);
return rand_dir * radians(90);
}
float get_turn(int seed, float initial, float angle_size) {
int rand_dir = int(floor(rand(seed) * 2.0));
if(rand_dir == 0)
return initial + angle_size;
else
return initial - angle_size;
}
float get_segment_intensity(
vec2 start, vec2 end,
vec2 segment_process_range,
float progress,
vec2 uv) {
vec2 segment_vec = end - start;
vec2 pixel_vec_segment = uv - start;
float t = clamp(dot(pixel_vec_segment, segment_vec) / (segment_length * segment_length), 0.0, 1.0);
vec2 closest_point = start + t * segment_vec;
float distance_to_segment = distance(uv, closest_point);
float point_progress = mix(segment_process_range.x, segment_process_range.y, t);
if (point_progress <= min(progress, 1.0 - tail_lag) && point_progress >= progress - tail_lag) {
float intensity = 1.0 - smoothstep(0.0, line_width, distance_to_segment);
float lit_progress = (point_progress - (progress - tail_lag)) / tail_lag;
return intensity * lit_progress;
}
return 0.0;
}
float render_line(float time, vec2 uv) {
float local_time = time / line_lifetime;
int seed = int(floor(local_time));
float progress = fract(local_time);
float line_intensity = 0.0;
vec2 last_point = vec2(rand(seed), rand(seed + 1));
last_point = top_left_margin + last_point * (bottom_right_margin - top_left_margin);
float last_angle = get_start(seed);
vec2 last_dir = vec2(cos(last_angle), sin(last_angle));
float last_progress = 0.0;
for(int j = 0; j < segment_count; j++) {
vec2 segment_bounds = vec2(last_progress, last_progress + (1.0-tail_lag)/float(segment_count));
last_progress = segment_bounds.y;
if(progress < segment_bounds.x)
break;
vec2 next_point = last_point + last_dir * segment_length;
float next_angle = get_turn(seed + j, last_angle, radians(45));
vec2 next_dir = vec2(cos(next_angle), sin(next_angle));
line_intensity = max(line_intensity, get_segment_intensity(
last_point, next_point,
segment_bounds,
progress,
uv));
if(progress >= segment_bounds.x && progress <= segment_bounds.y) {
vec2 head_pos = last_point + last_dir * segment_length * (progress - segment_bounds.x) / (segment_bounds.y - segment_bounds.x);;
float head_glow = 1.0 - smoothstep(0.0, line_width * head_size_multiplier, distance(uv, head_pos));
line_intensity = max(line_intensity, head_glow);
}
last_point = next_point;
last_angle = next_angle;
last_dir = next_dir;
}
return line_intensity;
}
void fragment() {
vec4 under_colour = COLOR;
vec2 centered = UV - vec2(0.5);
centered.x *= aspect_ratio;
vec2 uv = centered + vec2(0.5);
float line_intensity = 0.0;
for(int i = 0; i < line_count; i++) {
float offset = float(i) * 123.123;
line_intensity = max(line_intensity, render_line(TIME + offset, uv));
}
COLOR = mix(under_colour, line_colour, line_intensity * line_colour.a);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment