const float IN_RADIUS = 0.3;
const float OUT_RADIUS = 0.85;
const float PI = 3.14159;

vec3 borderColor(float x0, float x1, vec2 uv, 
                 float leftVisible, float rightVisible) {

    vec3 edgeCol = vec3(0.05);
    vec3 white = vec3(1.);
    float thick = 0.03;
   	
    // the exterior side of the left border
	float outside = (step(uv.x, x0-thick) + step(x0, uv.x));
    vec3 borderCol = mix(white, edgeCol, smoothstep(x0, x0-thick, uv.x)) 
    	* (1. - outside) * leftVisible;
        
    // the interior side of the left border
    outside = (step(uv.x, x0) + step(x0+thick, uv.x));
    borderCol += mix(edgeCol, white, smoothstep(x0+thick, x0, uv.x)) 
    	* (1. - outside)* leftVisible;      
    
    // the exterior side of the right border
    outside = (step(uv.x, x1) + step(x1+thick, uv.x));        
    borderCol += mix(white, edgeCol, smoothstep(x1, x1+thick, uv.x))
        * (1.- outside) * rightVisible ;
    
    // the interior side of the right border
    outside = (step(uv.x, x1-thick) + step(x1, uv.x));            
    borderCol += mix(edgeCol, white, smoothstep(x1-thick, x1, uv.x))
    	* (1.- outside) * rightVisible;
    
    return borderCol;
}

vec3 getBorderColor(float x0, float x1, vec2 uv,
              vec3 fragColor) {
        
    vec3 rightCol = vec3(0.);
    vec3 leftCol = vec3(0.);
        
    leftCol = borderColor(x0, x1, uv, 1., 0.);       
    rightCol = borderColor(x0, x1, uv, 0., 1.);
   
    if (leftCol != vec3(0.))
        return leftCol;
    else if (rightCol != vec3(0.))
   		return rightCol;                 
   
    return fragColor;   
}

vec3 getColor(float x0, float x1, vec2 uv, vec3 color) {
   
   // First u becomes [0,1] then the range [0.0, 0.5] will be 
   // transformed into [0.0, 1.0] and ]0.5, 1.0] into ]1.0, 0.0].
   float u = (uv.x - x0)/(x1 - x0);
              
   // u <= 0.5
   float ud = (u/0.5) * (1.0 - step(0.5, u));
   // u > 0.5
   ud += (1. - (u/0.5-1.)) * (1.0 - step(u, 0.5));
           
   // Remove aliasing by making the shading points near x0 and x1 darker.
   vec3 col = mix(vec3(0.0), color, smoothstep(.0, .6, ud)); 
            
   // Add lightning by making darker the shading points that are 
   // about to be covered and going "behind" another face. This also
   // removes aliasing since if x1-x0 is small the borders cover the 
   // darker sides and transition to interior area becomes very sharp. 
   float w = (x1 - x0);            
   col *= w / .55;
   return col;            
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-0.5*iResolution.xy) / iResolution.y;
    uv *= 2.7;
    
    // Polar coordinates
    vec2 uvr = vec2(length(uv), atan(uv.y, uv.x) + PI);
    uvr.x -= OUT_RADIUS;
       
    vec3 col = mix(vec3(0.01), vec3(0.05), smoothstep(2.2, .1, abs(uv.x)));    
    
    vec3 colors[4];
    colors[0] = vec3(0.9, 0.0, 0.0);
    colors[1] = vec3(0.0, 0.9, 0.0);
    colors[2] = vec3(0.0, 0.2, 1.0);
    colors[3] = vec3(1.0, 0.42, 0.0);
        
    float angle = uvr.y + 1.5*iTime + .5*sin(uvr.y) * 1.5*sin(iTime) * PI;
    
    // Add faces
    for(int i = 0; i < 4;i++)
    {
        float x0 = IN_RADIUS * sin(angle + 0.5 * float(i) * PI);       
        float x1 = IN_RADIUS * sin(angle + 0.5 * float(i+1) * PI);

        if (uvr.x >= x0 && uvr.x <= x1) {
            col = getColor(x0, x1, uvr, colors[i]);            
       }
    }

    // Add borders.
    float x0 = IN_RADIUS * sin(angle + 0.0);       
    float x1 = IN_RADIUS * sin(angle + 0.5*PI);
    float x2 = IN_RADIUS * sin(angle + 1.0*PI);       
    float x3 = IN_RADIUS * sin(angle + 1.5*PI);    
	
    if (x0 < x1) {
        col = getBorderColor(x0, x1, uvr, col);      
    }    
    
	if (x1 < x2) {
    	col = getBorderColor(x1, x2, uvr, col);
    }
   
   	if (x2 < x3) {
    	col = getBorderColor(x2, x3, uvr, col);
    }
    
    if (x3 < x0) {
    	col = getBorderColor(x0, x3, uvr, col);
    	if (x2 < x3) {
            col = getBorderColor(x3, x0, uvr, col);    	
    	}
    }
    
    col = pow(col,vec3(.454545));
	fragColor = vec4(col, 1.0);
}
