// NOTE: This source is minified and hard to read
// there are also some minute changes to accomodate the ES 2.0 spec.

// Works on AMD, might not show or bug out on other vendors
#define BUBBLES

float x=.001,v=0.,y=0.,f=0.,z=0.,d=0.,r=0.,e=0.,g=0.,o=0.,t=0.,a=0.,l=0.,i=0.,u=0.,h=0.,b=0.,C=0.;
vec3 Y;
float p(float v,float g)
{
	return v*g*exp(1.-v*g);
}

// global initializations in webgl must be constants
// this hack circumvents that
void updateglobals()
{
    v=iTime*2.7;
    y=p(9.,mod(clamp(v,19.,99.),2.5223));
    f=p(3.,mod(clamp(v,19.,99.),2.5223));
    z=1.5-smoothstep(151.,199.,v);
    d=pow(smoothstep(151.,199.,v),2.);
    r=1.+9.*smoothstep(-100.,100.,-v);
    e=smoothstep(208.,228.,v);
    g=smoothstep(254.,260.,v);
    o=smoothstep(331.,340.,v);
    t=smoothstep(40.,80.,v);
    a=pow(smoothstep(101.,105.,v),.5);
    l=1.-smoothstep(204.,205.,v);
    i=smoothstep(214.,225.,v);
    u=smoothstep(222.,240.,v);
    h=smoothstep(242.,244.,v);
    b=1.+8.*p(3.,clamp(v-204.,0.,99.));
    C=v+.6*max(0.,f);
    Y=9.*vec3(sin(v*.8),1,cos(.63*v));
}

mat3 p(float v)
{
	return mat3(1.,0.,0.,0.,cos(v),-sin(v),0,sin(v),cos(v));
}

mat3 n(float v)
{
	return mat3(cos(v),0.,sin(v),0.,1.,0.,-sin(v),0.,cos(v));
}

mat3 s(float v)
{
	return mat3(cos(v),-sin(v),0.,sin(v),cos(v),0.,0.,0.,1.);
}

float w(float v)
{
	return fract(sin(dot(v,12.9898))*43758.5);
}

float n(float v,float m,float x)
{
    float s=clamp(.5+.5*(m-v)/x,0.,1.);
    return mix(m,v,s)-x*s*(1.-s);
}

float n(vec3 v,float x)
{
    return length(v)-x;
}

float s(vec3 v,vec3 x)
{
    return length(max(abs(v)-x,0.));
}

float p(float v,float m,float x)
{
    return min(min(v,m),v-(x+min(v,m))+m);
}

float c(vec3 v)
{
    vec3 s=floor(v),f=fract(v);
    f=f*f*(3.-2.*f);
    float x=s.x+s.y*57.+113.*s.z;
    return mix(mix(mix(w(x),w(x+1.),f.x),mix(w(x+57.),w(x+58.),f.x),f.y),mix(mix(w(x+113.),w(x+114.),f.x),mix(w(x+170.),w(x+171.),f.x),f.y),f.z);
}

float c(vec3 v,float x)
{
    v.y-=x/2.;
    vec3 m=abs(v);
    return max(v.y,(m.x+m.y/1.2+m.z-x)/3.);
}

float k(vec3 x)
{
	return x.y+=20.-20.*t-.53*u,x=(x+vec3(.7,1.,.8))*p((v-101.)*.34*a*l)*n((v-101.)*.41*a*l)*s((v-101.)*.23*a*l),mix(max(c(x*n(v*.13),1.5+2.*h),-c(vec3(x.x,-x.y+.4,x.z)*n(v*.13)*p((v-260.)*.24*g)*s((v-260.)*.23*g),1.5*(1.-l)*(1.-h)+3.*g)),min(min(min(n(x+r*vec3(0.,.4883,0.),.6),n(x+r*vec3(-.3554,-.4883,-.6),.6)),n(x+r*vec3(.6838,-.4883,0.),.6)),n(x+r*vec3(-.3554,-.4883,.6),.6)),a-(1.-l)+o);
}

float F(vec3 x)
{
    float m=c(vec3(x.x,x.y,x.z)*(12.-3.*d)),f=s(vec3(x.x,x.y-.5-.2*(sin(x.z*.6)+cos(x.x*.6))-.004*m,x.z),vec3(9.,0.,9.)),y=k(x);
    vec3 w=mod(x,z+g)-.5*(z+g);
    float i=s(vec3(w.x+g*.1*sin(2.*x.y+2.*x.z+v),x.y,w.z+g*.1*cos(2.*x.y+2.*x.x+v)),vec3(.25,.81,.25)),l=s(vec3(w.x+g*.1*sin(2.*x.y+2.*x.z+v),x.y+.25,w.z+g*.1*cos(2.*x.y+2.*x.x+v)),vec3(.29,.04,.29)),r=max(-y+.3-.3*e+.6*h+.6*g,min(i,l)+(.00114+.0001*d-.0001*g)*m);
    return min(n(f,r,.3),y);
}

float q(vec3 v)
{
	return v.zx+=.1*vec2(c(v.yzx+C*.78),c(v.zxy+C*.91)),pow(c(7.*vec3(v.x,220.+v.y+mod(C*.1,10.),v.z)),1.2);
}

vec3 Z(vec3 v)
{
    float x=.01;
    return normalize(vec3(F(v+vec3(x,0.,0.))-F(v-vec3(x,0.,0.)),F(v+vec3(0.,x,0.))-F(v-vec3(0.,x,0.)),F(v+vec3(0.,0.,x))-F(v-vec3(0.,0.,x))));
}

float F(vec3 v,vec3 x,float m,float y,float f)
{
    // WebGL version of soft shadows, courtesy of iq
    float res = 1.0;
    float t = m;
    for( int i=0; i<16; i++ )
    {
		float h = F( v + x*t );
        res = min( res, f*h/t );
        t += clamp( h, 0.02, 0.10 );
        if( h<0.001 || t>y ) break;
    }
    return clamp( res, 0.0, 1.0 );
    // original shadows
    /*
    float i=1.;
    for(float s=m;s<y;)
    {
        float c=F(v+x*s);
        if(c<.001)
        return 0.;
        i=min(i,f*c/s);
        s+=c;
    }
    return i;
	*/
}

float Z(vec3 v,vec3 x,float m,float y,float f)
{
    float res = 1.0;
    float t = m;
    for( int i=0; i<16; i++ )
    {
		float h = k( v + x*t );
        res = min( res, f*h/t );
        t += clamp( h, 0.02, 0.10 );
        if( h<0.001 || t>y ) break;
    }
    return clamp( res, 0.0, 1.0 );
    /*
    float i=1.;
    for(float s=m;s<y;)
    {
        float c=k(v+x*s);
        if(c<.001)
        return 0.;
        i=min(i,f*c/s);
        s+=c;
    }
    return i;
	*/
}

vec3 F(vec3 x,float s)
{
    vec3 m=normalize(x-Y);
    float g=max(0.,dot(m,Z(x)));
    vec3 f=x*5.,r=mix(vec3(.7,.55,.47),vec3(.75,.61,.41),clamp(9.*x.y-1.,0.,2.))+2.*y*.2*c(vec3(f.x+v,1.,f.z+v))-.1*c(vec3(1.75*f.x-v,v,1.75*f.z-v));
    return vec3(.4,.65,.7)/clamp(vec3(.3*s),.7,32.)*r*1.25*vec3(.85,.7,.55)*(.2+.8*g)*(.2+.8*F(x,m,.06,80.,2.));
}

vec3 Z(vec3 v,vec3 s)
{
    vec3 m=vec3(0.);
    float f,i;
    f=i=0.;
    for(int g=0;g<30;++g)
    {
        m=v+f*s;
        i=F(m);
        f+=i;
        if(20.<f||abs(i)<x)
        break;
    }
    return F(m,f);
}

vec3 k(vec3 v,vec3 m)
{
    vec3 f=vec3(0.);
    float s,i;
    s=i=0.;
    for(int g=0;g<30;++g)
    {
        f=v+s*m;
        i=F(f);
        s+=i;
        if(20.<s||abs(i)<x)
        break;
    }
    if(k(f)<x)
    {
        vec3 g=Z(f);
        return(.45+.75*max(0.,min(1.,.8+.5*(1.+dot(s*m,g)))))*(.6*Z(f+.1*g,m-2.*dot(m,g)*g)+.4*pow(F(f,s),vec3(.4))+.4*pow(max(dot(normalize(m-Y),g),0.),80.));
    }
    return F(f,s);
}

vec3 q(vec3 v,vec3 m)
{
    vec3 f=vec3(0.);
    float s,i,c,y,g,r=1.;
    s=i=c=y=g=0.;
    for(int l=0;l<90;++l)
    {
        f=v+s*m;
#ifdef BUBBLES
        // only works properly on AMD
        i=min(F(f),q(f));
#else
        i=F(f);
#endif
        s+=i;
        y+=b*.01*pow(i,1.6)/k(f);
        vec3 w=normalize(f-Y);
        r+=.015*sqrt(i)/(.005+Z(f,w,.06,6.,1.)/k(f));
        if(20.<s||abs(i)<x)
        break;
	}
#ifndef BUBBLES
    s=min(s,20.0);
#endif
    if(20.<s)
		return vec3(min(2.*smoothstep(0.,12.,-f.y*.3),.3))/r+y+g;
    if(k(f)<x)
    {
    	vec3 l=Z(f);
    	return(.45+.75*max(0.,min(1.,.8+.5*(1.+dot(s*m,l)))))*(.6*k(f+.1*l,m-2.*dot(m,l)*l)+.4*pow(F(f,s),vec3(.4))+.4*pow(max(dot(normalize(m-Y),l),0.),80.))/r+y+g;
    }
    return F(f,s)/r+y+g;
}

vec3 X(vec3 v)
{
	return v=pow(.1+v,vec3(2.5)),v.y=pow(v.y,.56),v.z+=pow(v.z,.8)+.1,v.yz*=.8,v.y=smoothstep(-.1,1.2,v.y*.9)+.05,v*5.-.05;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    updateglobals();
    vec2 x=iResolution.xy,f=1.-2.*fragCoord.xy/x.xy;
    f.y*=x.y/x.x;
    mat3 m=p(-.22)*n(2.)*s(.06),r=p(.03*c(vec3(v*1.1578)))*n(.02*c(vec3(v*1.2462+x.x)))*s(.03*c(vec3(v*1.3102+x.y))),i=p(.008*c(17.*vec3(f.x,f.y,.22*v)))*n(.008*c(17.*vec3(f.x*.91,f.y*.73,.41*v)))*s(.008*c(17.*vec3(f.x*1.13,f.y*.91,.33*v)));
    vec3 l=vec3(-4.-2.*g,-12.8+9.*smoothstep(0.,28.,v)+2.*smoothstep(24.,45.,v),1.),z=vec3(f,.8+.04*y);
    float d=.2*smoothstep(50.,80.,v)-.3*p(3.,.3*clamp(v-20.,0.,20.));
    if(v>44.&&v<61.||v>202.&&v<209.||v>105.&&v<119.||v>342.)
    	l=vec3(-5.,-6.-6.*clamp((v-342.)/50.,0.,9.),2.),m=p(-.6-clamp((v-342.)/105.,0.,9.))*n(2.)*s(.06),d-=.25;
    if(v>230.&&v<240.)
    	l=vec3(-2.,-1.5,.5),m=p(-.12)*n(2.4)*s(0.);
    z=normalize(z)*m*r*i;
    vec3 C=X(pow(q(l,z),vec3(.8+d)));
    float a=.6/(.8+(.25+1./(smoothstep(0.,28.,v)-smoothstep(383.,399.,v)))*dot(f,f));
    fragColor=vec4(1.7*pow(.03*vec3(w(length(f)*v))+C*a,vec3(1.6)),1.);
}
