#version 420 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 texSessions;
uniform sampler2D texShort;
uniform sampler2D texTex1;
uniform sampler2D texTex2;
uniform sampler2D texTex3;
uniform sampler2D texTex4;

layout(r32ui) uniform coherent uimage2D[3] computeTex;
layout(r32ui) uniform coherent uimage2D[3] computeTexBack;

layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything
float diam(vec2 p,float s){p=abs(p);return (p.x+p.y-s)*inversesqrt(3.);}
vec3 hash3d(vec3 p){
    uvec3 q = floatBitsToUint(p);
    q += ((q>>16u)^q.yzx)*1111111111u;
    q += ((q>>16u)^q.yzx)*1111111111u;
    q += ((q>>16u)^q.yzx)*1111111111u;
  return vec3(q)/float(-1u);
}
vec3 erot(vec3 p,vec3 ax,float t){return mix(dot(ax,p)*ax,p,cos(t))+cross(ax,p)*sin(t);}
vec2 sdf(vec3 p){
    vec2 h;
   
    vec3 hp=p;
float sc = 1.;
   
  for(float i=0.;i++<8;){
   
     hp = erot(hp,vec3(0,0,1),hp.z*.2/sc);
      vec3 rnd = hash3d(floor(hp*10))*.01;
     hp+=rnd;
     hp.xy= abs(hp.xy)-3.5*exp(-3*fract(p.z*.01+0*rnd.x+fGlobalTime*.125+i*.1));
     hp*=1.5;
    sc*=1.5;
      hp = erot(hp,normalize(vec3(1,1,.5)),.785*.5);
  }

    h.y= 1.;
   hp = mix(vec3(length(fract(p)-.5)-.50),hp,.5);  
      h.x = min(min(diam(hp.xz,2.5),diam(hp.yz,1.5)),diam(hp.xy,.5))/sc;
   
  
  
    return h;
}
#define q(s) s*sdf(p+s).x
vec3 norm(vec3 p,float ee){vec2 e=vec2(-ee,ee);return normalize(q(e.xyy)+q(e.yxy)+q(e.yyx)+q(e.xxx));}

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 col = vec3(0.);
	
  
  vec3 ro=vec3(0.5,0.5,-5.),rt=vec3(0);
 ro= erot(ro,normalize(vec3(0,1,.5)),fGlobalTime*.1);
  vec3 z= normalize(rt-ro),x=vec3(z.z,0.,-z.x);
  vec3 rd= mat3(x,cross(z,x),z)*normalize(vec3(uv,1.));
  vec3 rp=ro;
  vec3 light = vec3(1.,2.,-3);
  vec2 d;
  float rl=0.;
  for(float i=0.;i++<128;){
       d = sdf(rp);
      if(d.x<.001) break;
      rl+=d.x;
      rp=ro+rd*rl;
    }
    if(d.x<.001){
        vec3 n= norm(rp,.001);
        vec3 ld = normalize(light-rp);
        float dif = max(.005,dot(ld,n));
        float spc = pow(max(0,dot(reflect(ld,n),rd)),32);
        float fre = pow(1+dot(rd,n),4);
        col = mix(vec3(.5)*dif*(mod(floor(fGlobalTime+rl),2)*.7+.1)+spc*.5,col,fre);
        col += (dFdx(rl)*5+dFdy(rl)*5)*vec3(.95,.2,.1);
      }
  col = mix(col,vec3(.95,.2,.1)*.1*mod(floor(uv.x*500)+floor(uv.y*500),2),1-exp(-.001*rl*rl*rl));
                                          //^ Dither sans faire expret, oups
      
  vec3 pcol = texelFetch(texPreviousFrame,ivec2(gl_FragCoord.xy+ivec2(0,3)*max(0,length(uv)-.1)),0).rgb; 
    col = 1*sqrt(col);
col = mix(col,pcol,.7);      
  out_color = vec4(col,1.);
}