120 lines
4.4 KiB
Plaintext
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;
|
|
}
|