#version 430 core

uniform float fGlobalTime; // in seconds
uniform vec2 v2Resolution; // viewport resolution (in pixels)

uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq
uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients
uniform sampler2D texBricks;
uniform sampler2D texGrunge;
uniform sampler2D texHello;
uniform sampler2D texMono;
uniform sampler2D texNoise;
uniform sampler2D texNormal;
uniform sampler2D texPaper;

float time;
 
layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything

vec4 plas( vec2 v, float time )
{
  float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );
  return vec4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );
}

#define R(v,a) (v.xy * cos(a) + v.yx * vec2(-sin(a), sin(a)))

float torus(vec3 p, vec2 r) {
   vec2 c =vec2(length(p.xy)-r.x,p.z);
   return length(c) - r.y;
 }

float max3(vec3 m) {
  return max(m.x, max(m.y, m.z));
}

float cube(vec3 p, vec3 d) {
   vec3 x = abs(p) - d;
   return length(max(x,0)) + max3(min(x,0));
}

float f(vec3 p) {
  p -= vec3(0,0,10);
  vec3 q = p;
  //q.xy = cos(time) * q.xy + vec2(-sin(time), sin(time))*q.yx;
  //q.xz = cos(time) * q.xz + vec2(-sin(time), sin(time))*q.yz;
   q.xy = R(q.xy,time);
  q.xz = R(q.xz,time);
  return min(torus(q, vec2(3,.7)),cube(q,vec3(.5))-.3);
}

vec4 colormap(vec3 n) {
   float m = max3(n);
   n.xy = R(n.xy, 314159/4);
   float l = max3(n);
   return vec4(m, m*l, l,1);
}

void main(void)
{
  vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);
  uv -= 0.5;
  uv /= vec2(v2Resolution.y / v2Resolution.x, 1);
  
  time = fGlobalTime;
  if(mod(time, 5) < 2.5) { 
     time += uv.y + uv.y - mod(uv.y, 0.1) -mod(uv.x, 0.2);;
  } else {
     time += uv.x+uv.y - mod(uv.x + uv.y, .2);
  }

   {
  vec2 m;
  m.x = atan(uv.x / uv.y) / 3.14;
  m.y = 1 / length(uv) * .2;
  float d = m.y;

  float f = texture( texFFT, d ).r * 100;
  m.x += sin( time ) * 0.1;
  m.y += time * 0.25;

  vec4 t = plas( m * 3.14, time ) / d;
  t = clamp( t, 0.0, 1.0 );
  out_color = t;
  }

  float t = 0;
  float tmax=100;
  float epsilon=0.0001;
  float r;
  vec3 p = vec3(0);
  vec3 d = vec3(uv.xy, 1);
  for(int i=0; i< 128 && t<tmax; i++) {
    r = f(p+d*t);
    if(r < epsilon*.1) {
      break;
    }
    t += r;
  }
  p+=d*t;

  float f0 = f(p);
  vec3 n = normalize(vec3(f(p+epsilon*vec3(1,0,0))-f0,f(p+epsilon*vec3(0,1,0))-f0,f(p+epsilon*vec3(0,0,1))-f0));
  if(t<tmax) {
     out_color = colormap(n);
  }
  out_color = pow(out_color, vec4( 1.5- .7*mod(time, 2.5)));
  float val = length(out_color);
  out_color = mix(out_color, vec4(val), vec4(.7 - .3*sqrt(val)));
  float fa = texture(texFFTSmoothed, 0.01).x;
  out_color += .4*texture(texMono,uv)*vec4((texture(texFFT, 0.01).x - fa) / fa);
}