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

float smoo( float d1, float d2, float k ) {
    float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
    return mix( d2, d1, h ) - k*h*(1.0-h); }

float bone(vec3 p) {
  p=abs(p);
  float nub = length(p-vec3(0.5,3,0))-0.7;
  float cyl = max(length(p.xz)-0.5,p.y-3.);
  return smoo(nub,cyl,1.);
}

float map(vec3 p) {
  float bi = floor(p.z/4.0+0.5)-0.5;
  float blone=1e15;
  for (int i=0; i<3;++i) {
    vec3 q=p;
    q.xy *= rot((bi+float(i))*1.1-iTime/4.0);
    q.z=mod(p.z+2.,4.)-2.-float(i*4);
    blone=min(blone,bone(q-vec3(6.0,0.0,0.0)));
  }
  return blone;
}

vec3 gn(vec3 p) {
  vec2 e=vec2(0.001,0.);
  return normalize(map(p) - vec3(map(p-e.xyy),map(p-e.yxy), map(p-e.yyx)));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord)
{
	vec2 uv = fragCoord.xy / iResolution.xy;
	
	float aspect = iResolution.x/ iResolution.y;
	uv = (uv* 2.0- 1.0)* vec2(aspect, 1.0)* 1.0;
	
  vec3 ro=vec3(0.,0.,iTime-10.), rd=normalize(vec3(uv,1.0));
  float t=0., d;
  
  for (int i=0; i< 100; ++i) {
    d=map(ro+rd*t);
    if (d<0.01) break;
    t += d;
  }
  vec3 col = vec3(0);
  
  vec3 ld = normalize(vec3(3,4,-13));
  
  if (d<0.01) {
    vec3 n = gn(ro+rd*t);
    col=vec3(0.2);
    col += dot(ld,n) * 0.23;
		col += pow(max(0.,dot(reflect(-ld,n),-rd)),4.)*0.1;
  }
  col=mix(vec3(clamp(length(uv)/9.,0.,1.))/7.,col,exp(-.00001*pow(t,3.)));
  
	col=pow(col,vec3(0.4545));

  fragColor=vec4(col,1);
}
