#version 430

layout(binding=0) uniform sampler2D tex;
layout(binding=1) uniform sampler2D tex1;
layout(binding=2) uniform sampler2D tex2;


in vec2 uv;

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

uniform float g_time;

// from pouet raymarching thread by las of mercury
float perlin(vec3 p) {
    vec3 i = floor(p);
    vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
    vec3 f = cos((p-i)*3.14159265)*(-.5)+.5;
    a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
    a.xy = mix(a.xz, a.yw, f.y);
    return mix(a.x, a.y, f.z);
}

float perlin2(vec3 p) {
    return 0.5*(perlin(p)+perlin(vec3(p.x, p.y, 0.5-p.z)));
}

float turbK(vec3 p) {
    float res = 0.0;
    float m = 0.5;
    for (int i=0; i<4; i++) {
        res += m*perlin2(p);
        p*=2.0;
        m*=0.5;
    }
    return res;
}




// noise functions from: https://github.com/ashima/webgl-noise/
vec3 mod289(vec3 x)
{
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 mod289(vec4 x)
{
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 permute(vec4 x)
{
  return mod289(((x*34.0)+1.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

vec3 fade(vec3 t) {
  return t*t*t*(t*(t*6.0-15.0)+10.0);
}

// Classic Perlin noise
float cnoise(vec3 P)
{
  vec3 Pi0 = floor(P); // Integer part for indexing
  vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
  Pi0 = mod289(Pi0);
  Pi1 = mod289(Pi1);
  vec3 Pf0 = fract(P); // Fractional part for interpolation
  vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
  vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
  vec4 iy = vec4(Pi0.yy, Pi1.yy);
  vec4 iz0 = Pi0.zzzz;
  vec4 iz1 = Pi1.zzzz;

  vec4 ixy = permute(permute(ix) + iy);
  vec4 ixy0 = permute(ixy + iz0);
  vec4 ixy1 = permute(ixy + iz1);

  vec4 gx0 = ixy0 * (1.0 / 7.0);
  vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
  gx0 = fract(gx0);
  vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
  vec4 sz0 = step(gz0, vec4(0.0));
  gx0 -= sz0 * (step(0.0, gx0) - 0.5);
  gy0 -= sz0 * (step(0.0, gy0) - 0.5);

  vec4 gx1 = ixy1 * (1.0 / 7.0);
  vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
  gx1 = fract(gx1);
  vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
  vec4 sz1 = step(gz1, vec4(0.0));
  gx1 -= sz1 * (step(0.0, gx1) - 0.5);
  gy1 -= sz1 * (step(0.0, gy1) - 0.5);

  vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
  vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
  vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
  vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
  vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
  vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
  vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
  vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);

  vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
  g000 *= norm0.x;
  g010 *= norm0.y;
  g100 *= norm0.z;
  g110 *= norm0.w;
  vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
  g001 *= norm1.x;
  g011 *= norm1.y;
  g101 *= norm1.z;
  g111 *= norm1.w;

  float n000 = dot(g000, Pf0);
  float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
  float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
  float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
  float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
  float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
  float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
  float n111 = dot(g111, Pf1);

  vec3 fade_xyz = fade(Pf0);
  vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
  vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
  float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
  return 2.2 * n_xyz;
}

float noise(vec3 c) {
        return cnoise(c); //abs(cnoise(coord * 2.5));
}

float turb(vec3 p) {
    float res = 0.0;
    float m = 0.5;
    for (int i=0; i<7; i++) {
        res += m*noise(p);
        p*=3.0;
        m*=0.65;
    }
    return res;
}


float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec3 tonemapUC2(vec3 x) {
    float A = 0.15;
    float B = 0.50;
    float C = 0.10;
    float D = 0.20;
    float E = 0.02;
    float F = 0.30;
    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}


uniform float feedback = 0.0;

void main() {

    vec2 uvCal = uv;

    uvCal -= vec2(0.5, 0.5);

    uvCal.x = abs(uvCal.x);
  //  uvCal.y = abs(uvCal.y);

    uvCal += vec2(0.5, 0.5);

    vec4 result = texture2D(tex, uvCal+vec2(0.0, 0.0));

    vec2 zp = vec2(0.45, 0.55);
    vec2 uvZoom = uv-zp;
    float uvZoomV = 0.01+0.99*clamp(2.0*sin(g_time*0.5), 0.0, 1.0);
    uvZoom *= uvZoomV*2.0;
    uvZoom += zp;
    uvZoom = clamp(uvZoom, 0.0, 1.0);

    vec4 bg = texture2D(tex1, uvZoom);
    // result.r = 1.0;

    float bright = dot(result.rgb, vec3(0.344, 0.5, 0.156));

    float brightF = clamp((1.0-0.9*bright)*3.5, 0.0, 1.0);

    result.rgb *= (0.8+0.3*brightF*turbK(vec3(uv*7.0, 0.15*g_time))*perlin2(vec3(uv*1.0, 0.1*g_time)));
//    result.rgb *= (brightF*perlin2(vec3(uv*3.0, 0.1*g_time)));
    result.a = 1.0;

    bg.rgb *= (1.0-uvZoomV);

    result.rgb += (bg.rgb*result.rgb+(bg.rgb*0.0)-vec3(0.50));


    vec2 uvC = uv-vec2(0.5,0.5);
    uvC *= 0.99;
    uvC += vec2(0.5,0.5);
//    result.rgb -= 0.999*texture2D(tex2, uvC).rgb;
    result.rgb += feedback*0.8*texture2D(tex2, uvC).rgb*vec3(1.1, 0.9, 0.8);

    vec4 color = result*result;
    vec2 uvc = uv-vec2(0.5, 0.5);

    float vignette = clamp((1.0-sqrt(dot(uvc, uvc))*1.0), 0.0, 1.0)+rand(uv)*0.05;
    vignette *= vignette;
    color *= vignette;
    color.rgb = tonemapUC2(color.rgb*3.0);
    color = pow(color, vec4(0.50*1.30))*2.0;
    color = clamp(color, 0.0, 1.0);

  //  color.rgb = vec3(brightF);

    color.a = 1.0;

    frag = color;
}

