#version 430

in vec2 uv;

layout(location = 0) out vec4 frag;
// layout(location = 1) out vec4 frag2;

uniform float g_time;


vec2 rotateXY2(vec2 p, float a) {
  vec2 r = p;
  r.x = cos(a)*p.x - sin(a)*p.y;
  r.y = sin(a)*p.x + cos(a)*p.y;
  return r;
}



uniform float flip=1.0;

uniform float overlayAlpha=1.0;


layout(binding=0) uniform sampler2D tex;
layout(binding=1) uniform sampler2D texGrad;
layout(binding=2) uniform sampler2D texNoise;
layout(binding=3) uniform sampler2D texBlur;

uniform float noiseOct = 8.0;
uniform float noiseFreq = 1.0;
uniform float noisePos = 0.0;
uniform float noisePosX = 0.0;
uniform float noisePosY = 0.0;
uniform float noiseAmp = 1.0;
uniform float noiseLevelMul = 0.50;
uniform float noiseLevelOct = 2.0;
uniform float noiseExp = 1.0;

uniform float texScaleX = 1.0;
uniform float texScaleY = 1.0;
uniform float texOfsX = 0.0;
uniform float texOfsY = 0.0;

uniform float toAlphaLimit = 0.0;
uniform float toAlphaAmp = 10.0;
uniform float toAlphaExp = 1.0;

uniform float bright = 1.0;
uniform float gradExp = 1.0;
uniform float gradRot = 90.0;

uniform float turbOp = 0.0;

uniform float gradBlurDir = 1.0;


float turb(vec2 p, float amp) {
    float a = noiseAmp*0.1*amp;
    float res = 1.0;
    p.xy *= noiseFreq*0.00001;
    p.x += noisePosX*0.001;
    p.y += noisePosY*0.001;
    float np = noisePos*0.01;
 //   if (turbOp < 0.5) {
        for (int i=0; i<noiseOct; i++) {
            float kb = a*((texture2D(texNoise, vec2(p.x+np*1.74, p.y+np*0.82)).r+
                            texture2D(texNoise, vec2(p.x*0.73+np*1.74, p.y*1.27+np*1.42)).g+
                            texture2D(texNoise, vec2(p.x*0.044+np*1.04+p.y*0.42, p.x*0.6+p.y*0.097+np*1.12)).b)*0.333-0.5);
            res += kb;
            p.xy *= noiseLevelOct;
            a *= noiseLevelMul;
        }
//    } else {
//        for (int i=0; i<noiseOct; i++) {
//            float kb = a*((texture2D(texNoise, vec2(p.x+np*1.74, p.y+np*0.82)).r+
//                            texture2D(texNoise, vec2(p.x*0.73+np*1.74, p.y*1.27+np*1.42)).g+
//                            texture2D(texNoise, vec2(p.x*0.044+np*1.04+p.y*0.42, p.x*0.6+p.y*0.097+np*1.12)).b)*0.333-0.5);
//            res *= 1.0+kb;
//            p.xy *= noiseLevelOct;
//            a *= noiseLevelMul;
//        }
//    }
    return res;
}

float deg2pi = 2.0*3.141592/360.0;


void main() {

    vec2 uvS = uv;
    uvS.y = 1.0-uvS.y;

    vec4 screen = texelFetch(tex, ivec2(gl_FragCoord.xy), 0);
    float nv = turb(vec2(gl_FragCoord.xy), 1.0*(1.0-gradBlurDir)+200.0*(gradBlurDir));

    nv = sign(nv)*pow(abs(nv), noiseExp);

//    vec3 bl = texelFetch(texBlur, ivec2(gl_FragCoord.xy), 0).rgb;
    vec3 bl = texture2D(texBlur, rotateXY2(vec2(uvS.y*texScaleY-1.5+texOfsY, uvS.x*texScaleX-0.5+texOfsX), deg2pi*gradRot)+vec2(0.5, 0.5)).rgb;
    vec3 bldx = dFdx(bl);
    vec3 bldy = dFdy(bl);

    vec2 nd = vec2(bldx.x, bldy.x)*10.0;

    vec4 grad = texture2D(texGrad, rotateXY2(vec2(uvS.y*texScaleY+nd.y*nv*gradBlurDir+(1.0-gradBlurDir)*nv-1.5+texOfsY, uvS.x*texScaleX+nd.x*nv*gradBlurDir-0.5+texOfsX), deg2pi*gradRot)+vec2(0.5, 0.5));

    float alp = toAlphaAmp*dot(grad.rgb, vec3(1.0))*0.3333-toAlphaLimit;

    alp = pow(alp, toAlphaExp);

    alp = clamp(alp, 0.0, 1.0);

    screen = pow(grad, vec4(gradExp))*alp*bright+screen*(1.0-alp);


   // screen.rgb = vec3(bldx.r, bldy.r, 0.0)*100.0;

    screen.a = 1.0;
    frag = screen;
}

