in vec2 uv;

out vec4 C;

uniform float u_t;
uniform float u_bpm;
uniform vec3 bg_col;
uniform vec3 main_col;
uniform vec3 silent_col;
uniform vec3 hl_col;

const float PI=acos(-1.);
const float TAU=PI*2.;
const vec2 ep=vec2(.00035,-.00035);
const float far=8.;
const int STEPCNT=64;
const float BEAT_DUR=60./u_bpm;

#include scene_nordlicht24/rand.glsl
//float rand(vec3 p){return dot(fract(sin(p*849.163)*636.164),fract(sin(p*734.845)*936.368));}
float Bayer2(vec2 a) {
    a = floor(a);
    return fract(a.x / 2. + a.y * a.y * .75);
}

#define Bayer4(a)   (Bayer2 (.5 *(a)) * .25 + Bayer2(a))

//float ease(float n){return pow(2.,7.*n-7.);}
float ease(float n){return smoothstep(0.,1.,smoothstep(0.,1.,n));}
// https://www.shadertoy.com/view/lctGRB
mat3 orthBas(vec3 z) {
    z = normalize(z);
    vec3 up = abs(z.y) < 0.99 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, 0.0, 1.0);
    vec3 x = normalize(cross(up, z));
    return mat3(x, cross(z, x), z);
}
float arrow(vec3 p, float thicc){
    p.y*=-1.;
    p.y+=.5;
    vec2 q=abs(p.xy);
    float SQ2 = sqrt(2.);
    float arrow2d = min(max(q.x,q.y),max(-(p.y-1.5), (q.x+(p.y-1.5))*SQ2));
    return max(abs(p.z)+1.-thicc, arrow2d)-1.;
}
float getDist(vec3 p, float time){
    float i_t=floor(time*.25/BEAT_DUR),
          f_t=fract(time*.25/BEAT_DUR);
    float eased_t=min(ease(f_t*2.),1.);
    float t=far;
    p.xy+=vec2(4.)*.5;
    vec2 i_p=floor(p.xy/4.);
    p.xy=(fract(p.xy/4.)-.5)*4.;
    float currAng=floor(rand(vec3(i_t   ,i_p))*4.)*TAU/4.;
    float nextAng=floor(rand(vec3(i_t+1.,i_p))*4.)*TAU/4.;
    if(i_t<2.5) currAng=0.;
    if(i_t<1.5) nextAng=0.;
    float currArr=arrow(vec3((p.xy
        -(vec2(0,-eased_t)*rot(-nextAng))*4.
        )*rot(currAng),p.z)
        ,1.);
    float nextArr=arrow(vec3((p.xy
        -(vec2(0,1.-eased_t)*rot(-nextAng))*4.
        )*rot(nextAng),p.z)
        ,1.);
    if(abs(i_p.x)+abs(i_p.y)<.5 || i_t>.5){
        t=min(t,
        max(
        min(mix(far,currArr,clamp(i_t-min(1.,max(abs(i_p.x),abs(i_p.y))),0.,1.)),nextArr),
        max(abs(p.x),abs(p.y))-1.75)
        );    
    }
            
    return t;
}
vec3 getNorm(vec3 p, float time){
    return normalize(ep.xyy*getDist(p+ep.xyy, time)+ep.yyx*getDist(p+ep.yyx, time)+
    ep.yxy*getDist(p+ep.yxy, time)+ep.xxx*getDist(p+ep.xxx, time));
}
vec3 pathtrace(vec2 p, float time) {
    float i_t=floor(time*.25/BEAT_DUR),
          f_t=fract(time*.25/BEAT_DUR);
    vec3 cd=vec3(mix(vec2(0),vec2(.2,-.2),
             mix(
             smoothstep(0,1,smoothstep(0.,1.,f_t)),
             step(7.5,i_t),
             min(1.,abs(7.-i_t))
             ))
         ,1),
         ro=orthBas(cd)*vec3(p*5.,-4),
         rd=orthBas(cd)*vec3(0,0,1),
         ld=normalize(vec3(.5,-1.,-.1)),
         po=ro,
         att=vec3(1);
    float lbright=.5;
    
    for(int j=0; j<STEPCNT; j++){
        float t=getDist(po,time);
        vec3 no=getNorm(po,time);
        po+=rd*t;
        if(t<ep.x){
            att*=(max(abs(po.x),abs(po.y))<2.)?hl_col:main_col;
            att+=pow(max(dot(-normalize(rd),reflect(ld,no)),0.),2.)*lbright;
            break;
        }
        if(po.z>far){
            att=bg_col;
            break;
        }
    }
    return clamp(att, 0., 1.);
}


vec3 moblur(vec2 p){
    return pathtrace(p,u_t-Bayer4(gl_FragCoord.xy)/50.0);
    
}

void main() {
    vec2 UV=vec2(uv.x*R.x/R.y, uv.y);
    C = vec4(moblur(UV), 1.0);
}
