OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / addons / sky3d_extended / shaders / cloud_cirrus.gdshader

72 lines · gdshader ref:
// 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;
}