#version 410 core

uniform float fGlobalTime; // in seconds
uniform vec2 v2Resolution; // viewport resolution (in pixels)
uniform float fFrameTime; // duration of the last frame, in seconds

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 sampler1D texFFTIntegrated; // this is continually increasing
uniform sampler2D texPreviousFrame; // screenshot of the previous frame
uniform sampler2D texChecker;
uniform sampler2D texNoise;
uniform sampler2D texTex1;
uniform sampler2D texTex2;
uniform sampler2D texTex3;
uniform sampler2D texTex4;

layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything
float time = fGlobalTime;
float rd(vec3 p){return fract(sin(dot(floor(p),vec3(45.,65.,269.)))*7845.236);}
mat2 rot(float t){float c = cos(t); float s = sin(t); return mat2 (c,-s,s,c);}
float bl (vec2 p, vec2 b){ vec2 q = abs(p)-b;
 return length(max(vec2(0.),q))+min(0.,max(q.x,q.y));}
 float box (vec3 p, vec3 b){ vec3 q = abs(p)-b;
 return length(max(vec3(0.),q))+min(0.,max(q.x,max(q.z,q.y)));}

 float zl1 ;float zl2;float bl2;float zl3; float bl3;
float map(vec3 p,vec3 tm){
 vec3 pb =p;
 vec3 pc = p;
  pc.xy *= rot(tm.y);
 vec3 pnc =pc;

 vec3 pn = p;
 vec3 pl = p;
 p = abs(p);
 p -= 1.;
 if(p.x>p.y)p.xy=p.yx;
 if(p.x>p.z)p.xz=p.zx;
 vec3 p2 = p;
 vec3 rp1 = vec3 (2.);
 p = mod(p,rp1)-0.5*rp1;
 vec3 rp2 = vec3 (4.);
 p2 = mod(p2,rp2)-0.5*rp2;
 float d1 = bl(p.zy,vec2(0.2));
 float d2 = bl(pn.xz,vec2(5.));
 float d4 = bl(p2.xz,vec2(0.1));
 float dl =min(d1,d4);
 float d3 = max(min(d1,d4),-d2);
 zl1 = max(d4,-d2);
 //return d3;
 pc = abs(pc);
 pc += 3.;
 if(pc.x<pc.y)pc.xy=pc.yx;
 if(pc.y<pc.z)pc.yz=pc.zy;
 vec3 pc2 = pc;
 vec3 rc1 = vec3(0.1,0.3,0.55);
 pc = mod(pc,rc1)-0.5*rc1;
 vec3 rc2 = vec3(0.005,0.3,0.2+fract(time*0.1));
 pc2 = mod(pc2,rc2)-0.5*rc2;
 float c1 = box(pc,vec3(0.1));
 float c2 = min(box(pnc,vec3(2.5,0.2,0.5)),box(pnc,vec3(0.5,5.,0.5)));
 float c4 = box(pc2,vec3(0.02));
 float c5 = min(length(pn)-tm.z*2.5,length(pc)-tm.z*0.2);
 float c3 = max(max(min(c1,c4),c2),-c5);
 float cl = min(max(c4,c2),length(pn)-tm.z*2.5);

 zl2 = cl;
 float fl2 = 0.01;
 bl2 += fl2 /(fl2+cl);
 float r2 = min(d3,c3);
 pb += vec3(0.,-5.,0.);
 vec3 pb2 = pb;
 vec3 pb3 = pb;
 float ft = 6.38/12.;
 float at = mod(atan(pb.y,pb.x)+0.5*ft,ft)-0.5*ft;
 pb.xy = vec2(cos(at),sin(at))*length(pb.xy);
 float at2 = mod(atan(pb2.y,pb2.z)+0.5*ft,ft)-0.5*ft;
 pb2.zy = vec2(cos(at2),sin(at2))*length(pb2.zy);
 float at3 = mod(atan(pb3.z,pb3.x)+0.5*ft,ft)-0.5*ft;
 pb3.xz = vec2(cos(at3),sin(at3))*length(pb3.xz);
 float b1 = box(pb-vec3(2.5,0.,0.),vec3(tm.x,0.02,0.02));
 float b2 = box(pb2-vec3(0.,0.,2.5),vec3(0.02,0.02,tm.x));
 float b3 = box(pb3-vec3(2.5,0.,0.),vec3(tm.x,0.02,0.02));
 float b5 = length(pn)-tm.z*5.;
 float b4 = max(min(min(b1,b3),b2),-pn.y+5.);

 float fl3 = 0.01;
 bl3 += fl3 /(fl3+b4);
 zl3 = b4;
 float r3 = min(r2,b4);
 return r3;
 }
 vec3 nor (vec3 p,vec3 tm){vec2 e = vec2(0.01,0.); return normalize(map(p,tm)-vec3(map(p-e.xyy,tm),map(p-e.yxy,tm),map(p-e.yyx,tm)));}
void main(void)
{
       vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);
 vec2 uc = uv;
       uv -= 0.5;
       uv /= vec2(v2Resolution.y / v2Resolution.x, 1);
 float t1 = pow(sin(time*0.5)*0.5+0.5,10.);
 vec3 p = vec3(0.,t1*20*sin(time*0.25)+3.,-5.);
 float tmx = mod(time*5.,floor(fract(time*0.1)*10.)/10.+0.1)*1.1;
 vec3 r = normalize(vec3(uv,0.4+fract(time*3.)*0.1));

 float tmy = mix(pow(fract(time*0.1),10.),pow(1.-fract(time*0.1),0.1),step(0.5,fract(time*0.05)));
 float tmz = smoothstep(0.5,0.9,fract(time*0.2));
 vec3 tm = vec3(tmx,tmy,tmz);
 p.xz*= rot(time);
 r.xz*= rot(time);
 r.zy *=rot(t1*2.);
 float dd = 0.;
 for(int i = 0 ; i < 48 ; i++){
   float d = map(p,tm);
   if(dd>40.){break;}
   if(d<0.01){break;}
   p += r*d;
   dd +=d;
 }
 vec3 n = nor(p,tm);
 float tex = rd(p*30.);
 float s = smoothstep(40.,0.,dd);
 float dn = smoothstep(0.,2.,length(p.y))*smoothstep(0.,2.,length(p.x))*smoothstep(0.,2.,length(p.z));
 float ml = distance(0.5,fract(p.x*0.1+time*2.));
 float l1 = smoothstep(2.,0.,zl1)*0.2+smoothstep(3.,0.,zl1)*0.1*smoothstep(0.,0.5,ml)*dn;
 l1 += smoothstep(1.,0.,zl1)*1.5*smoothstep(0.25,0.26,ml);
 float l2 = smoothstep(0.05,0.,zl2)*2.+bl2*0.05;
 float l3 = smoothstep(0.05,0.,zl3)*2.+bl3*0.5;
 float ld = clamp(dot(n,-r),0.,1.);
 float fres = pow(1.-ld,3.+tex*6.)*0.1;
 float spec = pow(ld,5.+tex*10.)*0.2;
 float b = sqrt(24.);
 float c = 0.;
 float d = pow(length(uv.y),2.)*0.03+0.0001;
 float r0 = (fres+spec+l1+l2+l3)*s;
 for(float j = -0.5*b;j <=0.5*b;j++)
 for(float k = -0.5*b;k <=0.5*b;k++){
   c += texture(texPreviousFrame,uc+vec2(j,k)*d).a;
 }
 c /= 24.;
 float tr = step(0.7,fract(time*0.3));

 vec3 r1 = mix(vec3(1.),3.*abs(1.-2.*fract(c*0.4+mix(0.45,0.85,tr)+vec3(0.,-1./3.,1./3.)))-1.,mix(0.25,0.8,tr))*c;
 vec3 r2 = pow(r1,mix(vec3(0.55,0.8,0.7),vec3(1.2),length(uv.y)));

       out_color =vec4(r2,r0);
}