#version 330 core
#define STEPS 160
in vec2 vUV;
out vec4 FragColor;
uniform vec3 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;
uniform float uAlpha;

float hash(vec2 p){
    return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);
}

void mainImage(out vec4 o, vec2 fragCoord)
{
    vec2 r = iResolution.xy;
    vec2 uv = fragCoord / r;
    vec2 suv = (fragCoord - 0.5 * r) / r.y;

    float t = iTime * 1.4;

    vec3 ro = vec3(0.0, 0.0, -2.5);
    vec3 rd = normalize(vec3(suv, 1.5));

    vec3 lightPos = vec3(0.0, 0.5, 0.0);

    float sweep = sin(t);
    float sweepAmount = 1.5;

    vec3 forward = vec3(0.0, 0.0, 1.0);
    vec3 lightDir = normalize(forward + vec3(sweep * sweepAmount, -0.2, 0.0));

    float coneAngle = radians(32.0);
    float cosInner = cos(coneAngle);
    float cosOuter = cos(coneAngle * 1.2);

    float volumetric = 0.0;
    float lightMask = 0.0;

    float d = 0.0;

    for(int i = 0; i < STEPS; i++)
    {
        vec3 p = ro + rd * d;

        vec3 lp = p - lightPos;
        float dist = length(lp);
        vec3 ldir = lp / dist;

        float beam = dot(ldir, lightDir);
        float cone = smoothstep(cosOuter, cosInner, beam);

        float falloff = 1.0 / (1.0 + dist * dist * 0.4);
        float fog = exp(-dist * 0.6);

        float light = cone * fog * falloff;

        volumetric += light * 0.03;
        lightMask += light * 0.05;

        d += 0.05;
    }

    lightMask = clamp(lightMask, 0.0, 1.0);

    float facing = dot(lightDir, normalize(-ro));
    lightMask *= smoothstep(0.0, 0.2, facing);

    vec3 bg = texture(iChannel0, uv).rgb;

    vec3 col = vec3(0.01, 0.02, 0.03);

    col = mix(col, bg, lightMask);

    col += volumetric * vec3(1.0, 0.95, 0.8);

    float distFog = exp(-length(suv) * 2.0);
    col *= distFog;

    col += hash(suv + t) * 0.02;

    o = vec4(col, 1.0);
}

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