#define DTR 0.01745329
#define rot(a) mat2(cos(a),sin(a),-sin(a),cos(a))
#define fft(f) (1-pow(max(1-texture(texFFTSmoothed,pow(64,f)/425).x*0.1,0),sqrt(f)*20))

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

float gy(vec3 p, vec3 s){return (abs(dot(sin(p*s.x),cos((p*s.y).zxy)))-s.z)/(max(s.x,s.y)*1.8);}
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 mp(vec3 p)
{
		vec3 pp=p;
		p.xz*=rot(tt*0.1);
		p.xy*=rot(tt*0.1);
		
		vec3 v=vec3(sin(tt*0.5)*0.2,cos(tt*0.6)*0.2,0);
		sd = gy(p,vec3(3,3,1.)+v);	
		float gy2=gy(p,vec3(1.5,1.5,1.3));
		float an=pow(1.-pow(sin(tt*0.7)*0.5+0.5,3.),6.);
		sd=smin(-sd, abs(length(p) - 2.)-(an+0.1), -0.01);
		float c=length(p)-0.2;sd=min(sd,c);
		gl+=exp(-sd*0.1)*vec3(0.08);
		gl+=exp(-c*2.)*vec3(0.1,1.5,0.1)*0.8;
		sd=abs(sd)-0.001;
	

		if(sd<0.001)
		{	
			io=gy2<-0.1?1.1:-1.;
			oc=io<0.?vec3(0.05,0.05,0.2):vec3(0.1,0.5,0.9);
			oa=io<0.?0.6:0.3;
			ss=vec3(0);
		  vb=vec3(0.);
			ec=2;	
		}
		return sd;
}

void tr(){vb.x=0.;cd=0.;for(tc=1.;tc<512.;tc++){mp(ro+rd*cd);cd+=sd;td+=sd;if(sd<0.0001||cd>128.)break;}}
void nm(){mat3 k=mat3(cp,cp,cp)-mat3(.001);cn=normalize(mp(cp)-vec3(mp(k[0]),mp(k[1]),mp(k[2])));}

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

float occlusion(vec3 ro, vec3 rd, float d)
{
    float td,ta,md=d; 
    while(td<d){
    float m=mp(ro+rd*td);td+=m;
    if(m<md){md=m;ta=td;}
    if(m<0.0001) break;}
    vec3 ep=ro+rd*td;
    float ls=max(mix(dot(nm(ep),-rd),1.-td/d,0.95),0.);
    float ms=0.005;
    return ls+(md<ms&&ls<0.1?1.-max(pow(md/ms,2.5),1.-max(1.-ta/d,0.)):0.)*oa; 
}

void px()
{
  cc=vec3(0.3,0.3,0.6)+length(pow(abs(rd+vec3(0,0.,0)),vec3(3)))*0.3+gl/tc;
  vec3 l=vec3(0.5,0.3,0.8);
  if(cd>128.){oa=1.;return;}
  float df=clamp(length(cn*l),0.,1.);
  vec3 fr=pow(1.-df,3.)*mix(cc,vec3(0.4),0.5);
  float sp=(1.-length(cross(cr,cn*l)))*0.2;
  float ao=min(mp(cp+cn*0.3)-0.3,0.3)*0.4;
  
  //NEW OCCLUSION/SHADOWS TESTING
  vec3 ld = -normalize(cp - vec3(0,2,-5));
  float occ = occlusion(cp+cn*0.05,ld, 10.);
  
 
  cc=mix((oc*(df+fr+ss)+fr+sp+ao+gl/tc),oc,vb.x);
  
  cc-=occ*0.4;
}

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);
  ro=vec3(0,0,-5);rd=normalize(vec3(uv,1));
	tt=mod(time, 260.);
  
	for(int i=0;i<25;i++)
  {
		tr();cp=ro+rd*cd;nm();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);}
    if(max(es,0)%3==0&&cd<128.)rd=cr;es--;
		if(vb.x>0.&&i%2==1)oa=pow(clamp(cd/vb.y,0.,1.),vb.z);
		px();fc=fc+vec4(cc*oa,oa)*(1.-fc.a);if((fc.a>=1.||cd>128.))break;
  }
  col = fc/fc.a;
}

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