#define gt iTime*1.15

float t,det=.005, maxdist=300.,lidist=0., drohit=0., ufohit=0., roadhit=0., flohit=0.,coneinside=0.,drofract=0., ufofract=0., drodist, drocone, droroty, drorotx, fg=0.,dtub=0.,eyeglow=0., tenthit=0., headhit=0., monspos, monshit=0.,f=1.,lion=1.,end=0., ray=0., rayglow=0., raytime=0.,tunstart=30.,monstart=330.,notub=0.;
vec3 from, dronedir, dronepos, ufopos, licolor=vec3(1.,.85,.7), mcolor=vec3(0.,1.,0.), grcolor=vec3(1.,.3,.1);
vec2 uv;

float[] data1 = float[](0.,1.,1.,1.,0.,1.,0.,0.,1.,0.,0.,1.,1.,0.,0.,1.,1.,1.,0.,0.,1.,1.,1.,0.);
float[] data2 = float[](1.,0.,0.,0.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.);
float[] data3 = float[](1.,0.,0.,0.,0.,1.,1.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.);
float[] data4 = float[](1.,1.,1.,0.,0.,1.,0.,1.,1.,0.,1.,0.,0.,1.,0.,1.,1.,1.,0.,0.,1.,0.,0.,1.);
float[] data5 = float[](1.,0.,0.,0.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.,0.,1.,0.,0.,1.);
float[] data6 = float[](0.,1.,1.,1.,0.,1.,0.,0.,1.,0.,0.,1.,1.,0.,0.,1.,0.,0.,1.,0.,1.,1.,1.,0.);


float rnd(float p, float t) 
{
    p = fract(p * .1031+gt);
    p *= p + 33.33;
    return step(fract(2. * p*p),t);
}


float title(vec2 p, float it)
{
    float tt=gt-it;
    if (tt<0.||tt>8.) return 0.;
    float t=smoothstep(-1.,.5,sin(5.+tt*.7));
    p.y*=1.5;
    p.x-=.2;
    p*=2.;
    float id=floor(p.x*20.);
    if (id>23.||id<0.) return 0.;
    p.x=fract(p.x*20.);
    float c=0.;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data1[int(id)]*rnd(id,t);
    p.y+=.12;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data2[int(id)]*rnd(id+100.,t);
    p.y+=.12;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data3[int(id)]*rnd(id+200.,t);
    p.y+=.12;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data4[int(id)]*rnd(id+300.,t);
    p.y+=.13;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data5[int(id)]*rnd(id+400.,t);
    p.y+=.13;
    c+=step(.2,p.x)*step(.9,p.y)*step(p.y,1.)*data6[int(id)]*rnd(id+500.,t);
    p.y+=.13;
    return c;
}



float hash(vec2 p)
{
	vec3 p3  = fract(vec3(p.xyx) * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}


mat3 lookat(vec3 dir, vec3 up) 
{
	dir=normalize(dir);vec3 rt=normalize(cross(dir,normalize(up)));
    return mat3(rt,cross(rt,dir),dir);
}


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

vec3 path(float t)
{
    float s=sin(t*.1),c=cos(t*.05);
    vec3 p=vec3(vec2(s*s,c*c*c)*5.,t);
    p.y+=smoothstep(.0,.5,abs(.5-fract(t*.02)))*10.;
    return p;
}

float fractal(vec2 p, float anim, int iter)
{
    p=abs(10.-mod(p,20.))-10.;
    float ot=1000.;
    for (int i=0; i<iter; i++)
    {
        p=abs(p)/clamp(p.x*p.y,.25,1.)-2.;
        ot=min(ot,abs(p.y)+.7*anim*fract(abs(p.x)*.1+gt*.5+float(i)*.25));
        
    }
    ot=exp(-5.*ot);
    return ot;
}

float box(vec3 p, vec3 l)
{
    vec3 c=abs(p)-l;
    return length(max(vec3(0.),c))+min(0.,max(c.x,max(c.y,c.z)));
}


float kset(vec3 p, float g)
{
    float m=100.,z=p.z*.2;
    p=abs(fract(p*.1)-.5);
    for (int i=0; i<5;i++)
    {
        p=abs(p);
        p=p/dot(p,p)-.8;
        m=min(m,abs(length(p)-.5));
    }
    m=exp(-2.*m);
    fg+=max(0.,.7-m)*(1.+sin(p.x*4.+t)*1.)*roadhit*g;
    return m;
}


vec3 sky(vec3 dir)
{
	float s=.5,fade=1., fade2=1., pa=0., sd=0.1;
	vec3 v=vec3(0.);
	for (float r=0.; r<5.; r++) {
		vec3 p=s*dir+vec3(.3,.4,.5);
        mat2 rt=rot(r);
        p.xz*=rt;
        p.xy*=rt;
        p.yz*=rt;
		p = abs(1.-mod(p,2.)); 
		float pa,a=pa=0.;
		for (int i=0; i<12; i++) { 
			p=abs(p)/dot(p,p)-.7; 
			float l=(length(p)-(p.x+p.y)*.5)*1.5;
			a+=abs(l-pa); 
			pa=length(p);
		}
		sd+=.5;
		float cv=abs(2.-mod(sd,4.));
		v+=normalize(vec3(cv,cv*cv,cv*cv*cv))*pow(a*.015,2.)*fade; 
		pa=a;
		s+=.01;
	}
	v=mix(vec3(length(v)*.5),v,.5)*.7; 
	return min(vec3(1.),v*f);	
}



float road(vec3 p)
{
    float start=-p.z+tunstart;
    mat2 rot1=rot(p.z*.01+p.x*.02);
    mat2 rot2=rot(radians(-30.*sign(p.y)));
    p.y=-abs(p.y)-3.;
    float z=p.z,d=p.y;
    p.z=mod(p.z,10.)-5.;
    float der=1., sc=1.1;
    float m=100.;
    for (int i=0; i<5; i++)
    {
        p=abs(p);
        der*=sc;
        p=p*sc-1.5;
        p.xz*=rot1;
        p.yz*=rot1;
        p.xy*=rot2;
    }
    d=max(d, -box(p,vec3(5.,5.,20.))/der);
    d=max(abs(d)-.5, start);
    return d*.5;
}


float disk(vec3 p){
    p-=ufopos;
    float l=length(p)-20.;
    if (l>.1&&ray<.5&&drocone>1.) return l;
    p.xz*=rot(gt*.2);
    p/=4.;
    vec2 pr=vec2(atan(p.x,p.z)*2.,length(p)-.75);
    ufofract=fractal(pr,0.,6);
    p.y+=ufofract*.05;
    float r=1.-pow(length(p.xz),2.)*.055,disk=max(max(abs(p.y)-r,length(p.xz)-4.),-length(p.xz)+1.);
    return disk*3.;
}

float monster(vec3 p){
    p.xy-=path(p.z+5.).xy; 
    p.z-=monspos;
    p.y+=raytime*1.5;
    p.yz*=rot(sin(-raytime*.1)*.5);
    p*=.7;
    float l=length(p.xy)-2.;
    if (l>.1&&ray<.5&&drocone>1.) return l;
    p.xy*=rot(gt*2.*(1.-ray)+p.z*.2*smoothstep(0.,20.,p.z));
    vec3 p2=p;
    p.xy=abs(p.xy)-.7+cos(p.z+1.)*.8*smoothstep(10.,0.,p.z);
    float cyl=length(p.xy)-.2*smoothstep(0.,1.,p.z)-.02-sin(p.z*10.)*.03;
    p=p2;
    cyl=max(cyl,-p.z);
    p.z-=4.;
    float sph=length(p)-1.8-sin(atan(p.x,p.y)*10.)*.05-sin(p.z*20.)*.05;
    sph=min(sph,max(length(p.xy)-.5,-p.z));
    float d=cyl;
    d=min(d,sph);
    p.z+=1.7;
    float eye=length(p)-.4;
    d=min(d,eye);
    eyeglow+=.2/(.5+eye*20.);
    headhit=step(sph,d);
    tenthit=step(cyl,d);
    return d;
}

float drone(vec3 p) 
{
    float l=length(p)-3.;
    if (l>.1) return l;
    p.yz*=rot(-droroty*step(1.15,abs(p.x)));
    drofract=fractal(p.xy*.5,0.,6);
    float dro=max(length(p)-3.+pow(drofract,.1)*.3,-length(p+vec3(0.,0.,3.))+.6);
    p.x=abs(abs(p.x)-1.1)-.1;
    dro=max(dro,-abs(p.x)+.07)*.6;
    return dro;
}


float de(vec3 p)
{
    vec3 p2=p;
    p-=dronepos;
    p=lookat(dronedir,vec3(0.,1.,0.))*p;
    p.xz*=rot(drorotx);
    p.yz*=rot(droroty);
    drocone=max(length(p.xy)+p.z*.25+.3,p.z+2.8)+10.-lion*10.;
    float dro=drone(p);
    p.z+=2.;
    float drolight=length(p)-.5;
    p=p2;
    p.xy-=path(p.z).xy;
    float roa=road(p);
    float k=kset(p*.2,0.)*2.*smoothstep(100.,20.,abs(p.x));
    float flo=(p2.y+2.-smoothstep(-10.,tunstart,p2.z)*20.*smoothstep(200.,0.,abs(p2.x))+k);
    float hue=length(p.xy)-17.;
    flo=max(flo,-hue+k*.5)*.5;
    roa-=kset(p2,1.)*.4*f;
    float d=min(dro,drolight);
    float tub=(length(abs(p.xy*rot(p2.z*.05+.7))-6.+sin(p.z*.5)*.5)-.5-sin(p.z*30.)*.02)*.5;
    float ufo=disk(p2);
    float mons=monster(p2);
    float rayo=length((p2-ufopos).xz)-.5;
    drocone=max(drocone,-roa+.1);
    drocone=max(drocone,-tub+.5);
    drocone=max(drocone,-flo+2.);
    drocone=max(drocone,-ufo+1.);
    d=min(d,drocone);
    d=min(d,roa+.2);
    d=min(d,tub+notub);
    d=min(d,flo);
    d=min(d,ufo);
    d=min(d,mons);
    d=min(d,rayo+1.-ray);
    dtub=step(tub,d);
    drohit=step(dro,d);
    ufohit=step(ufo,d);
    roadhit=max(step(roa,d),dtub);
    flohit=step(flo,d);
    monshit=step(mons,d);
    coneinside=step(drocone,d);
    lidist=.1/(.002+drolight*drolight*2.);
    rayglow+=.2/(.1+rayo*.2*smoothstep(20.,0.,-p2.y+raytime*.5));
    if (coneinside>.5 && d<.1) return clamp(abs(d),.2,.25);
    fg*=max(0.,1.-d*.1)*(1.-dtub);
    return d;
}

vec3 normal(vec3 p)
{
    vec2 e=vec2(0.,det);
    return normalize(vec3(de(p+e.yxx),de(p+e.xyx),de(p+e.xxy))-de(p));
}

float ao(vec3 p, vec3 n) {
	float st=.05;
	float ao=0.;
    for(float i=0.; i<6.; i++ ) {
        float td=st*i*i;
        float d=de(p+n*td);
        ao+=max(0.,(td-d)/td);
    }
    return clamp(1.-ao*.3,0.,1.);
}


vec3 matrix(vec3 p)
{
    vec3 n=normalize(p-dronepos);
    p.xy-=path(p.z).xy;
    float c=0.;
    if(coneinside<.5) c+=(fractal(p.xy,2.,5)+fractal(p.xz,2.,5)+fractal(p.yz,2.,5));
    c=c*(1.-drohit)+drohit*drofract*.5; // optimizar
    return grcolor*c*c*2.;
}


vec3 march(vec3 from, vec3 dir)
{
    float ns;
    vec3 p, col=vec3(0.),cl=col;
    float dl=0.;
    float d, td=0.,foff;
    float h=(.5-hash(gl_FragCoord.xy+gt*10.))*.15;
    for (int i=0; i<300; i++)
    {
        p=from+td*dir;
        d=de(p)*(1.+h);
        if (d<det || td>maxdist) break;
        td+=d;
        det*=1.+td*.0;
        if (f<.5) col+=matrix(p)/(2.+d*d*30.)*exp(-.001*td*td)*step(1.,td)*.5;
        foff=exp(-.2*distance(p,dronepos));
        cl+=(coneinside+.0*dtub)/(1.+d*d)*mix(grcolor,licolor,f)*foff;
    }
    float fade=exp(-.001*td*td);
    if (d<.1) {
        vec3 n=normal(p);
        float camli=max(0.,dot(normalize(dronepos-p),n));
        col+=camli*(.5+dtub)*fade*f*(roadhit+flohit)*mix(vec3(1.),licolor,lion)*foff*8.;
        col+=f*(drohit+ufohit*.5)*.2*max(0.,dot(dir,-n))*licolor;
        float fr=pow(drofract,.4);
        col-=f*smoothstep(.8,.9,fr)*.2*drohit;
        col+=f*smoothstep(.31,.3,fr)*.2*drohit;
        fr=pow(ufofract,1.);
        col-=f*smoothstep(.7,1.,fr)*.2*ufohit;
        col+=f*smoothstep(.3,.5,fr)*.15*ufohit;
        col+=1./(.0+drocone)*licolor*f*roadhit*lion*foff;
        col+=10./(5.+drocone*drocone*.2)*licolor*f*roadhit*lion*foff;
        col+=roadhit*grcolor*smoothstep(15.,0.,abs(p.z-monspos-10.))*1.;
        if (roadhit>.5) col=col*max(ao(p,n),max(0.,1.-drocone*.15));
        float k=smoothstep(0.,3.,kset(p*4.,0.));
        if (p.z<tunstart||length(p.xy)>9.) col+=max(0.,n.y)*(.1*k+.2*(1.-flohit))*(1.-drohit)*f*(step(gt,35.)+end);
        if (flohit>.5) col+=k*ao(p,n)*f;
        col+=headhit*monshit*max(0.,dot(-dir,n))*grcolor*.3;
        col*=exp(-.00003*td*td);
    } else {
        col=sky(dir)*smoothstep(-.3,-.1,dir.y);
        
    }
    fg*=smoothstep(59.,60.,gt)*smoothstep(74.,73.,gt)+smoothstep(71.,72.,gt)*0.;
    col+=cl*lion*.07+lidist*(.01+lion)*licolor+fg*grcolor*fade*f*(1.-drohit)*(1.-monshit)+h*.3;
    col+=eyeglow*grcolor*.7+rayglow*.1*ray;
    return col;
}




void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    uv = (fragCoord-iResolution.xy*.5)/iResolution.y;
    uv*=1.5;
    vec2 uv2=uv, uv3=uv;
    //if (abs(uv.y)<.55){
    t=(gt-30.)*5.;
    if(t>monstart-100.) t=t*2.-monstart+100.;
    float s=sin(gt*.25+2.), c=cos(gt*.5+2.);
    float dt=t, drorot=smoothstep(41.,42.,gt), ufot=0., dark=1.;
    drorotx=s*s*s*s*s*4.*drorot;
    droroty=c*c*c*drorot;
    from=path(t+0.)+vec3(13.,-10.,0.);
    vec3 adv=path(t+10.);
    if (gt>35.) {
        from=path(75.)+vec3(0.,-4.,0.);
        adv=path(10.);
        dark=.5;
    }
    if (gt>42.) {
        from=path(t+0.);
        adv=path(t+10.);
        dark=1.;
    }
    if (gt>51.) {
        from=path(150.);
        from.x+=4.;
        from.y+=0.;
        adv=path(140.);
    }
    if (gt>58.) {
        from=path(t+30.);
        adv=path(t+10.);
    }
    if (t>monstart-100.) {
        from=path(monstart);
        adv=path(monstart+1.);
        drorotx=droroty=1.;
    }
    if (t>monstart-50.) {
        dt=monstart*1.8-t-20.;
        from=path(dt+19.);
        adv=path(dt+10.);
        drorotx=smoothstep(monstart-30.,monstart-20.,t)*3.14;
        droroty=0.;
        uv*=3.;
    }
    if (t>monstart) {
        dt=monstart*1.8-t-20.;
        from=path(dt-5.);
        adv=path(dt+5.);
        drorotx=0.;
        droroty=3.14;
        uv*=.5;
    }
    if (t>monstart+70.) {
        from=path(dt+19.);
        from.xy=path(dt+24.).xy;
        adv=path(dt+25.);
        uv*=1.5;
    }
    if (t>monstart+120.) {
        from=path(dt+20.);
        adv=path(dt+15.);
        f=0.;
        uv=uv2;
        uv*=3.;
    }
    if (t>monstart+190.) {
        from=path(dt+8.);
        adv=path(dt+15.);
        f=1.;
        uv=uv2;
        uv*=1.5;
        notub=1.;
    }
    ufopos=path(t+10.); 
    ufopos.y=100.-smoothstep(0.,15.,gt)*50.;
    monspos=-t+monstart*1.8;
    if (t>monstart+315.) {
        raytime=t-monstart-315.;
        ray=1.;
        uv2.x+=sin(gt*50.)*.02;
    }
    dronepos=path(dt+15.-end*10.);
    vec3 droneadv=path(dt+16.);
    dronedir=dronepos-droneadv; 
    dronepos=mix(ufopos,dronepos,smoothstep(10.,20.,gt));
    dronedir=mix(vec3(0.,-1.,.1),dronedir,smoothstep(15.,20.,gt));
    if (t>monstart+240.) {
        monspos+=7.;
        f=end=1.;
        from=vec3(30.,0.,-50.);
        adv=path(max(-45.,monspos));
        adv.y=5.;
        uv=uv2;
        ufopos=path(-45.);
        ufopos.y=20.;
        float s=smoothstep(monstart+290.,monstart+310.,t);
        dronepos=mix(dronepos,ufopos,s);
        dronedir=vec3(0.,.5,1.);
        droroty=-s*2.;
        lion=step(t,monstart+310.);
    }
    if (t>monstart+400.) {
        ufot=t-monstart-400.;
        raytime=0.;
        ray=0.;
        uv=uv3;
        ufopos=path(-45.);
        ufopos.y+=50.+ufot*.5;
        ufopos.x+=10.;
        ufopos.z+=smoothstep(50.,200.,ufot)*500.;
        from=path(-45.);
        from.y+=40.;
        adv=ufopos;
        dronepos=ufopos;
        lion=1.;
        maxdist=1000.;
    }
    if (gt<15.) from.z=-80., from.x=40.,from.y=70.,adv=ufopos;
    vec3 dir=normalize(vec3(uv,1.));
    dir=lookat(adv-from,vec3(0.,1.,0.))*dir;
    vec3 col=march(from, dir);
    col*=vec3(1.2,1.1,1.)*1.2;
    if (ufot>.0) col=mix(vec3(1.),col,min(1.,ufot*.1));
    col*=smoothstep(170.,150.,ufot);
    col=mix(col*dark,grcolor,.8*title(gl_FragCoord.xy/iResolution.xy,30.*1.15));
    fragColor=vec4(col,1.0);
    //}
}
