#define PI 3.14159265359
#define Radius1 28.0
#define Radius2 3.0
#define AA
#define Speed1	1.0/50.0
#define Speed2	5.0
#define Speed3	0.0

// Include code borrowed from IQ

float sdTorus( vec3 p, vec2 t )
{
  vec2 q = vec2(length(p.xz)-t.x,p.y);
  return length(q)-t.y;
}


float map(in vec3 pos)
{
    vec3 q = pos;
    float d = -sdTorus( q.xzy, vec2(Radius1,Radius2) ) ;

    return d;
}

vec3 calcNormal( in vec3 pos )
{
    const float ep = 0.0001;
    vec2 e = vec2(1.0,-1.0)*0.5773;
    return normalize( e.xyy*map( pos + e.xyy*ep ) +
					  e.yyx*map( pos + e.yyx*ep ) +
					  e.yxy*map( pos + e.yxy*ep ) +
					  e.xxx*map( pos + e.xxx*ep ) );
}



vec3 applyFog( in vec3  rgb, in float distance, in float strength )
{
    float fogAmount = 1.0 - exp( -distance*strength );
    vec3  fogColor  = vec3(0.0);
    return mix( rgb, fogColor, fogAmount );
}

void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 ro, in vec3 rd )
{
    ro += vec3(0.0,Radius1,0);
    rd = rd.zxy;


    float t = 0.5;
    for( int i=0; i<64; i++ )
    {
        vec3 p = ro + t*rd;
        float h = map(p);
        if( abs(h)<0.001 ) break;
        t += h;
    }

    vec3 p = ro + t*rd;
    float theta = (atan(p.x,p.y)/PI + 1.0)*150.0 - iTime*Speed2;
    int tata = int(theta);
    //float incPhi = (tata&1)==0?iTime*Speed3:-iTime*Speed3;
    float phi   = (atan(length(p.xy)-Radius1,p.z)/PI + 1.0)*30.0; // + incPhi;
    float itheta = floor(theta);
    float iphi	 = floor(phi);
    float ftheta = theta - itheta;
    float fphi	 = phi - iphi;
    ftheta = clamp(ftheta * 0.6 + 0.2,0.0,1.0);
    fphi = clamp(fphi * 0.8 + 0.1,0.0,1.0);
    vec4  rand = texture( iChannel1,vec2(iphi,itheta)*0.386557);
    float digit = floor(rand.r * 10.0);
    float freq = texture( iChannel2,vec2(rand.g,0.25)*0.386557).r;


    digit = mod(digit + (freq > 0.2?1.0:0.0),10.0);

    vec3 color = vec3(smoothstep( 0.51,0.49,texture( iChannel0,vec2((1.0-ftheta+digit)/8.0,(fphi+12.0)/16.0),-3.).a));
    color *= vec3(0,2,0);
    vec3 norm = calcNormal(p);
    color = applyFog(color,t,0.2*((norm.z*norm.z)/3.0 + 0.1 + clamp(norm.y*0.4,0.0,1.0))); // Hack to dim pixels with lots of aliasing
    fragColor = vec4(color,1.0);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec3 tot = vec3(0);
#ifdef AA
	vec2 rook[4];
    rook[0] = vec2( 1./8., 3./8.);
    rook[1] = vec2( 3./8.,-1./8.);
    rook[2] = vec2(-1./8.,-3./8.);
    rook[3] = vec2(-3./8., 1./8.);
    for( int n=0; n<4; n++ )
    {
        // pixel coordinates
        vec2 o = rook[n];
        vec2 p = (-iResolution.xy + 2.0*(fragCoord+o))/iResolution.y;
#else //AA
        vec2 p = (-iResolution.xy + 2.0*fragCoord)/iResolution.y;
#endif // AA

        vec3 ro = vec3(0);
        vec3 rd = normalize(vec3(p,-1.0));

        vec4 color;
        mainVR( color,fragCoord,ro,rd );
        tot += color.xyz;


#ifdef AA
    }
    tot /= 4.;
#endif //AA

	fragColor = vec4( tot, 1.0 );
}
