#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 texMono;
uniform sampler2D texNoise;
uniform sampler2D texNormal;
uniform sampler2D texPaper;
uniform sampler2D texPooBrain;

layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything


float rubban( vec3 p)
{
  return length( p.xy+vec2(cos(p.z),sin(p.z)) ) - .1;
}

float rubban1( vec3 p)
{
  return length( p.xy+vec2(cos(p.z+2.),sin(p.z+2.)) ) - .1;
}

float rubban2( vec3 p)
{
  return length( p.xy+vec2(cos(p.z+4.),sin(p.z+4.)) ) - .1;
}

float map( in vec3 p)
{
  float d = p.y+1.;
  d = min(d, -p.y+2.);
  d = min(d, cos(p.x)+cos(p.y)+cos(p.z)+cos(p.y*20.)*10.*texture(texFFT,0.05).r);
  p.x += 3.;  p.x = mod(p.x, 6.)-3.;
  d = min(d, rubban(p));
  d = min(d, rubban1(p));
  d = min(d, rubban2(p));
  d = max(d, p.z-fGlobalTime*3.-6.);
  return d;
}

vec2 rotate( vec2 v, float a)
{
  return vec2( v.y*cos(a) - v.x*sin(a), v.x*cos(a) + v.y*sin(a));
}

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);  vec2 uv2 = uv;
  uv.x += texture(texFFT, uv.y*.5+.5).r;
  vec3 col = vec3(0.);

  vec3 org = vec3(cos(fGlobalTime*10.)*texture(texFFT,0.1).r*5., cos(fGlobalTime*20.)*texture(texFFT,0.1).r*5.,fGlobalTime*3.);
  vec3 dir = normalize(vec3(uv, 1.-length(uv)*1.));
  dir.xy = rotate(dir.xy, fGlobalTime*.25);
  dir.xz = rotate(dir.xz, fGlobalTime*.1);
  vec4 p =vec4(org,0.);

  for(int i=0; i<128; i++)
  {
    float d = map(p.xyz);
    p += vec4( dir*d, 1./64.);
    if(d<0.01)
      break;
  }

  col += vec3(.1,.1,1.0)*p.w *p.w;  p.x += 3.;  p.x = mod(p.x, 6.)-3.;
  float coef = 0.;  for(float i=0.; i<.02; i+=1./100.)
  {
    coef += texture( texFFT, i).r;
  }
  col += vec3(1.,.3,.1) / (.1 + pow( rubban(p.xyz), 2.) ) * coef;

  coef = 0.;  for(float i=.1; i<.25; i+=1./100.)
  {
    coef += texture( texFFT, i).r;
  }
  col += vec3(.1,1.,.1) / (.1 + pow( rubban1(p.xyz), 2.) ) * coef;

  coef = 0.;  for(float i=.25; i<.5; i+=1./100.)
  {
    coef += texture( texFFT, i).r;
  }
  col += vec3(.5,.1,1.) / (.1 + pow( rubban2(p.xyz), 2.) ) * coef;
  
  col *= vec3(3.);

  col = pow(col, vec3(1.2));
  //col += texture(texFFT, length(uv)).rgb*100;
  col = mix( col.rgb, col.bgr, texture(texFFT, uv.y*.5+.5).r*10.);
  
  col *= exp(-length(p.xyz-org)*.25);

  uv = uv2;
  uv.y -= texture(texFFT, 0.05).r*2.;
  uv += vec2(.6,.25);
  if( uv.x < .2 && uv.x > -.2 && uv.y < -abs(uv.x) && uv.y > -.2 && !( uv.x < .1 && uv.x > -.1 && uv.y+.2 > abs(uv.x) && uv.y < -.1 ))
    col = vec3(1.,.8,.2);


  out_color = vec4(col,1.);
}