/*
* License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
* Created by bal-khan
*/

#define R iResolution.xy
#define A(u) texture(iChannel0, u)
#define B(u) texture(iChannel1, u)
#define C(u) texture(iChannel2, u)

vec3 tex; // global variable holding texture coordinates and then final color

// 2D rotation utility
void rot(inout vec2 p, float a)
{
    p = vec2(cos(a)*p.x + sin(a)*p.y, -sin(a)*p.x + cos(a)*p.y);
}

float map(vec3 p)
{
    float ret, a_XY, a_q_XY;        // variables explained at affectation
    vec2 q, displace_tex, tcd;
    rot(p.zx, 6.*iMouse.x/R.x);     // rotate space around zx with mouse
    a_XY = atan(p.x, p.y);          // angle x^y
    q = vec2(length(p.xy)-.5, p.z); // torus space vector laying along xy plane, hole being from z direction
    rot(q, iTime*.5 + a_XY );       // rotate torus space along angle x^y
    q.y = abs(q.y)-.125;            // take the absolute value of one axis to get a symmetry of the torus space along 0 starting at .125 unit from 0
    a_q_XY = atan(q.x, q.y);        // angle qx^qy <==> angle ON the ring of the torus <==> location on the ring from center to exterior
    tex = vec3(.0);                 // this is going to contain the color from characters texture

    tcd = vec2(a_q_XY/5., a_XY/1.256); // the 2 angles we have for the torus are our texture coordinates
                                       // dividing tcd by value greater than 1 allow to "zoom in" the texture
                                       // This let see letters more clearly

    // here is texture animation
    // what this is doing : adding a ramping [-2:+2] value to one of the texture coordinate at a time,
    // alternating between them at a regular interval
    // to have a displacement dependent of 1 column/line
    // you need to floor/ceil the texture coordinates  to get an id
    // then feed it to a sinus function after multiplying it by something larger to get more riples from the sin
    // remap [-1,1] to [-2,2]
    displace_tex =
    sin(floor(tcd.yx*16.)*2.+vec2(1.,-1.)*iTime/4.)*2. // id part
    *
    vec2(
        smoothstep(1.5, 1., mod(iTime/4.   , 4.)) // alternate axis part
        ,
        smoothstep(1.5, 1., mod(iTime/4.+2., 4.))
        );
    // add the displacement to the texture coordinates
    tcd += displace_tex;
    // sampling the letter texture
    tex.x = A(tcd).x;

    // getting the distance field of the toris with a small texture displacement
    ret = length(q) - .11-.005*length(tex);
    // store an id of the texture coordinates in tex.yz for coloring each square differently, this is done in main
    tex.yz = vec2(floor(tcd.xy*16.)/16.);

    return ret*.7; // multiply the distance field by a value inferior to 1 to lessen artifacts
}

void mainImage( out vec4 o, in vec2 f )
{
    o = o-o;
    vec2 uv = (f-.5*R)/R.yy;            // making a screen centered vector for x & y axises
    vec3 dir = normalize(vec3(uv, 1.)); // using said vector to make the direction of the ray
    vec3 pos = vec3(.0, .0, -2.);       //starting position of the ray
    vec2 dist = vec2(0.);               // variable holding {last_distance, sum_distances}
    bool hit = false;
    vec3 p;                             // this is the ray
    for(int i = 0; i < 64; i++)         // marching loop
    {
        p = pos + dist.y * dir;         // update the ray position
        dist.x = map(p);                // distance to closest object from ray + texture_id
        dist.y += dist.x;               // sum the distance

        if(dist.x < 0.001)              // we hit, assign hit to true and break out of the loop
        {
            hit = true;
            break;
        }
    }

    // Here coloring starts
    // I use the 2nd texture to color the toris
    // the variable "tex" contained cells id on it's yz vector part and the x part wich was a 0 or 1 indicating the presence of a letter
    // the variable is overwritten by the final coloring in wich we use the ids
    // I sample the texture using 2 different coordinates so that letters and their background are not the same
    tex =
        B( tex.yz * vec2(1.5, -1.5) ).xyz * tex.x      // this affect the color of the letters
        +
        B( tex.yz ).xyz                   * (1.-tex.x) // this affect the toris non_lettered parts color
        ;

    // affect color to output variable
    o.xyz =
        (hit ? 1. : .0) * (tex)                        // textured toris color
        +
        (hit ? 0. : 1.) * C(dir).xyz                   // cubemap bgd color
        ;

    //o.xyz = vec3(o.x * .3 + o.y* .59 + o.z*.11);     // b&w mode (grayscale conversion)
}