/*
Bouncing on Marble 1.0
By Blokatt (@blokatt | blokatt.net)
22/09/18
*/

#define MOTION_BLUR_LENGTH 0.025
#define MOTION_BLUR_SAMPLES 10.0
#define ARC_MAX_LEN 8.0
#define ARC_MAX 0.3
#define TIME_OFFSET 13.75 + (iMouse.x / iResolution.x - .5)
#define JUMPING_SPEED 1.0

const float PI = 3.141592653589793238462643;
const float HPI = PI * 0.5;
const float FPI = ARC_MAX_LEN / PI;
const float MOTION_BLUR_FALOFF = 1.0 - (1.0 / (1. + MOTION_BLUR_SAMPLES * 0.3));
const float MOTION_BLUR_LENGTH_OFFSET = MOTION_BLUR_LENGTH / MOTION_BLUR_SAMPLES;
#define RATIO iResolution.x / iResolution.y

mat2 rot(float a){
	return mat2(cos(a), -sin(a),
        		sin(a), cos(a));
}

float smoothmod(float v, float d, float p){
	float res = mod(v, d);
    return res * (1. - smoothstep(d - p, d, res));
}

vec4 baseTexture(in vec2 uv, float depth){
    float size = 1.;
    float blur = min(.0005 * (depth * 10.5), .0030);
    return vec4(.5) * smoothstep(0., blur, smoothmod(uv.x * size, .05, blur * 5.)) * smoothstep(0., blur * RATIO, smoothmod(uv.y * size, .05, blur * RATIO * 3.)) * smoothstep(1., 1. - blur, mod(uv.x * size + .05 * floor(mod(uv.y * size, .1) * 20.), .1) * 20.) + texture(iChannel0, uv * 5.) - vec4(.14, .15, .01, 0.);
}

float arcExtreme(float t) {
	return ARC_MAX * floor(abs(HPI - mod(t / ARC_MAX_LEN - HPI, PI)) * FPI);
}

vec4 zoomer(in vec2 uv, in float t){
    uv.x *= RATIO;
    vec2 _uv = uv;

    float bounceT = t * JUMPING_SPEED + .2;
    float z = .1 + abs(sin(bounceT)) * (1. + arcExtreme(bounceT));
    uv *= z;
    uv.x += cos(t * 1.) * .25 * sin(t * .2 + .2);
    uv.y -= sin(t * 1.) * .25 * sin(t * .2 + .2);
	uv *= rot(t * .3 + length(uv) * .5);

    float l = length(uv);
    float depth = sin(l * 10. - t * 5.) * ((1. / (1. + l * .25)) * .03);
    float size = 1.5 + depth * 1.5;
    float _l = length(_uv * size);
    return vec4(1. - depth * 15.) * baseTexture(uv * size, z) * (mix(smoothstep(.25 * .15, .5 * .15, _l * z - max(0., max(0., .006 - z * 2.5))), 1., clamp(0., 1., .15 + z + depth)));
}

vec4 trail(in vec2 uv, in float t){
    t += TIME_OFFSET;
	vec4 col = zoomer(uv, t);
    float factor = .5;
    for (float i = 1.; i < MOTION_BLUR_SAMPLES; i += 1.){
    	col = mix(col, zoomer(uv, t - i * MOTION_BLUR_LENGTH_OFFSET), 1. * factor);
        factor *= MOTION_BLUR_FALOFF;
    }
    return col;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy - .5;
    fragColor = vec4(trail(uv, iTime - .005).r, trail(uv * .996, iTime).g, trail(uv * .993, iTime + .005).b, 1.) * (1. - smoothstep(.5, .9, length(uv)));
}
