Randoloot/scripts/game/wormhole_vortex.gdshader
2026-10-17 14:28:20 +02:00

63 lines
2.7 KiB
Plaintext

shader_type canvas_item;
render_mode unshaded;
uniform float elapsed = 0.0;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
return mix(mix(hash(i), hash(i + vec2(1, 0)), f.x),
mix(hash(i + vec2(0, 1)), hash(i + vec2(1, 1)), f.x), f.y);
}
float turbulence(vec2 p) {
return noise(p) * 0.55 + noise(p * 2.07) * 0.28 + noise(p * 4.13) * 0.17;
}
void fragment() {
vec2 p = (UV - 0.5) * 2.0;
float r = length(p);
float a = atan(p.y, p.x);
float t = elapsed;
float reveal = smoothstep(0.0, 1.2, t);
float pulse = 1.0 + 0.012 * sin(t * 2.1);
float radius = r / pulse;
// Use circular coordinates for seamless turbulent filaments.
float twist = a + 2.6 * log(max(radius, 0.035)) - t * 0.65;
vec2 flow = vec2(cos(twist), sin(twist));
float clouds = turbulence(flow * 5.0 + vec2(radius * 13.0, -t * 0.3));
float filaments = pow(max(0.0, sin(twist * 7.0 + clouds * 5.0)), 5.0);
float disc = exp(-pow((radius - 0.46) / 0.125, 2.0));
float rim_r = 0.432 + 0.008 * sin(a * 6.0 - t * 1.4) + (clouds - 0.5) * 0.017;
float rim = exp(-abs(radius - rim_r) * 170.0);
float bloom = exp(-abs(radius - rim_r) * 25.0);
float halo = exp(-pow(radius / 0.66, 4.0));
vec3 cyan = vec3(0.16, 0.73, 1.0);
vec3 violet = vec3(0.40, 0.15, 0.93);
vec3 tint = mix(violet, cyan, 0.5 + 0.5 * sin(twist * 2.0 + t * 0.3));
vec3 color = tint * disc * (0.18 + clouds * 0.55 + filaments * 0.85);
color += cyan * bloom * 0.3 + vec3(0.63, 0.92, 1.0) * rim * 1.5;
color += violet * halo * 0.055;
// A dark throat with contracting spiral bands suggests a deep tunnel.
float inside = 1.0 - smoothstep(0.37, 0.425, radius);
float depth = -log(max(radius / 0.425, 0.015));
float tunnel = pow(max(0.0, sin(depth * 16.0 - t * 3.3 + a * 2.0)), 12.0);
float throat_fade = smoothstep(0.035, 0.3, radius);
vec3 throat = vec3(0.003, 0.006, 0.026);
throat += mix(violet, cyan, radius / 0.425) * tunnel * throat_fade * 0.22;
throat += cyan * pow(max(0.0, sin(twist * 5.0 + clouds * 2.0)), 14.0) * throat_fade * 0.11;
color = mix(color, throat, inside);
// Orbiting pinpoints and their short luminous trails, outside the event horizon.
float orbit_angle = a - t * 0.24;
vec2 orbit = vec2(cos(orbit_angle), sin(orbit_angle)) * radius * 43.0;
float sparks = pow(turbulence(orbit), 18.0) * 32.0;
sparks *= smoothstep(0.45, 0.52, radius) * (1.0 - smoothstep(0.62, 0.86, radius));
color += vec3(0.56, 0.83, 1.0) * sparks;
float alpha = max(inside, max(disc * (0.5 + clouds * 0.5), bloom * 0.8));
alpha = max(alpha, halo * 0.1 + sparks);
alpha *= (1.0 - smoothstep(0.84, 0.98, radius)) * reveal;
COLOR = vec4(color, clamp(alpha, 0.0, 1.0));
}