Cloud

Cloud

Shader loading...

View Source Code
// Cloud shader effect
// Based on volumetric rendering techniques

// Constants to control cloud appearance
#define ITERATIONS 60
#define CLOUD_DENSITY 0.65
#define CLOUD_SPEED 0.15
#define CLOUD_SCALE 2.5
#define CLOUD_DETAIL 2.8
#define CLOUD_HEIGHT 0.4

// Noise function for cloud generation
float noise(vec3 p) {
    vec3 i = floor(p);
    vec3 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);
    
    // Hash function
    vec2 uv = (i.xy + vec2(37.0, 17.0) * i.z) + f.xy;
    float a = fract(sin(uv.x * 7.5 + uv.y * 3.14) * 753.57);
    float b = fract(sin((uv.x + 1.0) * 7.5 + uv.y * 3.14) * 753.57);
    float c = fract(sin(uv.x * 7.5 + (uv.y + 1.0) * 3.14) * 753.57);
    float d = fract(sin((uv.x + 1.0) * 7.5 + (uv.y + 1.0) * 3.14) * 753.57);
    
    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}

// Fractal Brownian Motion for more detailed clouds
float fbm(vec3 p) {
    float f = 0.0;
    float weight = 0.5;
    float scale = 1.0;
    
    for (int i = 0; i < 5; i++) {
        f += weight * noise(p * scale);
        weight *= 0.5;
        scale *= 2.0;
    }
    
    return f;
}

// Main cloud function
float cloudDensity(vec3 p) {
    // Adjust height for cloud formation
    float height = smoothstep(0.0, CLOUD_HEIGHT, p.y);
    height *= smoothstep(1.0, 0.7, p.y);
    
    // Add time-based movement
    p.xz += u_time * CLOUD_SPEED;
    
    // Generate cloud pattern
    float noise = fbm(p * CLOUD_SCALE);
    noise = pow(noise, CLOUD_DETAIL);
    
    return noise * height * CLOUD_DENSITY;
}

// Color functions
vec3 skyColor(vec3 rayDir) {
    float sunAmount = max(dot(rayDir, normalize(vec3(0.2, 0.6, 0.3))), 0.0);
    vec3 skyCol = mix(vec3(0.3, 0.5, 0.9), vec3(0.8, 0.9, 1.0), rayDir.y * 0.5 + 0.5);
    vec3 sunCol = vec3(1.0, 0.8, 0.4);
    return mix(skyCol, sunCol, pow(sunAmount, 8.0));
}

void main() {
    // Normalized coordinates
    vec2 uv = gl_FragCoord.xy / u_resolution.xy;
    uv = uv * 2.0 - 1.0;
    uv.x *= u_resolution.x / u_resolution.y;
    
    // Ray setup - camera position and direction
    vec3 rayOrigin = vec3(0.0, 1.0, -5.0);
    vec3 rayDir = normalize(vec3(uv, 1.0));
    
    // Ray marching parameters
    float stepSize = 0.1;
    float transmittance = 1.0;
    vec3 color = vec3(0.0);
    
    // Cloud space transformation
    mat3 cloudSpace = mat3(
        cos(u_time * 0.05), 0.0, sin(u_time * 0.05),
        0.0, 1.0, 0.0,
        -sin(u_time * 0.05), 0.0, cos(u_time * 0.05)
    );
    
    // Cloud ray marching
    for (int i = 0; i < ITERATIONS; i++) {
        // Current position along ray
        vec3 pos = rayOrigin + rayDir * float(i) * stepSize;
        
        // Transform to cloud space
        vec3 cloudPos = cloudSpace * pos;
        
        // Sample cloud density at this position
        float density = cloudDensity(cloudPos);
        
        // Skip empty space
        if (density > 0.01) {
            // Light scattering calculation
            float lightDensity = cloudDensity(cloudPos + vec3(0.3, 0.5, 0.2));
            float lightFactor = exp(-lightDensity * 2.0);
            
            // Cloud lighting colors
            vec3 cloudColor = mix(
                vec3(0.8, 0.8, 0.9),     // Base cloud color
                vec3(1.0, 0.9, 0.8),     // Lit cloud color
                lightFactor
            );
            
            // Accumulate color with transmittance
            color += cloudColor * density * stepSize * transmittance;
            
            // Reduce transmittance (more opaque)
            transmittance *= exp(-density * stepSize * 2.0);
            
            // Exit early if nearly opaque
            if (transmittance < 0.01) {
                break;
            }
        }
    }
    
    // Mix with sky background
    vec3 backgroundColor = skyColor(rayDir);
    color = color + backgroundColor * transmittance;
    
    // Output final color
    gl_FragColor = vec4(color, 1.0);
}