justburner 79884d
#ifdef GL_ES
justburner 79884d
precision mediump float;
justburner 79884d
#endif
justburner 79884d
justburner 79884d
justburner 79884d
uniform mat3      worldToOutput;
justburner 79884d
justburner 79884d
uniform sampler2D inputImage[2];
justburner 79884d
uniform mat3      outputToInput[2];
justburner 79884d
justburner fc0e00
uniform bool bhue;    // Blend HUE?
justburner fc0e00
uniform bool bsat;    // Blend Saturation?
justburner fc0e00
uniform bool blum;    // Blend Luminosity?
justburner fc0e00
uniform float balpha; // Blending Alpha
justburner fc0e00
uniform bool bmask;   // Base mask?
justburner 79884d
justburner fc0e00
// ---------------------------
justburner 79884d
// Blending calculations from:
justburner 79884d
// https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_blend_equation_advanced.txt
justburner 79884d
justburner 79884d
float minv3(vec3 c)
justburner 79884d
{
justburner 79884d
  return min(min(c.r, c.g), c.b);
justburner 79884d
}
justburner 79884d
justburner 79884d
float maxv3(vec3 c)
justburner 79884d
{
justburner 79884d
  return max(max(c.r, c.g), c.b);
justburner 79884d
}
justburner 79884d
justburner 79884d
float lumv3(vec3 c)
justburner 79884d
{
justburner 79884d
  return dot(c, vec3(0.30, 0.59, 0.11));
justburner 79884d
}
justburner 79884d
justburner 79884d
float satv3(vec3 c)
justburner 79884d
{
justburner 79884d
  return maxv3(c) - minv3(c);
justburner 79884d
}
justburner 79884d
justburner 79884d
// If any color components are outside [0,1], adjust the color to get the components in range.
justburner 79884d
vec3 ClipColor(vec3 color)
justburner 79884d
{
justburner 79884d
  float lum = lumv3(color);
justburner 79884d
  float mincol = minv3(color);
justburner 79884d
  float maxcol = maxv3(color);
justburner 79884d
  if (mincol < 0.0) {
justburner 79884d
    color = lum + ((color-lum) * lum) / (lum-mincol);
justburner 79884d
  }
justburner 79884d
  if (maxcol > 1.0) {
justburner 79884d
    color = lum + ((color-lum) * (1.0 -lum)) / (maxcol-lum);
justburner 79884d
  }
justburner 79884d
  return color;
justburner 79884d
}
justburner 79884d
justburner 79884d
// Take the base RGB color <cbase> and override its luminosity</cbase>
justburner 79884d
// with that of the RGB color <clum>.</clum>
justburner 79884d
vec3 SetLum(vec3 cbase, vec3 clum)
justburner 79884d
{
justburner 79884d
  float lbase = lumv3(cbase);
justburner 79884d
  float llum = lumv3(clum);
justburner 79884d
  float ldiff = llum - lbase;
justburner 79884d
  vec3 color = cbase + vec3(ldiff);
justburner 79884d
  return ClipColor(color);
justburner 79884d
}
justburner 79884d
justburner 79884d
// Take the base RGB color <cbase> and override its saturation with</cbase>
justburner 79884d
// that of the RGB color <csat>.  The override the luminosity of the</csat>
justburner 79884d
// result with that of the RGB color <clum>.</clum>
justburner 79884d
vec3 SetLumSat(vec3 cbase, vec3 csat, vec3 clum)
justburner 79884d
{
justburner 79884d
  float minbase = minv3(cbase);
justburner 79884d
  float sbase = satv3(cbase);
justburner 79884d
  float ssat = satv3(csat);
justburner 79884d
  vec3 color;
justburner 79884d
  if (sbase > 0.0) {
justburner 79884d
    // Equivalent (modulo rounding errors) to setting the
justburner 79884d
    // smallest (R,G,B) component to 0, the largest to <ssat>,</ssat>
justburner 79884d
    // and interpolating the "middle" component based on its
justburner 79884d
    // original value relative to the smallest/largest.
justburner 79884d
    color = (cbase - minbase) * ssat / sbase;
justburner 79884d
  } else {
justburner 79884d
    color = vec3(0.0);
justburner 79884d
  }
justburner 79884d
  return SetLum(color, clum);
justburner 79884d
}
justburner 79884d
justburner fc0e00
// ---------------------------
justburner 79884d
justburner 79884d
void main( void )
justburner 79884d
{
justburner 79884d
  // Read sources
justburner fc0e00
  vec2 fg_texPos = (outputToInput[0] * vec3(gl_FragCoord.xy, 1.0)).xy;
justburner fc0e00
  vec2 bg_texPos = (outputToInput[1] * vec3(gl_FragCoord.xy, 1.0)).xy;
justburner fc0e00
  vec4 fg_frag = texture2D(inputImage[0], fg_texPos);
justburner fc0e00
  vec4 bg_frag = texture2D(inputImage[1], bg_texPos);
justburner 79884d
justburner 79884d
  // De-premultiplication
justburner fc0e00
  vec3 fg_pix = vec3(0.0);
justburner fc0e00
  if (fg_frag.a > 0.0) fg_pix = fg_frag.rgb / fg_frag.a;
justburner fc0e00
  vec3 bg_pix = vec3(0.0);
justburner fc0e00
  if (bg_frag.a > 0.0) bg_pix = bg_frag.rgb / bg_frag.a;
justburner 79884d
justburner 79884d
  // Figure out output alpha
justburner fc0e00
  float fg_alpha = fg_frag.a * balpha;
justburner fc0e00
  float bg_alpha = bg_frag.a;
justburner fc0e00
  if (bmask) {
justburner fc0e00
    gl_FragColor.a = bg_alpha;
justburner fc0e00
  } else {
justburner fc0e00
    gl_FragColor.a = fg_alpha + bg_alpha * (1.0 - fg_alpha);
justburner fc0e00
  }
justburner 79884d
  if (gl_FragColor.a <= 0.0) discard;
justburner fc0e00
  
justburner 79884d
  // Perform blending
justburner fc0e00
  if (fg_alpha > 0.0 && bg_alpha > 0.0) {
justburner fc0e00
    vec3 o_pix = SetLumSat(bhue ? fg_pix : bg_pix, bsat ? fg_pix : bg_pix, blum ? fg_pix : bg_pix);
justburner fc0e00
    gl_FragColor.rgb = mix(bg_pix, o_pix, balpha);
justburner fc0e00
  } else if (fg_alpha > 0.0) {
justburner fc0e00
    gl_FragColor.rgb = fg_pix;
justburner 79884d
  } else {
justburner fc0e00
    gl_FragColor.rgb = bg_pix;
justburner 79884d
  }
justburner 79884d
justburner 79884d
  // Premultiplication
justburner 79884d
  gl_FragColor.rgb *= gl_FragColor.a;
justburner 79884d
}