// Cirrus cloud layer - thin wispy streaks at high altitude
// Abs-noise fBM with curl warp and UV stretch
shader_type spatial;
render_mode blend_mix, depth_draw_never, cull_front, unshaded;
#include "noise.gdshaderinc"
uniform float curve_strength : hint_range(0.0, 0.01) = 0.003;
uniform float plane_half_size : hint_range(100.0, 100000.0) = 50000.0;
uniform float coverage : hint_range(0.0, 1.0) = 0.25;
uniform vec2 wind_offset = vec2(0.0);
uniform vec3 sun_direction = vec3(0.0, 1.0, 0.0);
uniform vec3 sun_color : source_color = vec3(1.0);
uniform float sun_energy = 1.0;
uniform vec3 moon_direction = vec3(0.0, -1.0, 0.0);
uniform float moon_energy = 0.0;
uniform float uv_stretch : hint_range(1.0, 8.0) = 5.0;
uniform float curl_strength : hint_range(0.0, 2.0) = 0.6;
uniform int octaves : hint_range(2, 8) = 4;
uniform float persistence : hint_range(0.2, 0.7) = 0.45;
uniform float lacunarity : hint_range(1.5, 4.0) = 2.5;
void vertex() {
float dist_from_center = length(VERTEX.xz) / plane_half_size;
float curve = dist_from_center * dist_from_center * curve_strength * plane_half_size;
VERTEX.y -= curve;
}
void fragment() {
// Stretch UVs along wind direction for wispy character
vec2 uv = UV * vec2(uv_stretch, 1.0) + wind_offset;
// 2D curl noise warp — divergence-free swirling distortion
vec2 curl_pos = uv * 2.0 + wind_offset * 0.3;
float c_eps = 0.01;
float cdx = value_noise(curl_pos + vec2(c_eps, 0.0))
- value_noise(curl_pos - vec2(c_eps, 0.0));
float cdy = value_noise(curl_pos + vec2(0.0, c_eps))
- value_noise(curl_pos - vec2(0.0, c_eps));
vec2 curl = vec2(cdy, -cdx) / (2.0 * c_eps);
uv += curl * curl_strength;
// Abs-noise fBM — sharp filaments
float f = 0.0;
float amp = 0.5;
float freq = 1.0;
for (int i = 0; i < octaves; i++) {
f += amp * abs(value_noise(uv * freq) * 2.0 - 1.0);
amp *= persistence;
freq *= lacunarity;
}
float density = smoothstep(1.0 - coverage - 0.1, 1.0 - coverage + 0.2, f) * 0.9;
// Sun contribution fades naturally via sun_energy at night
vec3 sun_lit = sun_color * 0.9 * sun_energy;
// Moon contribution: boost for visibility on clouds
float moon_boost = moon_energy * 5.0;
vec3 moon_lit = vec3(0.7, 0.8, 0.95) * moon_boost * 0.4;
// Night ambient
float night_blend = clamp(1.0 - sun_direction.y * 3.0, 0.0, 1.0);
vec3 night_ambient = vec3(0.04, 0.045, 0.07);
vec3 final_color = sun_lit + moon_lit + night_ambient * night_blend;
// Edge fade: start earlier (0.7) for smooth horizon blending
float edge_dist = max(abs(UV.x - 0.5), abs(UV.y - 0.5)) * 2.0;
float final_alpha = density * (1.0 - smoothstep(0.7, 0.98, edge_dist));
if (final_alpha < 0.01) discard;
ALBEDO = final_color;
ALPHA = final_alpha;
}