#define div 10.
#define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a))
vec2 po(vec2 p)
{
    return vec2(length(p),atan(p.y,p.x));
}

vec2 va(vec2 q)
{
    return vec2(q.x*cos(q.y),q.y*sin(q.y));
}


float mix3(float l1,float l2, float l3,vec2 a)
{
    return l1*min(1.-a.x,1.-a.y)+l2*min(a.x,a.y)+l3*max(a.x-a.y,a.y-a.x);
}

float hash(vec2 p)
{
    return fract(sin(dot(p,vec2(78.398,12.862)))*38057.12);//[0,+1]
}

vec2 hash2(vec2 p)
{
    p=vec2(dot(p,vec2(78.3979,13.397)),dot(p,vec2(219.233,79.247)));
    return 2.*fract(sin(p)*38807.12)-1.;//[-1,+1]
}

float blocknoise(vec2 p)
{
    p*=div;
    vec2 i=floor(p);
    return hash(i);
}

float valuenoise(vec2 p)
{
    p*=div;
    vec2 i=floor(p);
    vec2 f=p-i;
    //vec2 u=f*f*(3.-2.*f);
    vec2 u=f*f*f*(6.*f*f-15.*f+10.);
    float v00=hash(i+vec2(0.,0.));
    float v10=hash(i+vec2(1.,0.));
    float v01=hash(i+vec2(0.,1.));
    float v11=hash(i+vec2(1.,1.));
    return mix(mix(v00,v10,u.x),mix(v01,v11,u.x),u.y);
}

float perlinnoise(vec2 p)
{
    p*=div;
    vec2 i=floor(p);
    vec2 f=p-i;
    //vec2 u=f*f*(3.-2.*f);
    vec2 u=f*f*f*(6.*f*f-15.*f+10.);
    float v00=dot(hash2(i+vec2(0.,0.)),f-vec2(0.,0.));
    float v10=dot(hash2(i+vec2(1.,0.)),f-vec2(1.,0.));
    float v01=dot(hash2(i+vec2(0.,1.)),f-vec2(0.,1.));
    float v11=dot(hash2(i+vec2(1.,1.)),f-vec2(1.,1.));
    float t=mix(mix(v00,v10,u.x),mix(v01,v11,u.x),u.y);
    return t*0.5+0.5;
}

float simplexnoise(vec2 p)
{
    p*=div;
    p.x=p.x*1.1547;//1.1547=2/sqrt(3)
    p.y=p.x*0.5+p.y;
    vec2 i=floor(p);
    vec2 f=p-i;
    vec2 s=vec2(step(f.y,f.x),1.-step(f.y,f.x));
    vec2 u=f*f*f*(6.*f*f-15.*f+10.);
    float v00=dot(hash2(i+vec2(0.,0.)),f-vec2(0.,0.));
    float v11=dot(hash2(i+vec2(1.,1.)),f-vec2(1.,1.));
    float v10=dot(hash2(i+s),f-s);
    float t=mix3(v00,v11,v10,u);
    return 0.5*t+0.5;
}

float fbm_value(vec2 p)
{
    float r=0.;
    float w=0.5;
    for(int i=0;i<4;i++)
    {
        r+=w*valuenoise(p);
        p*=2.0;
        w*=0.5;
    }
    return r;
}

float fbm_perlin(vec2 p)
{
    float r=0.;
    float w=0.5;
    for(int i=0;i<4;i++)
    {
        r+=w*perlinnoise(p);
        p*=2.0;
        w*=0.5;
    }
    return r;
}

float fbm_simplex(vec2 p)
{
    float r=0.;
    float w=0.5;
    for(int i=0;i<4;i++)
    {
        r+=w*simplexnoise(p);
        p*=2.0;
        w*=0.5;
    }
    return r;
}

float fbm_perlin_turb(vec2 p)
{
    float r=0.;
    float w=0.5;
    for(int i=0;i<4;i++)
    {
        r+=w*abs(2.*perlinnoise(p)-1.);
        p*=2.;
        w*=0.5;
    }
    return r+0.2;
}

float fbm_perlin_ridge(vec2 p)
{
    float r=0.;
    float w=0.5;
    for(int i=0;i<4;i++)
    {
        r+=w*(0.8-abs(2.*perlinnoise(p)-1.))*(0.8-abs(2.*perlinnoise(p)-1.));
        p*=2.;
        w*=0.5;
    }
    return r+0.2;
}

float fbm_flow_perlin(vec2 p,float t)
{
    p += 0.03*sin( vec2(0.27,0.23)*t+ length(p)*vec2(4.1,4.3));
    p*=0.5;
    vec2 k=vec2(fbm_perlin(p),fbm_perlin(p+vec2(2.,4.5)));
    //k +=0.1*iTime;//sin( vec2(0.12,0.14)*iTime + length(k));
    k*=0.6;
    vec2 l=vec2(fbm_perlin(k),fbm_perlin(k+vec2(2.,8.5)));
    return 1.-dot(l,l);
}



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

vec3 transform(vec3 p,float angle){
    p.xz*=rot(angle*0.5);
    p.xy*=rot(angle*0.7);
    return p;
}

vec4 noiseball(vec3 ro,vec3 rd,vec3 pos,float angle,float r){
    vec4 col=vec4(0.);
    float t=dot(pos-ro,rd);
    vec3 p=ro+rd*t;
    float y=length(pos-p);
    if(y<r){
        float x=sqrt(r-y);
        vec3 pF=ro+rd*(t-x)-pos;
        pF=transform(pF,angle);
        vec2 uvF=vec2(atan(pF.x,pF.z),pF.y);
        float f=fbm_flow_perlin(uvF,iTime*8.);
        vec4 front=vec4(vec3(f),S(0.4,0.8,f))*S(0.8,0.6,abs(uvF.y));
        vec3 pB=ro+rd*(t+x)-pos;//back intersection
        pB=transform(pB,angle);
        vec2 uvB=vec2(atan(pB.x,pB.z),pB.y);
        float b=fbm_flow_perlin(uvB,iTime*8.);
        vec4 back=vec4(vec3(b),S(0.4,0.8,b))*S(0.8,0.6,abs(uvB.y));
        col=mix(back,front,front.a);

    }
    return col;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-iResolution.xy*0.5)/iResolution.y;
    vec2 M=iMouse.xy/iResolution.xy-0.5;
    vec3 bg=vec3(0.2,0.2,0.7)*fbm_perlin_ridge(uv*2.)*mix(vec3(0.3,0.9,0.3),vec3(0.9,0.2,0.9),valuenoise(uv*2.));
    vec4 col = vec4(bg,0.);
    for(float i=0.1;i<=1.;i+=0.1){
        vec3 ro=vec3(0.,0.,-2.);
        vec3 rd=normalize(vec3(uv,1.));
        vec4 noise=noiseball(ro,rd,vec3(0.),(iTime*i+i*10.)*sign(sin(i*50.)),i);
        noise.rgb*=vec3(hash(vec2(i*8.,iTime*0.0001)),hash(vec2(4.,i*3.)),hash(vec2(i,i*10.)));
        col=+mix(col,noise,noise.a);
    }
    col=pow(col,vec4(0.4545));

    fragColor = col;
}
