// -= Twister95 =-
// Written by Blokatt (Jan Vorisek)
// blokatt.net | @blokatt | github.com/blokatt
// 04/09/18

#define WIDTH 0.05
#define PI 3.14159265358
#define TAU PI * 2.0
#define EDGE 0.001
#define BORDER 0.02
#define DITHER_MIX 0.35
#define OPENING_WIDTH 85.0

float margin(in float v){
	return length(iResolution) * v;
}

float luma(in vec4 c){	
	return (c.r * 0.3 + c.g * 0.59 + c.b * 0.11) / 3.;
}

vec4 dither8x8(in vec2 position, in vec4 col) {    
    float threshold = texture(iChannel1, vec2(position.xy / 8.)).r;	
    return vec4(mix(col.rgb, vec3(col.rgb * floor(floor(col.rgb * 64.) / 64. + threshold)) * 1.5, DITHER_MIX), 1.);
}

vec4 side(in vec3 tint, in vec2 coord, in float t, in float off){	
    t *= .65;
    float time = -t + off + sin(t + coord.y * .5) * 5. - cos(t * .5 + coord.y * .4 + .2) * 2.5 - (sin(t * .25 + cos(coord.y * .5) + PI) * (1. * cos(.6 + t * .0125))) * 2.5 + (iMouse.x / iResolution.x) * TAU;    
    float angle = sin(time);
    float offset = cos(time);
    vec3 normal = vec3(offset, 0., angle); 
    vec3 reflection = reflect(vec3(coord.xy - .5, .5), normal);
    float x = .5 - sin((coord.y - .5) * 3. + t * 3.) * .06 - sin(coord.y * 5. - t * 1.) * .025 * (sin(t * .25 + .3) * .5 + .5);
    float w = WIDTH * (1. + (OPENING_WIDTH * ((smoothstep(.9, 2.75, coord.y)) + (smoothstep(.1, -1.75, coord.y)))) + .1 * sin(t * 10. + coord.y * (2. + 10. * cos(t * .25))));                    
    return ((vec4(vec3((1.25, 1., 1.2) - tint) * (1. + .3 * sin(reflection.x * 25. * angle + time) * cos (reflection.y * 50. - time)), 1.) * texture(iChannel0, reflection) * 1.25) * (.3 + angle)) * (.85 - smoothstep(w * angle - EDGE, w * angle + EDGE, abs(x - (coord.x + w * offset)))); 		
}

vec4 image(in vec2 coord, in float time){    
	return side(vec3(0., .25, 5.), coord, time, 0.) +
           side(vec3(.3, .1, .15), coord, time, PI  * .5) +
           side(vec3(0., 0., 1.), coord, time, PI) + 
           side(vec3(.05, .38, .5), coord, time, PI * 1.5);           
}

float border(in vec2 coord){	 
	return clamp(0., step(iResolution.x - margin(BORDER), coord.x)
                   + step(iResolution.y - margin(BORDER), coord.y)
              + 1. - step(margin(BORDER), coord.x)
              + 1. - step(margin(BORDER), coord.y), 1.);
}

vec4 post(in vec2 coord, in float time){
	vec2 uv = coord/iResolution.xy;  
    return vec4(0.1, 0.04, 0.16, 1.) + (vec4(image(vec2(uv.x - .0015, uv.y), time).r, image(uv, time).g, image(vec2(uv.x + .0015, uv.y), time).b, 1.)) * (1. + border(coord));                                                                                 
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{    
    fragColor = dither8x8(fragCoord, mix(post(fragCoord, iTime), mix(post(fragCoord, iTime - .05), post(fragCoord, iTime + .05), .35), .35));
}
