#version 430 core

///////////////////////////////////////////////////////////////////////////////
// shader inputs/outputs
///////////////////////////////////////////////////////////////////////////////
uniform float iGlobalTime; // in seconds
uniform vec2 iResolution; // viewport resolution (in pixels) (1080p or 720p)
uniform mat4 iMidiPad; // 16 buttons of midi controller
uniform float iMidiPadValue; // sum of all elements in iMidiPad/16

// all samplers have linear filtering applied, wraping set to repeat
//
uniform sampler1D iFFTTexture; // 1024
uniform float iFFT[8]; // latest frame
uniform float iFFTs[8]; // smoothed latest frame
uniform sampler2D iFFTsHistory; // smoothed fft history, 8x1024, x coord = bin, y coord n-frames earlier, y=0 is latest frame

// predefined textures
//
uniform sampler2D iTex1;
uniform sampler2D iTex2;
uniform sampler2D iTex3;
uniform sampler2D iTex4;
uniform sampler2D iTex5;
uniform sampler2D iTex6;
uniform sampler2D iTex7;
uniform sampler2D iTex8;
uniform sampler2D iNoise;
uniform sampler2D iChecker;

// out_color must be written in order to see anything
//
layout(location = 0) out vec4 out_color;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

float hash(float n){
       return fract(sin(n)*53487.23645);
}

float noise(vec3 p)
{
       vec3 p0 = floor(p), f = fract(p);
       //f = smoothstep(0,1,f);
       f = atan(f);
       float n = p0.x + p0.y * 57 + p0.z * 113;
       return mix( mix( mix(hash(n), hash(n+1), f.x), mix(hash(n + 57), hash(n+58), f.x), f.y),  mix( mix(hash(n+113), hash(n+114), f.x), mix(hash(n + 170), hash(n+171), f.x), f.y), f.z);
}
vec3 ro(vec3 p, float a){
       return mat3(1,0,0,0,cos(a), sin(a), 0, -sin(a), cos(a))*p;
}

float h( vec3 p){
       vec3 p0 = p;
       p = ro(p.zxy, (iFFTs[0] -iFFTs[6] )* 5 + iGlobalTime/2 ).zxy;
       p.z += iGlobalTime * 10;
       p.xy = mod(p.xy - 2.5,5)-2.5;
       p.x += sin(p.x) * iFFTs[1];
       return -length(p.xy) + 3 + 5* iFFTs[0] - iFFTs[4] + 2*sin(p.z) - noise(p);
}


void main(void)
{
       vec3 rd = normalize(vec3(iResolution.x/iResolution.y*(gl_FragCoord.x/iResolution.x - .5),(gl_FragCoord.y/iResolution.y - .5), 1)), p=vec3(0);
       float d;
       for(int i = 0; i < 250; i++)
       {
               d = h(p);
               if(d<.001)
                       break;
               p += rd * d / 4;
       }
vec2 uv = vec2( gl_FragCoord.xy ) / iResolution;
       vec2 uv5 = uv - 0.5;
       vec2 m;
       m.x = atan(uv5.x / uv5.y);
       m.y = length(uv5);
       float f = texture( iFFTTexture, m.y  ).r * 100;
       m.y -= iGlobalTime;
       vec4 t = texture( iChecker, uv.xy  );
       out_color = vec4(.3, .4,.5,1) * vec4( h(p - vec3(.01)) * 16.) + (iFFTs[1] - iFFTs[6] ) * 4 *noise (p - vec3(0,0,iGlobalTime * 10))

;
}