R"(
#version 440

#define SAMPLER_BINDING(x) %sampler_binding

layout(%set_decorator, binding=SAMPLER_BINDING(0)) uniform sampler2D fs0;
layout(%set_decorator, binding=SAMPLER_BINDING(1)) uniform sampler2D fs1;

layout(location=0) in vec2 tc0;
layout(location=0) out vec4 ocol;

#define STEREO_MODE_DISABLED 0
#define STEREO_MODE_SIDE_BY_SIDE 1
#define STEREO_MODE_OVER_UNDER 2
#define STEREO_MODE_INTERLACED 3
#define STEREO_MODE_ANAGLYPH_RED_GREEN 4
#define STEREO_MODE_ANAGLYPH_RED_BLUE 5
#define STEREO_MODE_ANAGLYPH_RED_CYAN 6
#define STEREO_MODE_ANAGLYPH_MAGENTA_CYAN 7
#define STEREO_MODE_ANAGLYPH_TRIOSCOPIC 8
#define STEREO_MODE_ANAGLYPH_AMBER_BLUE 9

#define TRUE 1
#define FALSE 0

const vec2 left_single_matrix  = vec2(1.f, 0.4898f);
const vec2 right_single_matrix = vec2(0.f, 0.510204f);
const vec2 sbs_single_matrix   = vec2(2.0, 0.4898f);
const vec2 sbs_multi_matrix    = vec2(2.0, 1.0);
const vec2 ou_single_matrix    = vec2(1.0, 0.9796f);
const vec2 ou_multi_matrix     = vec2(1.0, 2.0);

#ifdef VULKAN
layout(push_constant) uniform static_data
{
	float gamma;
	int limit_range;
	int stereo_display_mode;
	int stereo_image_count;
};
#else
uniform float gamma;
uniform int limit_range;
uniform int stereo_display_mode;
uniform int stereo_image_count;
#endif

vec4 anaglyph(const in vec4 left, const in vec4 right)
{
	switch (stereo_display_mode)
	{
	case STEREO_MODE_ANAGLYPH_RED_GREEN:    return vec4(left.r, right.g, 0.f, 1.f);
	case STEREO_MODE_ANAGLYPH_RED_BLUE:     return vec4(left.r, 0.f, right.b, 1.f);
	case STEREO_MODE_ANAGLYPH_RED_CYAN:     return vec4(left.r, right.g, right.b, 1.f);
	case STEREO_MODE_ANAGLYPH_MAGENTA_CYAN: return vec4(left.r, right.g, (left.b + right.b) / 2.f, 1.f);
	case STEREO_MODE_ANAGLYPH_TRIOSCOPIC:   return vec4(right.r, left.g, right.b, 1.f);
	case STEREO_MODE_ANAGLYPH_AMBER_BLUE:   return vec4(left.r, left.g, (right.r + right.g + right.b) / 3.f, 1.f);
	default:                                return texture(fs0, tc0);
	}
}

vec4 anaglyph_single_image()
{
	const vec4 left  = texture(fs0, tc0 * left_single_matrix);
	const vec4 right = texture(fs0, (tc0 * left_single_matrix) + right_single_matrix);

	return anaglyph(left, right);
}

vec4 anaglyph_stereo_image()
{
	const vec4 left = texture(fs0, tc0);
	const vec4 right = texture(fs1, tc0);
	
	return anaglyph(left, right);
}

vec4 read_source()
{
	if (stereo_display_mode == STEREO_MODE_DISABLED)
	{
		return texture(fs0, tc0);
	}

	if (stereo_image_count == 1)
	{
		switch (stereo_display_mode)
		{
			case STEREO_MODE_ANAGLYPH_RED_GREEN:
			case STEREO_MODE_ANAGLYPH_RED_BLUE:
			case STEREO_MODE_ANAGLYPH_RED_CYAN:
			case STEREO_MODE_ANAGLYPH_MAGENTA_CYAN:
			case STEREO_MODE_ANAGLYPH_TRIOSCOPIC:
			case STEREO_MODE_ANAGLYPH_AMBER_BLUE:
				return anaglyph_single_image();
			case STEREO_MODE_SIDE_BY_SIDE:
				return (tc0.x < 0.5)
					? texture(fs0, tc0 * sbs_single_matrix)
					: texture(fs0, (tc0 * sbs_single_matrix) + vec2(-1.f, 0.510204f));
			case STEREO_MODE_OVER_UNDER:
				return (tc0.y < 0.5)
					? texture(fs0, tc0 * ou_single_matrix)
					: texture(fs0, (tc0 * ou_single_matrix) + vec2(0.f, 0.020408f));
			case STEREO_MODE_INTERLACED:
				return ((int(gl_FragCoord.y) & 1) > 0)
					? texture(fs0, tc0 * left_single_matrix)
					: texture(fs0, (tc0 * left_single_matrix) + right_single_matrix);
			default: // undefined behavior
				return texture(fs0, tc0);
		}
	}

	if (stereo_image_count == 2)
	{
		switch (stereo_display_mode)
		{
			case STEREO_MODE_ANAGLYPH_RED_GREEN:
			case STEREO_MODE_ANAGLYPH_RED_BLUE:
			case STEREO_MODE_ANAGLYPH_RED_CYAN:
			case STEREO_MODE_ANAGLYPH_MAGENTA_CYAN:
			case STEREO_MODE_ANAGLYPH_TRIOSCOPIC:
			case STEREO_MODE_ANAGLYPH_AMBER_BLUE:
				return anaglyph_stereo_image();
			case STEREO_MODE_SIDE_BY_SIDE:
				return (tc0.x < 0.5)
					? texture(fs0, (tc0 * sbs_multi_matrix))
					: texture(fs1, (tc0 * sbs_multi_matrix) + vec2(-1.f, 0.f));
			case STEREO_MODE_OVER_UNDER:
				return (tc0.y < 0.5)
					? texture(fs0, (tc0 * ou_multi_matrix))
					: texture(fs1, (tc0 * ou_multi_matrix) + vec2(0.f, -1.f));
			case STEREO_MODE_INTERLACED:
				return ((int(gl_FragCoord.y) & 1) > 0)
					? texture(fs0, tc0)
					: texture(fs1, tc0);
			default: // undefined behavior
				return texture(fs0, tc0);
		}
	}

	// Unreachable. Return debug color fill
	return vec4(1., 0., 0., 1.);
}

void main()
{
	vec4 color = read_source();
	color.rgb = pow(color.rgb, vec3(gamma));
	ocol = (limit_range == FALSE)
		? color
		: ((color * 220.) + 16.) / 255.;
}
)"
