//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.

float corner(vec2 p) {
  return length(max(p,0.))+min(0.,max(p.x,p.y));
}

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 h_(vec2 p) {
  float l1 = linedist(p, vec2(0,-.75), vec2(0,-10)) - 1.5;
  float l2 = linedist(p, vec2(0,-.5), vec2(0,-10)) - .5;
  float l3 = linedist(p, vec2(-1,10), vec2(-1,-10)) - .5;
  float ud = abs(p.y)-2.5;
  return corner(vec2(ud,min(max(l1,-l2),l3)));
}

float e_(vec2 p) {
  float l1 = linedist(p, vec2(0,-.75), vec2(0,-1.)) - 1.5;
  float l2 = linedist(p, vec2(0,-.5), vec2(0,-1.25)) - .5;
  float l3 = linedist(p, vec2(-1,-.65), vec2(1,-.65)) - .25;
  float ho = linedist(p, vec2(.45,-1.05), vec2(10,-1.05)) - .15;
  return corner(vec2(min(max(l1,-l2),l3),-ho));
}

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

float profile(vec2 p, float stronch) {
  return corner(vec2(abs(p.x)-stronch-.3,p.y+.05))-.05;
}

vec3 gploc;
float letter(vec3 p, bool e, float off) {
  p.z += sin(iTime*3.+off)*.2;
  p = erot(p,vec3(0,1,0),cos(iTime*4.+off)*.1);
  p = erot(p,vec3(0,0,1),sin(iTime*4.+off)*.1);
  p.x += sin(iTime*4.7+off);

  float x = iTime*(5.+sin(off)*.5)+off;
  float stronch = (sin(x)*.5+.5+sin(x*3.)*.2)*3.;

  gploc = p * vec3(1./(stronch+.35),1,1);
  vec2 h = vec2(p.x,e ? e_(p.yz) : h_(p.yz));
  return profile(h, stronch);
}

int gid;
vec3 ggploc;
float scene(vec3 p) {
  p -= vec3(0,-1.2,0);
  float h1 = letter(p-vec3(1,-3,0),false,.4);
  ggploc = gploc;
  gid = 0;
  float e1 = letter(p,true,2.9);
  if (e1 < h1) {

  ggploc = gploc;
    gid = 1;
    h1 = e1;
  }
  float e2 = letter(p-vec3(0,6,0),true,5.9);
  if (e2 < h1) {
    gid = 2;
  ggploc = gploc;
    h1 = e2;
  }
  float h2 = letter(p-vec3(1,3,0),false,4.2);
  if (h2 < h1) {
    gid = 3;
  ggploc = gploc;
    h1 = h2;
  }
  return h1;
}

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

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

  bool ise =  sin(iTime*5.)>0.;

  vec3 cam = normalize(vec3(2,uv));
  vec3 init = vec3(-18.+sin(iTime*3.5)*3.,0,0);

  float yrot = sin(iTime)*.4;
  float zrot = cos(iTime*5.5)*.4;
  float xrot = sin(iTime*2.)*.3;
  cam = erot(cam,vec3(1,0,0),xrot);
  init = erot(init,vec3(0,1,0),yrot);
  cam = erot(cam,vec3(0,1,0),yrot);
  init = erot(init,vec3(0,0,1),zrot);
  cam = erot(cam,vec3(0,0,1),zrot);
  init.z += sin(iTime*5.)*.4;

  vec3 p = init;
  bool hit = false;
  bool inside = false;
  float trigdist = .05;
  for (int i = 0; i < 150 && !hit; i++) {
    float dist = scene(p);
    p += cam*dist;
    hit = dist*dist < 1e-6;
    if (dist < trigdist) {
      inside = true;
    }
    if (inside && dist > trigdist) break;
    if (distance(p,init) > 50.) break;
  }
  vec3 ploc = ggploc;
  float id = float(gid);
  vec3 n = norm(p);
  vec3 r = reflect(cam,n);
  float fact = length(sin(r*4.2)*.5+.5)/sqrt(3.);
  float diff = length(sin(n*2.9)*.4+.6)/sqrt(3.);
  float fres = 1. - abs(dot(cam,n))*.98;
  float spec = (fact*.05 + pow(fact,8.)*2.)*fres;
  vec3 diffcol = vec3(0.7,.1,.05);
  diffcol = erot(diffcol,n,.2);
  diffcol = erot(diffcol,normalize(sin(n*6.)),.2);
  diffcol = min(max(erot(diffcol,normalize(vec3(1,2,3)),id+floor(iTime*3.))*.8+.5,0.05),.9);
  if (dot(sin(erot(ploc,normalize(vec3(1,1,1)),.6*id)*20.),vec3(1)) > 0.5) diffcol = pow(fact,4.)*diffcol*10.;
  vec3 col = diff*diffcol+spec*mix(diffcol,vec3(1),.5);
  float ang = atan(uv.x,uv.y);
  float bg = sin(ang*10.+iTime*2.);
  ang += iTime;
  vec3 rainbow = vec3(sin(ang),sin(ang+3.14/3.),sin(ang+3.14*2./3.))*.4+.6;
  bg = smoothstep(fwidth(bg),0.,bg);
  float circ = length(uv)-.4;
  circ = smoothstep(fwidth(circ),0.,circ);
  vec3 bgcol = vec3(mix(rainbow,vec3(1),bg));

  vec3 fancycol = vec3(0.7,.1,.05);
  fancycol = min(max(erot(fancycol,normalize(vec3(1,2,3)),9.+floor(iTime*3.)*1.3)*.8+.5,0.05),.9);
  bgcol = mix(bgcol,fancycol,circ);
  fragColor.xyz = hit ? col : bgcol;
  if (inside && !hit) fragColor.xyz = vec3(0);
  fragColor *= 1.-dot(uv,uv)*.3;
  fragColor = sqrt(fragColor);
}
