//CC0 1.0 Universal https://creativecommons.org/publicdomain/zero/1.0/
//To the extent possible under law, Blackle Mori has waived all copyright and related or neighboring rights to this work.

vec3 erot(vec3 p, vec3 ax, float ro) {
  return mix(dot(ax,p)*ax,p,cos(ro))+sin(ro)*cross(ax,p);
}

float linedist(vec3 p, vec3 a, vec3 b) {
  float k = dot(p-a,b-a)/dot(b-a,b-a);
  return distance(p, mix(a,b,clamp(k,0.,1.)));
}

float linedist(vec2 p, vec2 a, vec2 b) {
  float k = dot(p-a,b-a)/dot(b-a,b-a);
  return distance(p, mix(a,b,clamp(k,0.,1.)));
}

float smin(float a, float b, float k) {
  float h = max(0.,k-abs(b-a))/k;
  return min(a,b)-h*h*h*k/6.;
}

float box(vec4 p, vec4 d) {
  vec4 q = abs(p)-d;
  return length(max(q,0.)) + min(0., max(max(q.x,q.y),max(q.z,q.w)));
}
float box(vec3 p, vec3 d) {
  vec3 q = abs(p)-d;
  return length(max(q,0.)) + min(0., max(q.x,max(q.z,q.y)));
}

vec4 wrot(vec4 p) {
  return vec4(dot(p,vec4(1.)), p.yzw + p.zwy - p.wyz - p.xxx)/2.;
}

float sep;
float t;
float plane;
float obj;
float hiddenball;
float clouds(vec3 p) {
  
  p = erot(p,normalize(vec3(2,3,1)),2.123);
  float d1 = length(abs(asin(sin(p))*.9))-1.;
  p = erot(p,normalize(vec3(1,2,3)),2.453);
  float d2 = length(abs(asin(sin(p))*.9))-1.;
  p = erot(p,normalize(vec3(3,2,1)),0.7821);
  float d3 = length(abs(asin(sin(p))*.9))-1.;
  return (d1+d2+d3)/3.;
}

float airplane(vec3 p) {
  float pln = linedist(p, vec3(.4,0,0), vec3(-.6,0,0))-.1-cos(p.x*2.)*.1;
  float wingskel = linedist(p.xy, vec2(0,.6), vec2(0,-.6))-.15;
  float wing = linedist(vec2(wingskel, p.z), vec2(-.04,0), vec2(-1,0))-.04;
  float tail = linedist(p, vec3(-.65,0,0), vec3(-.85,0,.2))-.13;
  float ruddskel = linedist(p.xy, vec2(-.9,.3), vec2(-.9,-.3))-.1;
  float rudd = linedist(vec2(ruddskel, p.z), vec2(-.04,.28), vec2(-1,.28))-.03;
  return smin(min(rudd,wing), smin(tail,pln,0.2),.1);
}

float blimp(vec3 p) {
  float blmp = linedist(p, vec3(.6,0,0), vec3(-.7,0,0))-.4-cos(p.x*2.)*.1;
  float carriage = linedist(p, vec3(.3,0,-.5), vec3(-.3,0,-.5))-.15;
  p.yz = abs(p.yz);
  p.yz = vec2(max(p.y,p.z),min(p.y,p.z));
  float ruddskel = linedist(p.xy, vec2(-1.,.3), vec2(-.8,-.3))-.2;
  float rudd = linedist(vec2(ruddskel, p.z), vec2(-.04,.0), vec2(-1,.0))-.03;
  return min(min(carriage,blmp),rudd);
}

float hotair(vec3 p) {
  p.z -= .4;
  float ht = length(p)-.7;
  float dimpl = linedist(p, vec3(0), vec3(0,0,-.8))-.2;
  float hollow = linedist(p, vec3(0), vec3(0,0,-1.3))-.18;
  float carriage = box(p-vec3(0,0,-1.3), vec3(.12))-.05;
  carriage = -min(-carriage, box(p-vec3(0,0,-1.), vec3(.12, .12, .3)));
  p.xy = abs(p.xy);
  float lines = linedist(p, vec3(0.1,0.1,-.5), vec3(.1,.1,-1.3))-.01;
  return min(-smin(-smin(ht, dimpl, 0.4),hollow,.01), min(lines,carriage));
}

float helicopter(vec3 p) {
  float body = linedist(p, vec3(.2,0,0), vec3(-.2,0,0))-.35;
  body = smin(body, linedist(p, vec3(.2,0,-.2), vec3(-1.,0,-.2))-.2, .2);
  float tail = linedist(p, vec3(-1.1,0,-.2), vec3(-1.3,0,0))-.13;
  body = smin(body,tail,.1);
  vec3 p2 = p;
  p2.x -= -1.3;
  p2 = erot(p2, vec3(0,1,0), iTime);
  p2.y -=0.15;
  p2.y=abs(p2.y);
  p2.xz = abs(p2.xz);
  p2.zx = vec2(max(p2.x,p2.z),min(p2.x,p2.z));
  p = erot(p, vec3(0,0,1), iTime);
  p.z -=0.44;
  p.yx = abs(p.yx);
  p.yx = vec2(max(p.y,p.x),min(p.y,p.x));
  
  float wingskel = linedist(p.xy, vec2(0,.6), vec2(0,-.6))-.1;
  float wing = linedist(vec2(wingskel, p.z), vec2(-.04,0), vec2(-1,0))-.04;
  float wingskel2 = linedist(p2.xz, vec2(0,.2), vec2(0,-.23))-.06;
  float wing2 = linedist(vec2(wingskel2, p2.y), vec2(-.04,0), vec2(-1,0))-.02;
  return min(body,min(wing,wing2));//smin(min(rudd,wing), smin(tail,pln,0.2),.1);
  
}

float scene(vec3 p) {
  float fl = p.z + 5.;
  
  vec3 pp = p;
  pp.y = asin(sin(pp.y/sep))*sep;
  float roll = pow(sin(fract(t*.03)*3.14/2.),50.) + floor(t*.03);
  pp = erot(pp, vec3(1,0,0),roll*acos(-1.)*2.);
  pp = erot(pp, vec3(0,1,0),sin(t)*.4);
  pp = erot(pp, vec3(0,0,1),cos(t*.5)*.2);
  pp.z += cos(t)*.3;
  pp.y += -sin(t*.5)*.2;
  float air = airplane(pp);
  float blmp = blimp(pp);
  float hot = hotair(pp);
  float heli = helicopter(pp);
  float mixval_a = smoothstep(-.25,.25,sin((iTime+1.)/2.));
  float mixval_b = smoothstep(-.15,.15,sin((iTime+1.)/4.));
  plane = mix(mix(hot, heli, mixval_a), mix(blmp, air, mixval_a), mixval_b);
  //plane = 
  
  
  p.x += mod(t,1000.);
  vec3 p2 = p;
  p2 = erot(p2, vec3(0,0,1),.31233);
  p2.xy = asin(sin(p2.xy/3.)*.97)*3.+3.;
  p2.z += 4.;
  p2 = erot(p2, vec3(0,0,1),t*.3);
  p2 = erot(p2, vec3(0,1,0),t*.2);
  p2 = erot(p2, vec3(1,0,0),t*.1);
  obj = length(min(1.-abs(p2),0.6))-.7;
  
  
  p = erot(p,normalize(vec3(2,3,1)),2.123);
  float d1 = dot(abs(asin(sin(p))*.9),vec3(1))/sqrt(3.)-1.;
  p = erot(p,normalize(vec3(1,2,3)),2.453);
  float d2 = dot(abs(asin(sin(p))*.9),vec3(1))/sqrt(3.)-1.;
  p = erot(p,normalize(vec3(3,2,1)),0.7821);
  float d3 = dot(abs(asin(sin(p))*.9),vec3(1))/sqrt(3.)-1.;
  
  
  
  float ground = mix((d1+d2+d3)/2.5, fl,0.2);
  vec4 reproj = vec4(ground, asin(sin(p*5.))/5.);
  float mx = cos(iTime*.3-fl*.3)*.5+.5;
  mx = smoothstep(0.4,.6,mx);
  mx = smoothstep(0.,1.,mx);
  reproj = mix(wrot(reproj), reproj,mx);
  ground = box(reproj,vec4(.02,.27,.27,.27))-0.04;
  hiddenball = length(reproj+vec4(.2,0,0,0))-.2;
  ground = min(ground, hiddenball);
  return min(min(obj,ground), plane);
}

vec3 norm(vec3 p) {
  mat3 k = mat3(p,p,p)-mat3(0.03);
  return normalize(scene(p)-vec3(scene(k[0]), scene(k[1]), scene(k[2])));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
  vec2 uv = vec2(fragCoord - iResolution.xy*.5)/iResolution.y;

  float sc = smoothstep(.5,.6,cos(iTime/10.+3.));
  t = pow(sin(fract(iTime*.4)*3.14/2.),70.)*2. + floor(iTime*.4)*2. + iTime*.9 + 2.;
  sep = 2.+cos(t*.4);
  vec3 cam = normalize(vec3(1, uv));
  vec3 init = vec3(-5.+sin(t), 0, 0) + cam;
  cam = erot(cam,vec3(0,1,0),.7-sc*.3);
  init = erot(init,vec3(0,1,0),.7-sc*.3);
  float zrot = t*.3;
  cam = erot(cam,vec3(0,0,1),zrot);
  init = erot(init,vec3(0,0,1),zrot); 
  init.z -= sc*4.;
  

  vec3 p = init;
  bool hit = false;
  float dist;
  bool triggered = false;
  bool outline = false;
  float glow = 0.;
  for (int i = 0; i < 150 && !hit; i++) { 
    dist = scene(p);
    glow += 1./(hiddenball*500.+1.);
    if (!triggered) triggered = dist < 0.03;
    if (triggered) {
      float ol = 0.05-dist;
      outline = ol < dist;
      dist = min(ol,dist);
    }
    hit = dist*dist < 1e-6;
    p+=cam*dist;
  }
  vec3 p2 = init;
  for (int i = 0; i < 30; i++) {
    float dd = abs(clouds(p2))+.1;
    p2+=cam*dd;
  }
  float lcoudstr = distance(p2, init);
  float fog = smoothstep(40.,10.,distance(p,init)+ lcoudstr*.5);
  bool pl = plane == dist;
  bool oj = obj == dist;
  vec3 n = norm(p);
  vec3 r = reflect(cam,n);
  float ao = smoothstep(-.1,.1,scene(p+n*.1));
  float diff = ao*length(sin(n*vec3(3,2,2))*.5+.5)/sqrt(3.);
  diff = floor(diff*6.)/6.+.1;
  float spec = length(sin(r*vec3(3,2,2))*.5+.5)/sqrt(3.);
  float fres = 1.-abs(dot(cam,n))*.9;
  vec3 matcol = mix(vec3(0.3,0.7,0.2), vec3(0.7,0.5,0.2), smoothstep(-5.5,-4.5,p.z));
  matcol = mix(matcol, vec3(0.7,0.75,0.9), smoothstep(-4.5,-3.5,p.z));
  if (pl) {
    matcol = vec3(0.9,0.8,0.3);
    float id = floor(p.y/acos(-1.)/sep + 1.5);
    id += floor(iTime);
    matcol = abs(erot(matcol, vec3(1,0,0), id))*.6+.4;
    matcol = abs(erot(matcol, vec3(0,1,0), id*2.3423))*.6+.4;
  }
  vec3 col = matcol*diff + pow(spec,10.)*fres*1.5;
  if (oj) {
    
    float spec2 = length(sin(r*vec3(3,1,1))*.5+.5)/sqrt(3.);
    float spec3 = length(sin(-r*vec3(3,1,1))*.5+.5)/sqrt(3.);
    col = vec3(0.8,0.3,0.2)*floor(spec2*6.)/6.+pow(spec2,10.);
    col += (vec3(0.1,0.3,0.8)*floor(spec3*6.)/6.+pow(spec3,10.))*.7;
    col *=ao;
  }
  vec3 bgcol = vec3(0.4,0.7,0.9);
  if (!pl) {
    col *= 0.7;
  } else {
    col = col*.7+.3;
  }
  col = erot(col,normalize(sin(p)),.02);
  fragColor.xyz = (hit ? mix(bgcol, col,fog) : bgcol) + pow(smoothstep(40.,5.,lcoudstr),10.)*(1.-fog);
  if (outline) fragColor.xyz = mix(bgcol, fragColor.xyz*.2, fog);
  fragColor.xyz = smoothstep(vec3(-.2),vec3(1.2),fragColor.xyz);
  fragColor.xyz += (glow*vec3(0.7,0.3,0.)+glow*.9)*.4;
}
