Files
portal/cloud_1.gdshader
T
2026-06-17 15:28:56 -07:00

110 lines
4.0 KiB
Plaintext

shader_type spatial;
render_mode unshaded, cull_disabled;
uniform float movement_Factor : hint_range(6.0,36.0) = 6.0;
uniform float rotation_speed : hint_range(-5.0, 5.0) = 1.0;
uniform float scroll_speed : hint_range(-5.0, 5.0) = 0.5;
uniform float vertex_displacement : hint_range(0.0, 5.0) = 0.2;
uniform float inner_fade = 0.2;
uniform float outer_fade = 0.8;
uniform vec4 color : source_color = vec4(1.0);
uniform vec4 spiral_color : source_color = vec4(0.8, 0.8, 0.8, 1.0);
uniform float spiral_turns : hint_range(1.0, 48.0) = 1.0;
uniform float spiral_swirl : hint_range(6.0, 360.0) = 6.0;
uniform float spiral_width : hint_range(0.02, 0.5) = 0.047;
uniform float spiral_strands : hint_range(1.0, 2.0) = 1.0;
uniform sampler2D noise_tex : source_color;
uniform sampler2D cloud_tex : source_color;
// ── Shared helpers ──────────────────────────────────────────────────────
// Rotate UV.x around the cylinder and scroll UV.y over time.
vec2 rotate_and_scroll(vec2 uv, float t) {
float angle = uv.x * (2.0 * PI);
angle += t * rotation_speed;
uv.x = angle / (2.0 * PI);
uv.y += t * scroll_speed;
return uv;
}
// Noise UV used for both distortion and displacement.
vec2 noise_uv(vec2 uv, float t) {
return uv * 3.0 + vec2(t * 0.2, t * 0.15);
}
// Sample noise and apply distortion offset to the rotated UVs.
vec2 distort_uv(vec2 rotated_uv, vec2 raw_uv, float t, float distortion_amount) {
float n = texture(noise_tex, noise_uv(raw_uv, t)).r;
return rotated_uv + (n - 0.5) * distortion_amount;
}
// Full cloud colour at a given UV, including noise distortion.
vec4 sample_cloud(vec2 uv, float t) {
float distortion_amount = (sin(t * 0.1) * 0.5 + 0.5) / movement_Factor;
vec2 ruv = rotate_and_scroll(uv, t);
vec2 final_uv = distort_uv(ruv, uv, t, distortion_amount);
return texture(cloud_tex, final_uv);
}
// Spiral mask in tunnel UV space. Uses the same motion params as the clouds.
// `spiral_strands` lets you blend from a single helix (1) to dual helix (2).
float spiral_mask(vec2 uv, float t) {
vec2 moved_uv = rotate_and_scroll(uv, t);
float u = fract(moved_uv.x);
float v = fract(moved_uv.y);
// Primary helix.
float helix_a = fract(u * spiral_turns - v * spiral_swirl);
float dist_a = abs(helix_a - 0.5);
float half_w = spiral_width * 0.5;
float thread_a = 1.0 - smoothstep(half_w, half_w + 0.06, dist_a);
// Optional opposing helix for barber-pole look.
float helix_b = fract(u * spiral_turns + v * spiral_swirl + 0.5);
float dist_b = abs(helix_b - 0.5);
float thread_b = 1.0 - smoothstep(half_w, half_w + 0.06, dist_b);
float use_second = clamp(spiral_strands - 1.0, 0.0, 1.0);
return max(thread_a, thread_b * use_second);
}
vec3 apply_spiral_color(vec2 uv, float t, vec3 base_rgb) {
float mask = spiral_mask(uv, t) * spiral_color.a;
return mix(base_rgb, spiral_color.rgb, mask);
}
// ── Vertex & Fragment ───────────────────────────────────────────────────
void vertex() {
float t = TIME + 30.0;
// Sample the full cloud pattern — same logic as fragment()
vec4 cloud = sample_cloud(UV, t);
// Also grab raw noise for high-frequency displacement
float n = texture(noise_tex, noise_uv(UV, t)).r;
// Combine cloud luminance with noise for displacement
float luminance = dot(cloud.rgb, vec3(0.299, 0.587, 0.114));
float disp = ((luminance + n) * 0.5 - 0.5) * vertex_displacement;
VERTEX += NORMAL * disp;
}
void fragment() {
float t = TIME + 30.0;
// Sample cloud using the shared pipeline
vec4 col = sample_cloud(UV, t);
// Radial fade (soft edges)
float radius = length(UV - vec2(0.5));
float fade = smoothstep(inner_fade, outer_fade, radius);
col.rgb *= color.rgb;
col.rgb = apply_spiral_color(UV, t, col.rgb);
col.a *= fade;
ALBEDO = col.rgb;
ALPHA = col.a;
}