uniform sampler2D tex_in;
uniform sampler2D garbage_in;
uniform sampler2D core_in;
uniform int color_in;
uniform bool garbage_in_enabled;
uniform bool core_in_enabled;
uniform float highlights_in;
uniform float shadows_in;
uniform bool mask_only_in;

in vec2 ove_texcoord;
out vec4 frag_color;

#define SCREEN_COLOR_GREEN 0
#define SCREEN_COLOR_BLUE  1

void main(void) {
    vec4 tex_col = texture(tex_in, ove_texcoord);

    // Unassociate RGB before calculating values
    vec4 unassoc = tex_col;
    if (unassoc.a > 0) {
      unassoc.rgb /= unassoc.a;
    }

    // Simple keyer, generates a inverted mask (background is white, foreground black)
    float mask;
    if (color_in == SCREEN_COLOR_GREEN) {
      mask = (unassoc.g - max(unassoc.r, unassoc.b));
    } else{ // Assume SCREEN_COLOR_BLUE
      mask = (unassoc.b - max(unassoc.r, unassoc.g));
    }

    mask = clamp(mask, 0.0, 1.0);

    if (garbage_in_enabled) {
      // Force anything we want to remove to be 1.0
      vec4 garbage = texture(garbage_in, ove_texcoord);
      // Assumes garbage is achromatic
      mask += garbage.r;
      mask = clamp(mask, 0.0, 1.0);
    }

    if (core_in_enabled) {
      // Force anything we want to keep to be 0.1
      vec3 core = texture(core_in, ove_texcoord).rgb;
      vec3 core_invert = 1.0 - core.rgb;
      // Assumes core is achromatic
      mask *= core_invert.r;
      mask = clamp(mask, 0.0, 1.0);
    }

    // Crush blacks and push whites
    mask = highlights_in * (shadows_in * mask - 1.0) + 1.0;
    mask = clamp(mask, 0.0, 1.0);

    // Invert mask
    mask = 1.0 - mask;

    // Multiply color by mask
    tex_col *= mask;

    if (!mask_only_in) {
        frag_color = tex_col;
    } else {
        frag_color = vec4(vec3(mask), 1.0);
    }
}
