Files
zfxaction25/DonkeysAndDroids.Godot/background.gdshader
2026-04-19 00:43:27 +02:00

120 lines
4.4 KiB
Plaintext

shader_type canvas_item;
uniform vec4 color_a : source_color = vec4(0.05, 0.06, 0.10, 1.0); // base
uniform vec4 color_b : source_color = vec4(0.07, 0.10, 0.18, 1.0); // mid
uniform vec4 color_c : source_color = vec4(0.10, 0.16, 0.28, 1.0); // accent
// Swirl controls
uniform float swirl_strength = 0.8; // base twist near center
uniform float swirl_radius = 1.6; // falloff (bigger = more spread)
uniform float swirl_speed = 0.2; // base animation speed
// Secondary swirl "eddies"
uniform float secondary_swirl_strength = 0.5;
uniform float secondary_swirl_radius = 2.4;
uniform vec2 secondary_swirl_center = vec2(0.2, 0.8); // in UV space
// Extra flavor
uniform float time_scale = 1.0; // global time multiplier
uniform float vignette_strength = 0.6; // darken edges
uniform float grain_amount = 0.006; // tiny grain to fight banding
// Noise texture (fbm perlin)
uniform sampler2D noise_tex;
uniform float noise_uv_scale = 2.5; // tiling of noise
uniform float noise_distort_amount = 0.035; // how much noise warps UVs
uniform float swirl_noise_amount = 0.6; // how much noise affects swirl angle
uniform float swirl_noise_scale = 1.8; // scale for angle noise sampling
uniform float accent_noise_amount = 0.1; // how much noise modulates center accent
vec2 map_uv_wrapping(vec2 uv, int mode) {
switch (mode) {
case 1:
uv = clamp(uv, 0.0, 1.0);
break;
case 2:
uv = fract(uv / 2.0);
uv = min(uv, 1.0 - uv) * 2.0;
break;
case 3:
uv = clamp(abs(uv), -1.0, 1.0);
break;
}
return uv;
}
vec4 textureWrapped(sampler2D samp, vec2 uv, int mode) {
uv = map_uv_wrapping(uv, mode);
return textureLod(samp, uv, 0);
//return texture(samp, uv);
}
void fragment()
{
float t = TIME * time_scale;
// Keep a copy of original UV for some effects
vec2 base_uv = UV;
// === Noise-based UV distortion =======================================
vec2 noise_uv = base_uv * noise_uv_scale + vec2(t * 0.03, -t * 0.025);
vec3 noise_sample = texture(noise_tex, noise_uv).rgb; // fbm: smooth 0-1
// Use red/green channels to gently distort UVs
vec2 uv = base_uv + (noise_sample.rg - 0.5) * noise_distort_amount;
// === Swirl fields =====================================================
// Main swirl around screen center
vec2 center = vec2(0.5, 0.5);
vec2 pos = uv - center;
float r = length(pos); // distance from center
float angle = atan(pos.y, pos.x); // original polar angle
// Primary swirl: fades with radius and pulses over time
float base_swirl = swirl_strength
* exp(-r * swirl_radius)
* sin(t * swirl_speed + r * 6.28318);
// Secondary swirl "eddy" region somewhere else on the screen
vec2 pos2 = uv - secondary_swirl_center;
float r2 = length(pos2);
float secondary_swirl = secondary_swirl_strength
* exp(-r2 * secondary_swirl_radius)
* sin(t * swirl_speed * 0.7 + r2 * 6.28318 * 0.5);
// Noise-driven swirl angle perturbation (local turbulence)
vec2 swirl_noise_uv = base_uv * swirl_noise_scale + vec2(-t * 0.02, t * 0.015);
float swirl_noise = (textureWrapped(noise_tex, swirl_noise_uv, 2).r) * swirl_noise_amount;
angle += base_swirl + secondary_swirl + swirl_noise;
vec2 swirled = center + vec2(cos(angle), sin(angle)) * r;
// === Color gradient & accent =========================================
// Vertical gradient (using swirled Y)
float g = clamp(swirled.y, 0.0, 1.0);
vec4 col = mix(color_a, color_b, g);
// Accent towards center, modulated slightly by noise
float accent_factor = smoothstep(0.2, 0.8, 1.0 - r);
float accent_noise = (noise_sample.b - 0.5) * accent_noise_amount;
accent_factor = clamp(accent_factor + accent_noise, 0.0, 1.0);
col = mix(col, color_c, accent_factor * 0.6);
// === Vignette =========================================================
float vignette = smoothstep(0, 1.0, r);
float vignette_mul = mix(1.0, 1.0 - vignette_strength, vignette);
col.rgb *= vignette_mul;
// === High-frequency grain to kill banding ============================
// Use analytic noise for real high-frequency variation
float grain = fract(
sin(dot(base_uv * 128.0 + vec2(t * 0.5, -t * 0.35),
vec2(12.9898, 78.233)))
* 43758.5453
);
col.rgb += (grain - 0.5) * grain_amount;
COLOR = col;
}