#version 330 core

in vec2 uv;
out vec4 FragColor;

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;
uniform float uStartDelay;
uniform sampler2D iChannel0;

float hash(vec2 p) {
    float h = dot(p,vec2(127.1,311.7));
    return -1.0 + 2.0*fract(sin(h)*43758.5453123);
}

float noise(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);

    vec2 u = f*f*(3.0-2.0*f);

    return mix(mix(hash( i + vec2(0.0,0.0) ), 
        hash( i + vec2(1.0,0.0) ), u.x),
    mix( hash( i + vec2(0.0,1.0) ), 
        hash( i + vec2(1.0,1.0) ), u.x), u.y);
}

float noise(vec2 p, int oct) {
    mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
    float f  = 0.0;

    for(int i = 1; i < 3; i++){
        float mul = 1.0/pow(2.0, float(i));
        f += mul*noise(p); 
        p = m*p;
    }

    return f;
}

void main()
{
    float t = iTime - uStartDelay;
    if (t < 0.0) discard;

    vec2 fragCoord = uv * iResolution.xy;
    vec2 fragUv = fragCoord.xy / iResolution.xy;

    float glitch = pow(cos(t*0.5)*1.2+1.0, 1.2);


    if(noise(t+vec2(0, 0))*glitch > 0.62){
        fragUv.y = mod(fragUv.y+noise(vec2(t*4.0, 0)), 1.0);
    }


    vec2 hp = vec2(0.0, fragUv.y);
    float nh = noise(hp*7.0+t*10.0, 3) * (noise(hp+t*0.3)*0.8);
    nh += noise(hp*100.0+t*10.0, 3)*0.02;
    float rnd = 0.0;
    if(glitch > 0.0){
        rnd = hash(fragUv);
        if(glitch < 1.0){
            rnd *= glitch;
        }
    }
    nh *= glitch + rnd;
    float r = texture(iChannel0, fragUv+vec2(nh, 0.08)*nh).r;
    float g = texture(iChannel0, fragUv+vec2(nh-0.07, 0.0)*nh).g;
    float b = texture(iChannel0, fragUv+vec2(nh, 0.0)*nh).b;

    vec3 col = vec3(r, g, b);
    vec4 result = vec4(col.rgb, 1.0);
    result.a *= uAlpha;

    FragColor = result;
}
