#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

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 );
}

vec4 f_plane(vec3 pos) {
  float c = step(abs(pos.x),1.)*.25+.25;
  c += step(abs(pos.x),sin(sin(pos.z*3.)+sin(pos.z*4.2434))*.1+.2);

   float u = sin(pos.z*.03+fGlobalTime*.4)+sin(pos.z*.0114)+sin(pos.z*.021341);
   u = sin(u*10.);
   pos.y += u*u;

  float a = texture(texNormal,vec2(pos.z*.01,fGlobalTime*1))*.5-.15;  
  pos.xy *= mat2(cos(a),sin(a),-sin(a),cos(a));


  return vec4(vec3(c), max(abs(pos.y),abs(pos.x)-1.));
}

vec4 f_obj1(vec3 pos) {
  float z = floor(pos.z);
  pos.z = fract(pos.z+.5)-.5;
  float t = fGlobalTime+sin(sin(z)*131.+fGlobalTime)*3.;
  pos -= vec3(sin(t),cos(t),0)*2.;
  return vec4(abs(vec3(cos(z),cos(z+2.),cos(z-2.))),length(pos)-texture(texFFTSmoothed,pos.z*.002)*10.);
}

vec4 f_obj2(vec3 pos) {
  pos.z += .5;
  float z = floor(pos.z);
  pos.z = fract(pos.z*.5+.5)*2.-.5;
  pos.y -= sin(pos.x)*texture(texFFT,pos.z)+pow(abs(sin(pos.x+z+fGlobalTime*10.)+sin(pos.x+z*1.131)),5.)*.1+3.;
  float t = fGlobalTime+sin(sin(z)*131.+fGlobalTime)*3.;
  pos -= vec3(sin(t),cos(t),0)*2.;
  return vec4(abs(vec3(cos(z),cos(z+2.),cos(z-2.))),length(pos.yz)-.01);
}

vec4 m(vec4 c) {
  return vec4(c.xyz,1)/(c.w+.001);
}


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);

  vec3 pos = vec3(0,1,(fGlobalTime)*5.);
  vec3 dir = normalize(vec3(uv,1));

  vec4 v_plane, v_obj1, v_obj2;

  vec4 sum1 = vec4(0);

  for (int i = 0; i < 100; i++) {
    v_plane = f_plane(pos);
    v_obj1 = f_obj1(pos);
    v_obj2 = f_obj2(pos);
    float f = .5;
    f = min(f,v_plane.w);
    f = min(f,v_obj1.w);
    f = min(f,v_obj2.w);
    sum1 += v_obj1/(v_obj1.w+.1);

    pos += dir*f;
  }

   vec4 sum = m(v_plane);
   sum += m(v_obj1);
   sum += m(v_obj2);
   sum += vec4(texture(texMono,gl_FragCoord.xy/v2Resolution.xy).xyz*texture(texFFT,0).x*2.,1.)*10.;

  out_color = vec4(sum.xyz/sum.w+sum1.xyz*.01,1.);
}