#define rot(a) mat2(cos(a),sin(a),-sin(a),cos(a))

vec2 uv;
vec3 cp,cn,cr,ss,oc,gl,vb;
vec4 fc,cc;
float tt,cd,sd,md,io,oa,td,tc;
int es=0,ec;


float bx(vec3 p,vec3 s){vec3 q=abs(p)-s;return min(max(q.x,max(q.y,q.z)),0.)+length(max(q,0.));}
float cy(vec3 p, vec2 s){p.y+=s.x/2.;p.y-=clamp(p.y,0.,s.x);return length(p)-s.y;}
float smin(float a, float b, float k){float h=clamp(0.5+0.5*(b-a)/k,0.,1.);return mix(b,a,h)-k*h*(1.-h);}

float hash(vec2 p)
{
    p=fract(p)-cos(p);
    vec2 q=tan(abs(p*37482.34)+p.yx*678324.);
    return fract(q.x+p.x*q.y-p.y);
}

vec2 devide(vec2 r, float p, float a)
{
	float z=r.x+r.y*p;
	if(z<a){r.y=r.x+r.y-z;r.x=z;}
	else r.y=z-r.x;
	return r;
}

float mp(vec3 p)
{
        //now with mouse control
if(iMouse.z>0.){
    p.yz*=rot(2.0*(iMouse.y/iResolution.y-0.5));
    p.zx*=rot(-7.0*(iMouse.x/iResolution.x-0.5));
}
		vec3 pp=p;
        sd = length(p) - 1.3;
        p=pp;
		float m = (tt+pow(sin(tt+cos(tt*0.5)*2.)*0.5+0.5,3.)*5.)*0.2;
		for(float i = 0.; i < 2.; i++)
		{
			p.xy = abs(p.xy * rot(i*2.5+m*0.9)) - 1.;
			p.xz = abs(p.xz) * rot(i+m*0.7);
		}
		float axis = p.x;
		vec2 range = vec2(-4,8);
        sd=min(sd,cy(p,vec2(2,0.2)));
		for(float i = 0.; i < 3.; i++)
		{
			float pos = clamp(sin(tt*0.7+i)*0.5+0.5,0.3,0.7);
			range = devide(range, pos, axis);
		}
		p.x -= range.x + range.y * 0.5;
		sd=smin(sd,bx(p,vec3(range.y/2.-0.1,0.5,0.5))-0.03,0.1);
		if(sd>0.01 && mod(range.x,5.)>2.) gl += exp(-sd*0.5) * normalize(p*p)*vec3(0.5,0.01,0.5) / (length(pp));
		sd=abs(sd)-0.001;

		if(sd<0.06)
		{	
			io=range.y > 1. ? -1. : 3.;
			oc=mix(vec3(1,0.3,0.6),vec3(0.4,0.3,1),sin(range.x*3.)*0.5+0.5);
			oa=0.4;
			ss=vec3(0.);
			ec=2;	
		}
		return sd;
}

void nm(){mat3 k=mat3(cp,cp,cp)-mat3(.001);cn=normalize(mp(cp)-vec3(mp(k[0]),mp(k[1]),mp(k[2])));}

float tr(vec3 ro, vec3 rd)
{cd=0.;md=64.;for(tc=1.;tc<512.;tc++){mp(cp=ro+rd*cd);cd+=sd;td+=sd;
if(sd<md&&sd<cd-0.06)md=sd;if(sd<0.0001||cd>64.)break;}nm();return cd;}


void px(vec3 rd)
{
  cc.rgb=vec3(0.25,0.4,0.7)+length(pow(abs(rd+vec3(0,0.,0)),vec3(3)))*0.3+gl/tc;
  if(cd>64.){cc.a=1.;return;}cc.a=oa;
	vec3 ld = -normalize(cp+cn-vec3(5.,1,-10.));
  float df=clamp(length(cn*ld),0.,1.),
	sp=(1.-length(cross(rd,cn*ld)))*0.8,
    ao=min(mp(cp+cn*0.3)-0.3,0.3)*0.5;
  vec3 fr=pow(1.-abs(dot(rd,-cn)),3.)*mix(cc.rgb,vec3(0.4),0.3)*0.8;
  cc.rgb=(oc*(df+fr+ss)+fr+sp+ao+gl/tc);tr(cp+cn*0.06,ld);
    float sh=1.-mix(1.-clamp(md/0.06,0.,1.),clamp(dot(cn,-ld),0.,1.),0.1)*(io>0.?oa:1.)*0.5; //yay I made shadows work
	cc.rgb=mix(mix(vec3(sh),oc, 0.5),cc.rgb, sh)*sh;
}

void render(vec2 frag, vec2 res, float time, out vec4 col)
{
  uv=vec2(frag.x/res.x,frag.y/res.y);
  uv-=0.5;uv/=vec2(res.y/res.x,1);
  tt=mod(time+3.,256.);
  vec3 ro=vec3(0,0,-7.-sin(tt*0.6)*1.+1.),rd=normalize(vec3(uv,1));
  for(int i=0;i<25;i++)
  {
	float d=tr(ro,rd);
	ro=cp-cn*(io<0.?-0.01:0.01);
	cr=refract(rd,cn,i%2==0?1./io:io);
	i=io<0.?i+1:i;
    if((length(cr)==0.&&es<=0)||io<0.)
	{cr=reflect(rd,cn);es=(io<0.?es:ec);}
	px(rd);if(max(es,0)%3==0&&d<64.)rd=cr;es--;
	fc=fc+vec4(cc.rgb*cc.a,cc.a)*(1.-fc.a);
	if(fc.a>=1.)break;
  }
  col = pow(fc/fc.a,vec4(0.9));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    render(fragCoord.xy,iResolution.xy,iTime,fragColor);
}
