precision highp float;
float t;

float sym(vec2 p, float fs) {
    vec2 s = vec2(mod(fs,16.), 16.-floor(fs/16.));
    vec2 tsz = vec2(iChannelResolution[0]), rsz = 1. / tsz;
    p = (p + vec2(16.,0.) + s*64.)*rsz;
    return smoothstep(.5, .49, texture(iChannel0, p).a);
}

bool text_balls = false;
float text(vec2 p) {
	if (text_balls) {
		vec2 cid = floor(p), cc=(p-cid)*2.-1.;
		return step(length(cc), .7);
    } else {
        p *= .1;
        p += vec2(.1, .1);
        p *= vec2(iChannelResolution[0]);
        vec2 gsz = vec2(16.,64.);
        vec2 ci = floor(p/gsz), cp = mod(p, gsz);
#define SYM(a) if (ci.x == 0.) { return sym(cp*vec2(2.,1.), a); } ci.x -= 1.;
        if (ci.y == 1.) {
        	SYM(122.); SYM(117.); SYM(132.); SYM(124.); SYM(113.); SYM(119.);
        } else if (ci.y == 0.) {
            SYM(128.); SYM(113.); SYM(131.); SYM(132.); ci.x -= 1.;
            SYM(130.); SYM(113.); SYM(115.); SYM(117.); SYM(130.);
        }
        return 0.;
    }
}

const float PI=3.1415923;
const vec3 E=vec3(0.,.01,1.);

float hash1(float f){return fract(sin(f)*46347.423874);}
float hash2(vec2 v){return hash1(dot(v,vec2(79.53248,31.4328)));}

float noise2(vec2 v) {
	vec2 V=floor(v);v-=V;
	v*=v*(3.-2.*v);
	return mix(
		mix(hash2(V+E.xx), hash2(V+E.zx), v.x),
		mix(hash2(V+E.xz), hash2(V+E.zz), v.x), v.y);
}

mat3 RX(float a){float c=cos(a),s=sin(a);return mat3(1.,0.,0.,0.,-s,c,0.,c,s);}
mat3 RY(float a){float c=cos(a),s=sin(a);return mat3(c,0.,s,0.,1.,0.,-s,0.,c);}
mat3 RZ(float a){float c=cos(a),s=sin(a);return mat3(c,s,0.,-s,c,0.,0.,0.,1.);}

vec3 O, D, P, N;
vec2 UV;
int M;
float l;

void aapl(float offset, vec3 axis, int mi) {
	float x = dot(O,axis), rx = dot(D,axis), s = sign(rx);
	float lp = (s * offset - x) / rx;
	if (lp < l) {
		l = lp;
		P = O + D * l;
		N = - s * axis;
		M = mi;
		UV = axis.x*P.yz + axis.y*P.xz + axis.z*P.xy;
	}
}

float ss(float f){return max(0.,min(1.,f));}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    t = mod(iTime, 120.) * 12.0;
    vec2 R = iResolution.xy;
	vec2 uv=(fragCoord.xy/R)*2.-1.;uv.x*=R.x/R.y;

    //fragColor=vec4(hash2(uv));return;

	vec3 c=vec3(0.);
	float seed = t;

	float tpat = t/32.;

	////////////// TWEAK THESE
	float ls = .2, // lens size
				lf = 4. + 3.,// * sin(t*.1), // focus distance
				lS = 1.; // fov-ish
	vec3 sz = vec3(1.5,2.,6.);
	float or = 4.;
	mat3 mv = mat3(1,0,0,0,1,0,0,0,1);
	//mv = RY(2.*sin(t*.01))*RY(3.*sin(t*.039));
	//mv = RY(2.+sin(t*.05));
	float text_offset = -2. + 6. * hash1(floor(t/8.));
	float pscl = 4.;
	bool text_plane = false;
	bool pix1 = false, pix2 = false;
	bool pixmv = false;
	bool proj2 = false;
	bool proj1 = false;
	vec3 bgcolor = .5 * vec3(.3,.5,.8);
	float zmove = 0.;
	vec2 pixmvs = vec2(0.);
	float pixmvl = 1.;
	bool rpix = true;
	vec3 rpixc = vec3(0.);
	vec3 pixmvc = vec3(1.);
	vec3 pix2c = vec3(1.);
	vec3 pc = vec3(0.,0.,-6.);

	sz=vec3(8.);
	bgcolor = vec3(0.);
	ls = 1.;
	lf = 4.;
	rpix = true;
	rpixc = vec3(tpat/6.);
	mv = RY(tpat)*RX(tpat*.3);

	if (tpat > 6.) {
		pixmv = true;
		pixmvs=vec2(1., 0.);
	}

	if (tpat > 9.) {
		float tt=ss(tpat-9.);
		sz = mix(sz, vec3(1.5,2.,6.), tt);
		or = mix(or,1.,tt);
		ls = mix(ls,.1,tt);
	}

	if (tpat > 13.6) {
		float tt = smoothstep(13.6, 14., tpat);
		lS = mix(10., 1., tt);
		ls = mix(4., .1, tt);
		lf = mix(.1, 7., tt);
		mv = RZ(1.-tt);
		zmove = 4.;
	}

	if (tpat > 14.) {
		mv = RZ(.1*sin(tpat-14.));
	}

	if (tpat > 17.) {
		text_plane = true;
		text_offset = -6. + 2.*floor(tpat-17.);
	}

	if (tpat > 19.) {
		rpix = false;
	}

	if (tpat > 20.) {
		pixmv = false;
	}

	if (tpat > 21.8) {
		float tt=smoothstep(21.8, 22., tpat);
		sz = mix(sz, vec3(4.,1.,-1.), tt);
		pixmv = true;
	}

	if (tpat > 22.) {
		mv = RZ(tpat-22.);
		text_plane = false;
		bgcolor = .01 * vec3(.3,.5,.8);
		zmove = 47.;
	}

	if (tpat > 23.) {
		float tt = ss(tpat-23.);
		pixmvl = mix(pixmvl, 5., tt);
		pixmvs = mix(pixmvs, vec2(1., 10.), tt);
		pixmvc = .5 * vec3(.2, .5, .9);
		lf = 10.;
		ls = .1;
	}

	if (tpat > 24.) {
		text_plane = true;
		text_balls = true;
		text_offset = -8. + 2.*mod(floor(tpat-23.), 4.);
	}

	if (tpat > 26.) {
		rpix = true;
		rpixc = vec3(1.);
		text_plane = false;
		float tt = ss(tpat-26.);
		sz = mix(sz, vec3(2.,2.,-1.), tt);
		or = mix(or, 2., tt);
		mv *= RY(tt*(tpat-26.));
	}

	if (tpat > 28.) {
		proj1 = true;
		lf = 4.;
		pc = vec3(vec2(cos(tpat*.3), sin(tpat*.7)) * 1.5, 10.*sin(tpat*.9));
	}

	if (tpat > 30.) {
		ls = .12, // lens size
				lf = 4. + 3.,// * sin(t*.1), // focus distance
				lS = 7.; // fov-ish
		pixmv = false;
	}

	if (tpat > 34.) {
		proj1 = false;
		proj2 = true;
		lS = .1;
		bgcolor = .5 * vec3(.3,.5,.8);
	}

	if (tpat > 38.) {
		//bgcolor = vec3(1.,.0,.0);
		mv = RX(-3.);
	}

	// PATHTRACER STARTS
	lS *= lf;
#define NS 32.
	for (float s=0.;s<NS;++s) {
		float a = hash1(seed+=uv.x)*2.*PI, r = s/NS;
		O = vec3(vec2(cos(a),sin(a))*r*ls, or);
		vec3 at = vec3(uv*lS, O.z-lf);
		D = normalize(at - O) * mv; O *= mv;
		vec3 kc = vec3(1.);
		for (int i = 0; i < 4; ++i) {
			l = 1e6;
			aapl(sz.x, vec3(1.,0.,0.), 1);
			aapl(sz.y, vec3(0.,1.,0.), 2);
			if (sz.z>0.) aapl(sz.z, vec3(0.,0.,1.), 3);

			if (text_plane) {
				float dist = text_offset - O.z;
				float lt = dist / D.z;
				vec3 tp = O+D*lt;
				if (lt > 0. && lt < l) {
					if (text(tp.xy) > 0.) {
						l = lt;
						P = tp;
						N = vec3(0., 0., sign(dist));
						M = 4;
						UV = P.xy;
					} /* alpha glass fx */ //else { kc *= vec3(.5, .5, .7); }
				}
			}

			vec3 me = vec3(0.), ma = vec3(.7);
			float mr = .5;

			if (M == 4) {
				ma = vec3(.9);
				me = 4. * vec3(step(1.3,mod(t*.5+dot(3.*normalize(vec2(1.,1.)), UV), 2.)));
				mr = .9;
			} else {
                // Windows/ANGLE fix
				//UV.y -= tpat*zmove;
				//UV *= pscl;
                vec2 fix_uv_wtf = (UV - vec2(0., tpat*zmove)) * pscl;

                vec2 cid = floor(fix_uv_wtf);
				vec2 cpc = fract(fix_uv_wtf)*2. - 1.;

                if (rpix) {
					me += rpixc * step(.9,hash2(cid));
				}

				if (pix1) {
					float e2step = 2.;
					float e2a = t * .2;
					vec2 e2dir=vec2(cos(e2a),sin(e2a));
					float d = dot(UV, e2dir);
					me += vec3(2,0,0.5) * step(abs(d),e2step);
				}

				if (pix2) {
					me += max(me, pix2c*mod(floor(-.2*t+(dot(cid/12.,vec2(3.)))), 2.));
				}

				if (pixmv) {
					float pos = floor(t * pixmvs.x + pixmvs.y * hash1(cid.x));
					float len = 16.;
					float p = mod(cid.y + pos, len);
					me += pixmvc * step(len-pixmvl,p);
				}

				{
					vec3 ruv = normalize(floor(P*pscl) - pc);
					ruv *= RY(t*.1);

					vec3 dir = normalize(vec3(1.));

					me += bgcolor;

					if (proj1) {
						 me += 2.*vec3(.9,.7,.2) * step(1.5, mod(t *.1+ 6.*dot(ruv, dir), 2.));
					}

					if (proj2) {
						me += 7. * vec3(.9,.7,.2) * pow(max(0.,dot(dir,ruv)), 100.);
					}
				}

				me *= vec3(
					step(length(cpc),.8),
					step(length(cpc+vec2(.1,0.)),.8),
					step(length(cpc+vec2(.0,.1)),.8)
				);
				mr = .001 + hash2(cid)*.3;
				ma *= step(abs(cpc.x),.9)*step(abs(cpc.y),.9);
			}

			//kc *= 1. - l/40.;
			c += kc * me;
			kc *= ma;

			if (all(lessThan(kc,vec3(.001)))) break;

			O = P;
			D = normalize(mix(
				reflect(D, N),
				vec3(hash1(seed+=P.z),hash1(seed+=D.x),hash1(seed+=P.y))*2.-1., mr));
			D *= sign(dot(D, N));
		}
	}

	c /= NS;

	fragColor=vec4(sqrt(c), 0);
}
