#version 410 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 sampler1D texFFTIntegrated; // this is continually increasing
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

const float pi=acos(-1);
float t = mod(.4*fGlobalTime,10.*pi);
float ft=floor(t);
float dt=fract(t);
float st=ft+dt*dt;

#define sat(a) clamp(a,0.,1.)

vec2 amod(vec2 p,float m) {
 float a=mod(atan(p.x,p.y),m)-m*.5;
 return vec2(cos(a),sin(a))*length(p);
}
mat2 rot(float a) { float c=cos(a),s=sin(a); return mat2(c,s,-s,c); }
float sphere(vec3 p, float r) { return length(p)-r; }
float caps(vec3 p, float h, float r) {
 p.y-=clamp(p.y,0,h);
 return length(p)-r;
}

float m=0;
float scene(vec3 p) {
 float nz=texture(texNoise,p.xz).r*.001;
 float o=100.;

 vec3 pp=p;
 pp*=vec3(1,10.,1);
 o=min(o,sphere(1.02*pp, 1.)*.1+nz*2.);
 pp-=vec3(0,1.1+.4*sin(t*6),0); o=min(o,sphere(1.12*pp, 1.)*.1+nz*6.);
 pp-=vec3(0,1.1+.4*sin(t*4),0); o=min(o,sphere(1.1*pp, 1.)*.1+nz*6.);
 pp-=vec3(0,1.1+.4*sin(t*10),0); o=min(o,sphere(1.2*pp, 1.)*.1+nz*4.);
 pp-=vec3(0,1.1+.0*sin(t*4),0); o=min(o,sphere(1.2*pp, 1.)*.1+nz*4.);

 vec3 p2=p;
 p2.xz=amod(p2.xz,pi*.01);
 p2.xy*=rot(-pi*.34);
 p2 -= vec3(.55,0,0);
 float plate=caps(p2,1.2-.05*sin(p.x*p.y*p.z*10.),.05-.01*sin(p.x*p.z*20.));
 if(plate<o) m=5.;

 return min(o,plate);
}

vec3 camdir(vec2 uv, vec3 og, vec3 tg, float z) {
 vec3 f=normalize(tg-og);
 vec3 s=normalize(cross(vec3(.3*sin(t+sin(st)),1,0),f));
 vec3 u=normalize(cross(f,s));
 return normalize(f*z+uv.x*s+uv.y*u);
}

vec3 normal(vec3 p) {
 vec2 e=vec2(.001,0);
 return normalize(scene(p)-vec3(scene(p-e.xyy),scene(p-e.yxy),scene(p-e.yyx)));
}

float pales(vec2 uv, float screen, float number) {
 uv*=rot(-t*screen);
 return floor(smoothstep(.1,.2,cos(atan(uv.y,uv.x)*number)));
}

vec4 march(vec3 og, vec3 dir, int it, float tr, float mx) {
 float d=0;
 vec3 p=og;
 for(int i=0; i<it; i++) {
   float h=scene(p)*.8;
   if(abs(h)<tr || d>mx) break;
   d+=h;
   p+=dir*h;
 }
 return vec4(p,d);
}

float shadow(vec3 p, vec3 lp) {
 vec3 ldir=normalize(lp-p);
 float ldist=length(lp-p);
 float d=march(p,ldir,50,.0001,5.).w;
 if(d<ldist) {
   return .5;
 } else {
   return 1.;
 }
}











// Alkama / Spectrals + TPOLM + Calodox
// not the best































// THAT LIVESHADING IS WAY BEYOND THE 25mins LIMIT :D
//
// THOSE PANCAKES ARE IN WARP MODE !!!
// THEY ARE TRAVELING LIGHtSPEED TOWARD A WORLD OF HUGS
//
// EVIL BEARS MIGHT CAPTURE THEM OUT OF THE FLOW
// AND NOMNOMNOMNOMNOMNOM THEM
//
// Dont ask for the mapple syrup, you'll still like them dry
//
// Am uninspired, but it's hard to come with stuffs.
// And it makes me hungry...
//
// Greetings to
// Flopine / Evvvil / Noby / Fizzer / NuSan / Luna / Slerpy / LJ / IQ
// I'm shameless, am not as good, but I try.
//
// A WYV YUU <3
// Alkama / Spectrals (+) TPOLM (+) Calodox

void main(void)
{
 vec2 uv = (gl_FragCoord.xy / v2Resolution - .5) * vec2(v2Resolution.x/v2Resolution.y, 1.);

 vec2 uv2 = uv;
 uv2.xy+=.4*vec2((sin(st)+.2*sin(t*2)),sin(st*.5));
 vec3 bg=vec3(0);
 bg+=pales(uv2,.4,30.);
 bg-=pales(uv2,.2,28.);
 bg+=pales(uv2,-.6,20.);
 bg-=pales(uv2,-.3,18.);
 bg=mix(vec3(1.,.9, .5),vec3(1.,.4, .1),sat(bg));
 float ccc=1.-length(uv2*(1.+.2*sin(t*8.)));
 bg+=ccc;
 bg += .05*step(.9,bg.ggg);
 vec3 col=bg;

 vec3 eye=3.*vec3(.1,.3,.1);
 eye += 2.*vec3(sin(st)+.2*sin(t*2),.2*sin(st*.5),cos(st-sin(t)));
 vec3 target=vec3(.2*sin(st*4),.1*sin(st*2),.2*cos(st));
 vec3 dir=camdir(uv,eye,target,.75);

 vec3 lp=vec3(1,3,-2);
 lp.xz+=1.5*vec2(sin(t*8),cos(t*6));

 vec4 hit=march(eye,dir,400,.001,5.);
 float d=hit.w;
 if(d<5.){
   vec3 p=hit.xyz;
   vec3 n=normal(p);
   vec3 ld=normalize(lp-p);
   float diff=abs(dot(n,ld));
   if(m==0.) {
     float miaou=smoothstep(.96,1.,abs(n.y));
     col=diff*mix(vec3(1.,.9,.5),vec3(1.,.4,.1),miaou);
     col-=pow(texture(texNoise,p.xz*(2.-.5*p.y)).r, 3.);
   } else {
     float spec=sat(pow(abs(dot(dir,reflect(ld,n))),50.));
     float fres=1.-sat(pow(abs(1.-dot(n,-dir)),5.));
     col=sat(vec3(.8+spec)*fres)*cos(dir);
   }
   col*=shadow(p,lp);
 }

 out_color = vec4(pow(col,vec3(1./2.2)), 1.);
}