#extension GL_OES_standard_derivatives : enable

precision highp float;

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
#define iTime mod(time,360.)
//東京
mat2 rot(float a){float c=cos(a),s=sin(a);return mat2(c,-s,s,c);}
float box(vec2 p,vec2 b){
   vec2 q = abs(p)-b;
   return length(max(vec2(0.),q))+min(0.,max(q.x,q.y));
}
float box3(vec3 p,vec3 b){
   vec3 q =abs(p)-b;
   return length(max(vec3(0.),q))+min(0.,max(q.x,max(q.y,q.z)));
}
float tokyo(vec3 p){
       p*=2.;
       vec3 op = p;
       p.x -=6.;
       float d = box3(p-vec3(0.,4.,0.),vec3(5.,1.,1.));
       float q = min(d,box3(p-vec3(0.,0.,0.),vec3(4.,3.,1.)));
       q = max(q,-min(d,box3(p-vec3(0.,0.,0.),vec3(3.,2.,2.))));
       d = min(d,q);
       d =min(d,box3(p,vec3(4.,1.,1.)));
       d = min(d,box3(p,vec3(1.,7.,1.)));
       p.y-=-5.;
       p.x = abs(p.x)-2.;
       p.xy*=rot(-.885);
       d = min(d,box3(p,vec3(1.,2.5,1.)));

       p =op;
       p.x+=6.;
       float d2 = box3(p-vec3(0.,4.,0.),vec3(5.,1.,1.));
       float q2 = min(d2,box3(p-vec3(0.,0.,0.),vec3(4.,3.,1.)));
       q2 = max(q2,-min(d2,box3(p-vec3(0.,0.,0.),vec3(3.,2.,2.))));
       d2 = min(d2,q2);

       d2 = min(d2,box3(p-vec3(0.,5.,0.),vec3(1.,2.,1.)));
       d2 = min(d2,box3(p-vec3(0.,-5.,0.),vec3(1.,2.,1.)));
       d2 = min(d2,box3(p-vec3(1,-6.5,0.),vec3(2.,.5,1.)));
       p.y-=-4.;
       p.x = abs(p.x)-2.;
       p.xy*=rot(-.885);
       d2 = min(d2,box3(p,vec3(.5,2.5,1.)));

       d= min(d2,d);
       return d/2.;
}
float diam(vec3 p,float s){
        p = abs(p);
        return (p.x+p.y+p.z-s)*inversesqrt(3.);
}

vec3 op;
float di(vec3 p){
   float q = 0.;
   vec4 pp = vec4(p,1.1);
   const float cc = 2.;
   for(float i=1.; i<=cc ;i++){
     q += (asin(sin(pp.x))+acos(cos(pp.z)))/pp.a;
     pp*=1.1;
     pp.xyz +=vec3(1.1,2.,3.);
     pp.xyz = abs(pp.xyz);
     pp.xz *=rot(-.785*i+i);

   }
   return q/(cc+pp.a);

}
vec2 sdf(vec3 p){
vec3 tp = p;

  op = p;

   vec2 h;
   p.xy *=rot(p.z*.1);
   p.y= -abs(p.y)+(3.+asin(sin(iTime+p.z*.1))*.5);

   h.x = length(p+1.)-.1;
   p.y +=2.+di(p);
   h.x = min(h.x, box(p.xy,vec2(6.1,.5) ) );
       h.x *=.65;
   h.y = 1.;

   vec2 t;

   tp.xz*=rot(pow(fract(iTime*.3),.125)*3.14);
   tp.xy*=rot(pow(fract(iTime*.3+.5),.125)*3.14);
   t.x = mix(diam(tp,2.5),box3(tp,vec3(1.1)),asin(sin(floor(iTime)+pow(fract(iTime),.5)))*.3+.2);
       t.x =mix(t.x , tokyo(-tp),clamp(sin(time),-.5,.5)+.5);
        tp = op;
   vec4 ttp = vec4(tp,1.);
       ttp.yz*=rot(iTime*.01);
   for(float i=0.;i<=6.;i++){
       ttp*=1.3;
       ttp.xyz = abs(ttp.xzy)-11.;
       ttp.xz*=rot(-.785+i);
           ttp.xy*=rot(i);
       t.x = min(t.x,box3(ttp.xyz,vec3(.5))/ttp.a);
   }

   t.y = 2.;
   h = t.x < h.x ? t:h;
   return h;

}
#define q(s) s*sdf(p+s).x
#define ao(rp,n,k) clamp(sdf(rp+n*k).x/k,.0,1.)
#define gao(rp,n) (ao(rp,n,.1)+ao(rp,n,.5)+ao(rp,n,.7))
vec3 norm(vec3 p,float e){vec2 nv=vec2(-e,e);return normalize(q(nv.xyy)+q(nv.yxy)+q(nv.yyx)+q(nv.xxx));}
vec3 pal(float t){return .5+vec3(.5,.2,.1)*cos(6.28*(vec3(1.,.5,.6)*t+vec3(.0,.1,.2)));}
void main( void ) {

       vec2 position = ( gl_FragCoord.xy / resolution.xy ) + mouse / 4.0;

       vec2 uv = (2.*gl_FragCoord.xy-resolution.xy)/resolution.y;
   vec3 ro = vec3(12.,0.+mouse.y,-6.+mouse.x);
   vec3 rt = vec3(0.);
   vec3 z = normalize(rt-ro);
   vec3 x = (cross(z,vec3(0.,-1.,.0)));
   vec3 y = (cross(z,x));

   vec3 rp = ro;
   vec3 rd = normalize(mat3(x,y,z)*vec3(uv,.9));
   vec3 light = mat3(x,y,z)*vec3(-2.,-1.,-4.);
   vec3 col = vec3(.1);
   for(float i=0.;i<=128.;i++){
       vec2 d = sdf(rp);
       if(length(rp) > 50.) break;
       if(d.x <.001){

           vec3 n = norm(rp,.019);
           vec3 nn = norm(rp,.02+abs(sin(iTime+rp.z*.2))*.01);
                          float dif = dot(normalize(light-rp),n);
                          float spc = max(0.,dot(normalize(rp-ro),reflect(normalize(-light),n)));
                          spc = pow(spc,32.);
               float fr = pow(1.-dot(-rd,n),4.);
               col = vec3(.1)+vec3(.15,.5,.7)*dif+spc*.75;
               float l = length(n-nn);
               float s = step(.01,l);
               col = max(vec3(0.),mix(col-s,col*s, floor(rp.z*.1-.3+di(rp.zzz*.1)*.2)*(gao(rp,n)/3.)*.75+.5));
               col = pow(col,vec3(.8));
               if(d.y ==1.) {col *=smoothstep(10.5,.0,op.z);col += -fr+s*pal(op.z*.1+iTime)*smoothstep(-.1,.1,op.z);}
               break;


       }
       rp +=rd*d.x;

   }

       gl_FragColor = vec4(col,1.0 );

}