
vec2 code_transform_uv(float num_segs, float inv_num_segs, vec2 uv) {
	uv *= inv_num_segs;
	float cur_segment = floor(mod(uv.y, num_segs)) * inv_num_segs;
	uv.x = mod(uv.x - cur_segment, 1.0);
	uv.y = mod(uv.y, 1.0);
	return uv;
}

vec4 sample_code(sampler2D sampler_code, vec4 code_tex_params, vec2 uv) {
	vec2 code_aspect = code_tex_params.xy;
	float num_segs = code_tex_params.z;
	float inv_num_segs = code_tex_params.w;

	uv *= code_aspect;
	uv = code_transform_uv(num_segs, inv_num_segs, uv * 2);
	return texture(sampler_code, uv);
}

vec2 estd(vec2 p, vec2 f) {
	p = mod(p, 1.0);
	p -= 0.5;
	p *= f;
	p = p * sqrt(1.0 - 0.5 * p.yx * p.yx);
	p /= f;
	p += 0.5;
	return p;
}

vec4 sample_background(
	sampler2D sampler_bg,
	sampler2D sampler_bg_binary,
	sampler2D sampler_code,
	vec4 code_tex_params,
	vec2 uv,
	float r,
	float t
) {
	uv = estd(uv, vec2(1.5, 1.0) * r);

	vec2 bg_uv = uv * vec2(0.5, 0.8) * 0.5;
	vec2 bg_binary_uv = bg_uv;

	t *= 0.5;

	bg_uv.x += t * 0.02;
	bg_uv.y -= t * 0.145;
	bg_binary_uv.x += t * 0.013937;
	bg_binary_uv.y += t * 0.05;

	vec2 code_uv = uv;
	code_uv.x += t * 0.3;
	code_uv.y += t * 0.2;

	vec4 background = texture(sampler_bg, bg_uv);
	vec4 background_binary = texture(sampler_bg_binary, bg_binary_uv);
	vec4 code = sample_code(sampler_code, code_tex_params, code_uv) * r;

	background = background * background_binary + code;
	background.rgb = pow(background.rgb, mix(1 - vec3(1.0, 0.5, 0.3), vec3(1), r));

	return background;
}
