#define time iTime*0.1
#define pi 3.14159265
#define deg pi/180.

mat2 r2d(float a) {
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

float sdBox(vec3 p, vec3 s) {
    return max(abs(p.z)-s.z,max(abs(p.x)-s.x,abs(p.y)-s.y));
}

vec3 isor(vec3 p) {
    p.yz *= r2d(deg*35.265);
    p.xz *= r2d(deg*45.);
    return p;
}

//from https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl
// All components are in the range [0…1], including hue.
vec3 rgb2hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

 

// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}


//#define dtime time*hill(time,10.)
float bitm(vec2 uv,int c) {
    float h = 5.;
    float w = 3.;
    int p = int(pow(2.,w));
    float line1 = 9591.;
    uv = floor(vec2(uv.x*w,uv.y*h))/vec2(w,w);
    float c1 = 0.;
    float cc = uv.x + uv.y*w;
    c1 = mod( floor( float(c) / exp2(ceil(cc*w-0.6))) ,2.);
    c1 *= step(0.,uv.x)*step(0.,uv.y);
    c1 *= step(0.,(-uv.x+0.99))*step(0.,(-uv.y+1.6));
    return (c1);
}
 

vec3 slogo(vec2 uv, float ar, float size) {
    vec2 px = vec2(1./3.,1./5.);
    float ls = 4.1;
    uv.x = 0.993-uv.x;
    uv *= 8.*ls*(1./size);
    ls += 2.;
    float ul = length(uv);
    uv -= px.yx*0.5*0.5*ls;
    ul = length(vec2(uv.x*0.5,uv.y)-0.5);
    uv.x *= ar*1.75;
    int s = 29671;
    int c = 29263;
    int r = 31469;
    int y = 23186;
    uv.x= 5.-uv.x;
    float b = bitm(uv,s);
    uv.x -= 1./3.*4.;
    b += bitm(uv,c);
    uv.x -= 1./3.*4.;
    b += bitm(uv,r);
    uv.x -= 1./3.*4.;
    b += bitm(uv,y);
    float rr = step(0.,uv.x+px.x*13.)*step(0.,uv.y+px.y)*step(0.,(-uv.x+px.x*4.))*step(0.,(-uv.y+px.y*6.));
    b = clamp(b,0.,1.);
    //b = rr*floor(b);
    //float ptime = iTime;
    vec3 l = hsv2rgb(vec3(b+iTime/40.,0.1,rr-b*1.9))*rr;
    //l -= length(uv)*0.5;
    //l -= ul*rr*0.6;
    l -= 0.1-clamp(ul*0.1,rr*1.-b,0.1);
    //l -= 3.-ul*2;
    //l = clamp(l,-1.,1.);
    return vec3(l);
}


vec4 map(vec3 p) {
    vec3 o = p;
    p.z -= 1.;
    p.yz *= r2d(deg*35.265*sin(time));
    p.xz *= r2d(deg*45.+time);
    vec3 ob = isor(p);
    float d = -sdBox(p,vec3(1.01));
    d = min(d,sdBox(ob,vec3(0.01)));
    //p.xz *= r2d(deg*45.);
    p.xz = abs(p.xz);
    p.xz *= r2d(deg*45.);
    p.xy *= r2d(deg*45.);
    p.xy = -abs(p.xy)+0.75;
    p.xy *= r2d(-deg*45.);
    p.xyz -= 0.5;
    float pf = 3.;
    p = (fract(p*pf)-0.5)/pf;
    p.y = abs(p.y);
    p.xz = abs(p.xz);
    p.xz *= r2d(deg*45.);
    p.xy *= r2d(deg*20.);
    
    p.x += 0.15;
    d = min(d,max(sdBox(p,vec3(mix(0.15,0.2,sin(ob.y*4.+time)*0.5+0.5))),-(length(o.z)-0.075)));
    //d = max(d,-(length(o.z)-0.075));
    return vec4(p,d);
}

vec2 RM(vec3 ro, vec3 rd) {
    float dO = 0.;
    float ii = 0.;
    for (int i=0;i<120;i++) {
        vec3 p = ro+rd*dO;
        float dS = map(p).w;
        dO += dS;
        ii *= 0.01;
        if (dO > 100. || dS < 0.001) {break;}
    }
    return vec2(dO,ii);
}

vec3 calcNorm(vec3 p) {
    vec2 h = vec2(0.001,0.);
    return normalize(vec3(
        map(p+h.xyy).w-map(p-h.xyy).w,
        map(p+h.yxy).w-map(p-h.yxy).w,
        map(p+h.yyx).w-map(p-h.yyx).w
    ));
}

vec3 colo(vec3 p, vec3 n, vec2 d) {
    //vec3 col = sin(n+d.y*20.);
    vec3 col = 1.-d.xxx*0.6;
    col *= sin(vec3(0.3,0.36,0.5)*d.x*5.+vec3(0.3,0.8,0.1)*d.y*200.);
    return clamp(col,0.,1.);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec2 R = iResolution.xy;
    vec2 tv = uv;
    float ar = R.x/R.y;
    uv -= 0.5;
    uv.x *= ar;
    float c = length(uv);
    vec3 col = vec3(0.);
    vec3 ro = vec3(0.);
    vec3 rd = normalize(vec3(uv,1.));
    vec2 d = RM(ro,rd);
    vec3 p = ro+rd*d.x;
    vec3 n = calcNorm(p);
    float rl = 0.99;
    //col += d.xxx/5.;
    //col = n;
    col += colo(p,n,d);
    for (int i=0;i<9;i++) {
        ro = p+n*0.003;
        rd = reflect(rd,n);
        d = RM(ro,rd);
        p = ro+rd*d.x;
        n = calcNorm(p);
        col += colo(p,n,d)*rl;
        rl *= rl;
    }
    col *= 0.4;
    col -= 0.2;
    //col *= rl+0.5;
    
    //col -= sin(c*1400.)*0.06;
    col += slogo(tv,ar,1.)/40.;
    //col -= sin(d.x*35200.)*0.05;
    fragColor = vec4(col,1.0);
}
