#version 330 core

in vec2 vUV;
out vec4 FragColor;

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;
uniform float uRainIntensity;
uniform float uLightningIntensity;
uniform float uMoonGlow;
uniform vec2 uMouseOffset;

float rand(vec2 p)
{
    p += 0.2127 + p.x + 0.3713 * p.y;
    vec2 r = 4.789 * sin(789.123 * p);
    return fract(r.x * r.y);
}

float sn(vec2 p)
{
    vec2 i = floor(p - 0.5);
    vec2 f = fract(p - 0.5);
    f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
    float rt = mix(rand(i), rand(i + vec2(1.0, 0.0)), f.x);
    float rb = mix(rand(i + vec2(0.0, 1.0)), rand(i + vec2(1.0, 1.0)), f.x);
    return mix(rt, rb, f.y);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = fragCoord.xy / iResolution.y;
    uv += uMouseOffset;

    vec2 p = uv.xy * vec2(3.0, 4.3);
    float f =
        0.5 * sn(p)
        + 0.25 * sn(2.0 * p)
        + 0.125 * sn(4.0 * p)
        + 0.0625 * sn(8.0 * p)
        + 0.03125 * sn(16.0 * p)
        + 0.015 * sn(32.0 * p);

    float newT = iTime * 0.4 + sn(vec2(iTime * 1.0)) * 0.1;
    p.x -= iTime * 0.2;

    p.y *= 1.3;
    float f2 =
        0.5 * sn(p)
        + 0.25 * sn(2.04 * p + newT * 1.1)
        - 0.125 * sn(4.03 * p - iTime * 0.3)
        + 0.0625 * sn(8.02 * p - iTime * 0.4)
        + 0.03125 * sn(16.01 * p + iTime * 0.5)
        + 0.018 * sn(24.02 * p);

    float f3 =
        0.5 * sn(p)
        + 0.25 * sn(2.04 * p + newT * 1.1)
        - 0.125 * sn(4.03 * p - iTime * 0.3)
        + 0.0625 * sn(8.02 * p - iTime * 0.5)
        + 0.03125 * sn(16.01 * p + iTime * 0.6)
        + 0.019 * sn(18.02 * p);

    float f4 = f2 * smoothstep(0.0, 1.0, uv.y);

    vec3 clouds = mix(vec3(-0.4, -0.4, -0.15), vec3(1.4, 1.4, 1.3), f4 * f);
    float lightning = sn(vec2(f3) + vec2(pow(sn(vec2(iTime * 4.5)), 6.0)));

    lightning *= smoothstep(0.0, 1.0, uv.y + 0.5);
    lightning = smoothstep(0.76, 1.0, lightning);
    lightning *= 2.0 * uLightningIntensity;

    vec2 moonp = vec2(0.5, 0.8);
    float moon = smoothstep(0.95, 0.956, 1.0 - length(uv - moonp));
    vec2 moonp2 = moonp + vec2(0.015, 0.0);
    moon -= smoothstep(0.93, 0.956, 1.0 - length(uv - moonp2));
    moon = clamp(moon, 0.0, 1.0);
    moon += 0.3 * smoothstep(0.80, 0.956, 1.0 - length(uv - moonp));

    clouds += pow(max(1.0 - length(uv - moonp), 0.0), 1.7) * 0.3 * uMoonGlow;
    clouds *= 0.8;
    clouds += lightning + moon * uMoonGlow + 0.2;

    float ground = smoothstep(0.07, 0.075, f * (p.y - 0.98) + 0.01);

    vec2 newUV = uv;
    newUV.x -= iTime * 0.3;
    newUV.y += iTime * 3.0;
    float strength = sin(iTime * 0.5 + sn(newUV)) * 0.1 + 0.15;

    float rain = sn(vec2(newUV.x * 20.1, newUV.y * 40.1 + newUV.x * 400.1 - 20.0 * strength));
    float rain2 = sn(vec2(newUV.x * 45.0 + iTime * 0.5, newUV.y * 30.1 + newUV.x * 200.1));
    rain = strength - rain;
    rain += smoothstep(0.2, 0.5, f4 + lightning + 0.1) * rain;
    rain += pow(length(uv - moonp), 1.0) * 0.1;
    rain += rain2 * (sin(strength) - 0.4) * 2.0;
    rain = clamp(rain, 0.0, 0.5) * 0.5 * uRainIntensity;

    float tree = 0.0;
    vec2 treeUV = uv;

    float atree = abs(atan(treeUV.x * 59.0 - 85.5, 3.0 - treeUV.y * 25.0 + 5.0));
    atree += rand(treeUV.xy * vec2(0.001, 1.0)) * atree;
    tree += clamp(atree, 0.0, 1.0) * 0.33;

    atree = abs(atan(treeUV.x * 65.0 - 65.5, 3.0 - treeUV.y * 19.0 + 4.0));
    atree += rand(treeUV.xy * vec2(0.001, 1.0)) * atree;
    tree += clamp(atree, 0.0, 1.0) * 0.33;

    atree = abs(atan(treeUV.x * 85.0 - 91.5, 3.0 - treeUV.y * 21.0 + 4.0));
    atree += rand(treeUV.xy * vec2(0.001, 1.0)) * atree;
    tree += clamp(atree, 0.0, 1.0) * 0.34;
    tree = smoothstep(0.6, 1.0, tree);

    vec3 painting = tree * ground * (clouds + rain) + clamp(rain * (strength - 0.1), 0.0, 1.0);

    float r = 1.0 - length(max(abs(fragCoord.xy / iResolution.xy * 2.0 - 1.0) - 0.5, 0.0));
    painting *= max(r, 0.0);

    fragColor = vec4(max(painting, 0.0), uAlpha);
}

void main()
{
    mainImage(FragColor, vUV * iResolution.xy);
}
