KHR_blend_equation_advanced

Name

KHR_blend_equation_advanced

Name Strings

GL_KHR_blend_equation_advanced
GL_KHR_blend_equation_advanced_coherent

Contact

Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)

Notice

Copyright (c) 2012-2015 The Khronos Group Inc. Copyright terms at
    http://www.khronos.org/registry/speccopyright.html

Specification Update Policy

Khronos-approved extension specifications are updated in response to
issues and bugs prioritized by the Khronos OpenGL and OpenGL ES Working Groups. For
extensions which have been promoted to a core Specification, fixes will
first appear in the latest version of that core Specification, and will
eventually be backported to the extension document. This policy is
described in more detail at
    https://www.khronos.org/registry/OpenGL/docs/update_policy.php

Contributors

OpenGL ES Working Group in Khronos
Jeff Bolz, NVIDIA Corporation
Mathias Heyer, NVIDIA Corporation
Mark Kilgard, NVIDIA Corporation
Daniel Koch, NVIDIA Corporation
Rik Cabanier, Adobe
Slawek Grajewski, Intel

Status

Complete.
Ratified by the Khronos Board of Promoters on 2014/03/14.

Version

Last Modified Date:         February 14, 2018
Revision:                   17

Number

ARB Extension #174
OpenGL ES Extension #168

Dependencies

This extension is written against the OpenGL 4.1 Specification
(Compatibility Profile).

This extension is written against the OpenGL Shading Language
Specification, Version 4.10 (Revision 6).

OpenGL 2.0 is required (for Desktop).

OpenGL ES 2.0 is required (for mobile).

EXT_blend_minmax is required (for mobile).

This extension interacts with OpenGL 4.0.

This extension interacts with OpenGL 4.1 (Core Profile).

This extension interacts with OpenGL 4.3 or later.

This extension interacts with OpenGL ES 2.0.

This extension interacts with OpenGL ES 3.0.

This extension interacts with NV_path_rendering.

Overview

This extension adds a number of "advanced" blending equations that can be
used to perform new color blending operations, many of which are more
complex than the standard blend modes provided by unextended OpenGL.  This
extension provides two different extension string entries:

- KHR_blend_equation_advanced:  Provides the new blending equations, but
  guarantees defined results only if each sample is touched no more than
  once in any single rendering pass.  The command BlendBarrierKHR() is
  provided to indicate a boundary between passes.

- KHR_blend_equation_advanced_coherent:  Provides the new blending
  equations, and guarantees that blending is done coherently and in API
  primitive order.  An enable is provided to allow implementations to opt
  out of fully coherent blending and instead behave as though only
  KHR_blend_equation_advanced were supported.

Some implementations may support KHR_blend_equation_advanced without
supporting KHR_blend_equation_advanced_coherent.

In unextended OpenGL, the set of blending equations is limited, and can be
expressed very simply.  The MIN and MAX blend equations simply compute
component-wise minimums or maximums of source and destination color
components.  The FUNC_ADD, FUNC_SUBTRACT, and FUNC_REVERSE_SUBTRACT
multiply the source and destination colors by source and destination
factors and either add the two products together or subtract one from the
other.  This limited set of operations supports many common blending
operations but precludes the use of more sophisticated transparency and
blending operations commonly available in many dedicated imaging APIs.

This extension provides a number of new "advanced" blending equations.
Unlike traditional blending operations using the FUNC_ADD equation, these
blending equations do not use source and destination factors specified by
BlendFunc.  Instead, each blend equation specifies a complete equation
based on the source and destination colors.  These new blend equations are
used for both RGB and alpha components; they may not be used to perform
separate RGB and alpha blending (via functions like
BlendEquationSeparate).

These blending operations are performed using premultiplied source and
destination colors, where RGB colors produced by the fragment shader and
stored in the framebuffer are considered to be multiplied by alpha
(coverage).  Many of these advanced blending equations are formulated
where the result of blending source and destination colors with partial
coverage have three separate contributions:  from the portions covered by
both the source and the destination, from the portion covered only by the
source, and from the portion covered only by the destination.  Such
equations are defined assuming that the source and destination coverage
have no spatial correlation within the pixel.

In addition to the coherency issues on implementations not supporting
KHR_blend_equation_advanced_coherent, this extension has several
limitations worth noting.  First, the new blend equations are not
supported while rendering to more than one color buffer at once; an
INVALID_OPERATION will be generated if an application attempts to render
any primitives in this unsupported configuration.  Additionally, blending
precision may be limited to 16-bit floating-point, which could result in a
loss of precision and dynamic range for framebuffer formats with 32-bit
floating-point components, and in a loss of precision for formats with 12-
and 16-bit signed or unsigned normalized integer components.

New Procedures and Functions

void BlendBarrierKHR(void);

New Tokens

Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, and by
the <pname> parameter of GetIntegerv, GetBooleanv, GetFloatv, GetDoublev
and GetInteger64v:

    BLEND_ADVANCED_COHERENT_KHR                     0x9285

Note:  The BLEND_ADVANCED_COHERENT_KHR enable is provided if and only if
the KHR_blend_equation_advanced_coherent extension is supported.  On
implementations supporting only KHR_blend_equation_advanced, this enable
is considered not to exist.

Accepted by the <mode> parameter of BlendEquation and BlendEquationi:

    MULTIPLY_KHR                                    0x9294
    SCREEN_KHR                                      0x9295
    OVERLAY_KHR                                     0x9296
    DARKEN_KHR                                      0x9297
    LIGHTEN_KHR                                     0x9298
    COLORDODGE_KHR                                  0x9299
    COLORBURN_KHR                                   0x929A
    HARDLIGHT_KHR                                   0x929B
    SOFTLIGHT_KHR                                   0x929C
    DIFFERENCE_KHR                                  0x929E
    EXCLUSION_KHR                                   0x92A0

    HSL_HUE_KHR                                     0x92AD
    HSL_SATURATION_KHR                              0x92AE
    HSL_COLOR_KHR                                   0x92AF
    HSL_LUMINOSITY_KHR                              0x92B0

NOTE:  These enums are not accepted by the <modeRGB> or <modeAlpha>
parameters of BlendEquationSeparate or BlendEquationSeparatei.

Additions to Chapter 2 of the OpenGL 4.1 Specification (OpenGL Operation)

None.

Additions to Chapter 3 of the OpenGL 4.1 Specification (Rasterization)

None.

Additions to Chapter 4 of the OpenGL 4.1 Specification (Per-Fragment Operations and the Frame Buffer)

Modify Section 4.1.8, Blending (p. 359).

(modify the first paragraph, p. 361, allowing for new values in the
<mode> parameter) ... <modeRGB> and <modeAlpha> must be one of
FUNC_ADD, FUNC_SUBTRACT, FUNC_REVERSE_SUBTRACT, MIN, or MAX as listed
in Table 4.1.  <mode> must be one of the mode values in Table 4.1,
or one of the blend equations listed in tables X.1 and X.2. ...

(modify the third paragraph, p. 361, specifying minimum precision and
dynamic range for blend operations) ... Blending computations are treated
as if carried out in floating-point.  For the equations in table 4.1,
blending computations will be performed with a precision and dynamic range
no lower than that used to represent destination components.  For the
equations in table X.1 and X.2, blending computations will be performed
with a precision and dynamic range no lower than the smaller of that used
to represent destination components or that used to represent 16-bit
floating-point values as described in section 2.1.1.

(add unnumbered subsection prior to "Dual Source Blending and Multiple
 Draw Buffers", p. 363)

Advanced Blend Equations

The advanced blend equations are those listed in tables X.1 and X.2.  When
using one of these equations, blending is performed according to the
following equations:

  R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
  G = f(Gs',Gd')*p0(As,Ad) + Y*Gs'*p1(As,Ad) + Z*Gd'*p2(As,Ad)
  B = f(Bs',Bd')*p0(As,Ad) + Y*Bs'*p1(As,Ad) + Z*Bd'*p2(As,Ad)
  A =          X*p0(As,Ad) +     Y*p1(As,Ad) +     Z*p2(As,Ad)

where the function f and terms X, Y, and Z are specified in the table.
The R, G, and B components of the source color used for blending are
considered to have been premultiplied by the A component prior to
blending.  The base source color (Rs',Gs',Bs') is obtained by dividing
through by the A component:

  (Rs', Gs', Bs') =
    (0, 0, 0),              if As == 0
    (Rs/As, Gs/As, Bs/As),  otherwise

The destination color components are always considered to have been
premultiplied by the destination A component and the base destination
color (Rd', Gd', Bd') is obtained by dividing through by the A component:

  (Rd', Gd', Bd') =
    (0, 0, 0),               if Ad == 0
    (Rd/Ad, Gd/Ad, Bd/Ad),   otherwise

When blending using advanced blend equations, we expect that the R, G, and
B components of premultiplied source and destination color inputs be
stored as the product of non-premultiplied R, G, and B components and the
A component of the color.  If any R, G, or B component of a premultiplied
input color is non-zero and the A component is zero, the color is
considered ill-formed, and the corresponding component of the blend result
will be undefined.

The weighting functions p0, p1, and p2 are defined as follows:

  p0(As,Ad) = As*Ad
  p1(As,Ad) = As*(1-Ad)
  p2(As,Ad) = Ad*(1-As)

In these functions, the A components of the source and destination colors
are taken to indicate the portion of the pixel covered by the fragment
(source) and the fragments previously accumulated in the pixel
(destination).  The functions p0, p1, and p2 approximate the relative
portion of the pixel covered by the intersection of the source and
destination, covered only by the source, and covered only by the
destination, respectively.  The equations defined here assume that there
is no correlation between the source and destination coverage.


  Mode                      Blend Coefficients
  --------------------      -----------------------------------
  MULTIPLY_KHR              (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = Cs*Cd

  SCREEN_KHR                (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = Cs+Cd-Cs*Cd

  OVERLAY_KHR               (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
                                       1-2*(1-Cs)*(1-Cd), otherwise

  DARKEN_KHR                (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = min(Cs,Cd)

  LIGHTEN_KHR               (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = max(Cs,Cd)

  COLORDODGE_KHR            (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) =
                              0, if Cd <= 0
                              min(1,Cd/(1-Cs)), if Cd > 0 and Cs < 1
                              1, if Cd > 0 and Cs >= 1

  COLORBURN_KHR             (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) =
                              1, if Cd >= 1
                              1 - min(1,(1-Cd)/Cs), if Cd < 1 and Cs > 0
                              0, if Cd < 1 and Cs <= 0

  HARDLIGHT_KHR             (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
                                       1-2*(1-Cs)*(1-Cd), otherwise

  SOFTLIGHT_KHR             (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) =
                              Cd-(1-2*Cs)*Cd*(1-Cd),
                                if Cs <= 0.5
                              Cd+(2*Cs-1)*Cd*((16*Cd-12)*Cd+3),
                                if Cs > 0.5 and Cd <= 0.25
                              Cd+(2*Cs-1)*(sqrt(Cd)-Cd),
                                if Cs > 0.5 and Cd > 0.25

  DIFFERENCE_KHR            (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = abs(Cd-Cs)

  EXCLUSION_KHR             (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = Cs+Cd-2*Cs*Cd

  Table X.1, Advanced Blend Equations


When using one of the HSL blend equations in table X.2 as the blend
equation, the RGB color components produced by the function f() are
effectively obtained by converting both the non-premultiplied source and
destination colors to the HSL (hue, saturation, luminosity) color space,
generating a new HSL color by selecting H, S, and L components from the
source or destination according to the blend equation, and then converting
the result back to RGB.  The HSL blend equations are only well defined
when the values of the input color components are in the range [0..1].
In the equations below, a blended RGB color is produced according to the
following pseudocode:

  float minv3(vec3 c) {
    return min(min(c.r, c.g), c.b);
  }
  float maxv3(vec3 c) {
    return max(max(c.r, c.g), c.b);
  }
  float lumv3(vec3 c) {
    return dot(c, vec3(0.30, 0.59, 0.11));
  }
  float satv3(vec3 c) {
    return maxv3(c) - minv3(c);
  }

  // If any color components are outside [0,1], adjust the color to
  // get the components in range.
  vec3 ClipColor(vec3 color) {
    float lum = lumv3(color);
    float mincol = minv3(color);
    float maxcol = maxv3(color);
    if (mincol < 0.0) {
      color = lum + ((color-lum)*lum) / (lum-mincol);
    }
    if (maxcol > 1.0) {
      color = lum + ((color-lum)*(1-lum)) / (maxcol-lum);
    }
    return color;
  }

  // Take the base RGB color <cbase> and override its luminosity
  // with that of the RGB color <clum>.
  vec3 SetLum(vec3 cbase, vec3 clum) {
    float lbase = lumv3(cbase);
    float llum = lumv3(clum);
    float ldiff = llum - lbase;
    vec3 color = cbase + vec3(ldiff);
    return ClipColor(color);
  }

  // Take the base RGB color <cbase> and override its saturation with
  // that of the RGB color <csat>.  The override the luminosity of the
  // result with that of the RGB color <clum>.
  vec3 SetLumSat(vec3 cbase, vec3 csat, vec3 clum)
  {
    float minbase = minv3(cbase);
    float sbase = satv3(cbase);
    float ssat = satv3(csat);
    vec3 color;
    if (sbase > 0) {
      // Equivalent (modulo rounding errors) to setting the
      // smallest (R,G,B) component to 0, the largest to <ssat>,
      // and interpolating the "middle" component based on its
      // original value relative to the smallest/largest.
      color = (cbase - minbase) * ssat / sbase;
    } else {
      color = vec3(0.0);
    }
    return SetLum(color, clum);
  }


  Mode                      Result
  --------------------      ----------------------------------------
  HSL_HUE_KHR               (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = SetLumSat(Cs,Cd,Cd);

  HSL_SATURATION_KHR        (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = SetLumSat(Cd,Cs,Cd);

  HSL_COLOR_KHR             (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = SetLum(Cs,Cd);

  HSL_LUMINOSITY_KHR        (X,Y,Z)  = (1,1,1)
                            f(Cs,Cd) = SetLum(Cd,Cs);

  Table X.2, Hue-Saturation-Luminosity Advanced Blend Equations


Advanced blending equations are supported only when rendering to a single
color buffer using fragment color zero.  If any non-NONE draw buffer uses
a blend equation found in table X.1 or X.2, the error INVALID_OPERATION is
generated by [[Compatibility Profile:  Begin or any operation that
implicitly calls Begin (such as DrawElements)]] [[Core Profile and OpenGL
ES:  DrawArrays and the other drawing commands defined in section 2.8.3]]
if:

  * the draw buffer for color output zero selects multiple color buffers
    (e.g., FRONT_AND_BACK in the default framebuffer); or

  * the draw buffer for any other color output is not NONE.

[[ The following paragraph applies to KHR_blend_equation_advanced only. ]]

When using advanced blending equations, applications should split their
rendering into a collection of blending passes, none of which touch an
individual sample in the framebuffer more than once.  The results of
blending are undefined if the sample being blended has been touched
previously in the same pass.  The command

  void BlendBarrierKHR(void);

specifies a boundary between passes when using advanced blend equations.
Any command that causes the value of a sample to be modified using the
framebuffer is considered to touch the sample, including clears, blended
or unblended primitives, and BlitFramebuffer copies.

[[ The following paragraph applies to KHR_blend_equation_advanced_coherent
   only. ]]

When using advanced blending equations, blending is typically done
coherently and in primitive order.  When an individual sample is covered
by multiple primitives, blending for that sample is performed sequentially
in the order in which the primitives were submitted.  This coherent
blending is enabled by default, but can be enabled or disabled by calling
Enable or Disable with the symbolic constant BLEND_ADVANCED_COHERENT_KHR.
If coherent blending is disabled, applications should split their
rendering into a collection of blending passes, none of which touch an
individual sample in the framebuffer more than once.  When coherent
blending is disabled, the results of blending are undefined if the sample
being blended has been touched previously in the same pass.  The command

  void BlendBarrierKHR(void);

specifies a boundary between passes when using advanced blend equations.
Any command that causes the value of a sample to be modified using the
framebuffer is considered to touch the sample, including clears, blended
or unblended primitives, and BlitFramebuffer copies.

Advanced blending equations require the use of a fragment shader with a
matching "blend_support" layout qualifier.  If the current blend equation
is found in table X.1 or X.2, and the active fragment shader does not
include the layout qualifier matching the blend equation or
"blend_support_all_equations", the error INVALID_OPERATION is generated by
[[Compatibility Profile:  Begin or any operation that implicitly calls
Begin (such as DrawElements)]] [[Core Profile and OpenGL ES:  DrawArrays
and the other drawing commands defined in section 2.8.3]] The set of
layout qualifiers supported in fragment shaders is specified in sectino
4.3.8.2 of the OpenGL Shading Language Specification.

Additions to Chapter 5 of the OpenGL 4.1 Specification (Special Functions)

None.

Additions to Chapter 6 of the OpenGL 4.1 Specification (State and State Requests)

None.

Additions to Appendix A of the OpenGL 4.1 Specification (Invariance)

None.

Additions to the AGL/GLX/WGL/EGL Specifications

None.

Additions to the OpenGL Shading Language Specification, Version 4.10

Including the following line in a shader can be used to control the
language features described in this extension:

  #extension GL_KHR_blend_equation_advanced : <behavior>

where <behavior> is as specified in section 3.3.

A new preprocessor #define is added to the OpenGL Shading Language:

  #define GL_KHR_blend_equation_advanced 1

Modify Section 4.3.8.2, Output Layout Qualifiers, p. 47

(add to the end of the section, p. 50)

Fragment shaders additionally support the following layout qualifiers,
specifying a set of advanced blend equations supported when the fragment
shader is used.  These layout qualifiers are only permitted on the
interface qualifier out, and use the identifiers specified in the "Layout
Qualifier" column of Table X.3.

If a layout qualifier in Table X.3 is specified in the fragment shader,
the fragment shader may be used with the corresponding advanced blend
equation in the "Blend Equation(s) Supported" column.  Additionally, the
special qualifier "blend_support_all_equations" indicates that the shader
may be used with any advanced blending equation supported by the OpenGL
Specification.  It is not an error to specify more than one of these
identifiers in any fragment shader.  Specifying more than one qualifier or
"blend_support_all_equations" means that the fragment shader may be used
with multiple advanced blend equations.  Additionally, it is not an error
to specify any single any of these layout qualifiers more than once.

    Layout Qualifier                Blend Equation(s) Supported
    ------------------------        ------------------------------
    blend_support_multiply          MULTIPLY_KHR
    blend_support_screen            SCREEN_KHR
    blend_support_overlay           OVERLAY_KHR
    blend_support_darken            DARKEN_KHR
    blend_support_lighten           LIGHTEN_KHR
    blend_support_colordodge        COLORDODGE_KHR
    blend_support_colorburn         COLORBURN_KHR
    blend_support_hardlight         HARDLIGHT_KHR
    blend_support_softlight         SOFTLIGHT_KHR
    blend_support_difference        DIFFERENCE_KHR
    blend_support_exclusion         EXCLUSION_KHR
    blend_support_hsl_hue           HSL_HUE_KHR
    blend_support_hsl_saturation    HSL_SATURATION_KHR
    blend_support_hsl_color         HSL_COLOR_KHR
    blend_support_hsl_luminosity    HSL_LUMINOSITY_KHR
    blend_support_all_equations     /all blend equations/

  Table X.3, Fragment Shader Output Layout Qualifiers for Blend Support

A draw-time error will be generated in the OpenGL API if an application
attempts to render using an advanced blending equation without having a
matching layout qualifier specified in the active fragment shader.

GLX Protocol

!!! TBD

Dependencies on OpenGL 4.0

If OpenGL 4.0 is not supported, references to the BlendEquationi API should
be removed.

Dependencies on OpenGL 4.1 (Core Profile)

This extension throws an INVALID_OPERATION when Begin is called if advanced
blend equations are used in conjunction with multiple draw buffers.  For
the core profile of OpenGL 4.1 (and other versions of OpenGL), there is no
Begin command; instead, the error is thrown by other rendering commands
such as DrawArrays.  The language in this specification documenting the
error has separate versions for the core and compatibility profiles.

Dependencies on OpenGL 4.3 or later (any Profile)

References to Chapter 4 are replaced with references to Chapter 17 (Writing
Fragments and Samples to the Framebuffer).
References to section 4.1.8 are replaced with references to section 17.3.8.
References to Table 4.1 are replace with references to Table 17.1.
References to section 2.1.1 are replaced with references to section 2.3.3.

Dependencies on OpenGL ES 2.0

If unextended OpenGL ES 2.0 is supported, references to BlendEquationi,
BlendEquationSeparatei, GetInteger64v, and GetDoublev should be ignored.

Ignore any references to multiple draw buffers if EXT_draw_buffers or
NV_draw_buffers is not supported.

Dependencies on EXT_blend_minmax

Requires EXT_blend_minmax on OpenGL ES 2.0 implementations and references
to MIN and MAX should be replace by references to MIN_EXT and MAX_EXT as
introduced by that extension.

Dependencies on OpenGL ES 3.0

If unextended OpenGL ES 3.0 is supported, references to BlendEquationi,
BlendEquationSeparatei, and GetDoublev should be ignored.

Dependencies on NV_path_rendering

When NV_path_rendering is supported, covering geometry generated by the
commands CoverFillPathNV, CoverFillPathInstancedNV, CoverStrokePathNV, and
CoverStrokePathInstancedNV will automatically be blended coherently
relative to previous geometry when using the blend equations in this
extension.  This guarantee is provided even on implementations supporting
only NV_blend_equation_advanced.

Insert the following language after the discussion of the
BlendBarrierKHR() command for both extensions:

  [[ For KHR_blend_equation_advanced only: ]]

  The commands CoverFillPathNV, CoverFillPathInstancedNV,
  CoverStrokePathNV, and CoverStrokePathInstancedNV are considered to
  start a new blending pass, as though BlendBarrierKHR were called prior
  to the cover operation.  If a cover primitive is followed by subsequent
  non-cover primitives using advanced blend equations and touching the
  same samples, applications must call BlendBarrierKHR after the cover
  primitives to ensure defined blending results.

  [[ For KHR_blend_equation_advanced_coherent, the language immediately
     above should be used, but the first sentence should be prefixed with
     "When coherent blending is disabled, ...". ]]

Errors

If any non-NONE draw buffer uses a blend equation found in table X.1 or
X.2, the error INVALID_OPERATION is generated by Begin or any operation
that implicitly calls Begin (such as DrawElements) if:

  * the draw buffer for color output zero selects multiple color buffers
    (e.g., FRONT_AND_BACK in the default framebuffer); or

  * the draw buffer for any other color output is not NONE.

New State Initial Get Value Type Get Command Value Description Sec Attribute ——————– —- ———— ———— ———————— —– ———— BLEND_ADVANCED_ B IsEnabled TRUE are advanced blending 4.1.8 color-buffer COHERENT_KHR equations guaranteed to be evaluated coherently?

Note:  The BLEND_ADVANCED_COHERENT_KHR enable is provided if and only if
the KHR_blend_equation_advanced_coherent extension is supported.  On
implementations supporting only KHR_blend_equation_advanced, this enable
is considered not to exist.

New Implementation Dependent State

None.

Issues

Note:  These issues apply specifically to the definition of the
KHR_blend_equation_advanced specification, which was derived from the
extension NV_blend_equation_advanced.  The issues from the original
NV_blend_equation_advanced specification have been removed, but can be
found (as of August 2013) in the OpenGL Registry at:

  http://www.opengl.org/registry/specs/NV/blend_equation_advanced.txt

(0) How does this extension differ from the NV_blend_equation_advanced
    extension for OpenGL and OpenGL ES?

  RESOLVED:  A number of features have been removed from
  NV_blend_equation_advanced, including:

  * The BlendParameterivNV API has been removed, and with it, the
    BLEND_PREMULTIPLIED_SRC_NV and BLEND_OVERLAP_NV parameters.  The spec
    has been refactored to assume premultipled source colors and
    uncorrelated source and destination coverage.

  * A number of less commonly used blend modes have been removed,
    including:

     - certain "X/Y/Z" blending modes supported by few, if any, standards
       (INVERT, INVERT_RGB_NV, LINEARDODGE_NV, LINEARBURN_NV,
       VIVIDLIGHT_NV, LINEARLIGHT_NV, PINLIGHT_NV, HARDMIX_NV)

     - various versions of additive and subtractive modes (PLUS_NV,
       PLUS_CLAMPED_NV, PLUS_CLAMPED_ALPHA_NV, PLUS_DARKER_NV, MINUS_NV,
       MINUS_CLAMPED_NV)

     - other uncommon miscellaneous modes (CONTRAST_NV, INVERT_OVG_NV,
       RED, GREEN, BLUE)

  Additionally, this extension adds blending support layout qualifiers to
  the fragment shader (qualifying "out").  Each fragment shader can
  specify a set of advanced blend equations that can be used when it is
  active.  For example:

    layout(blend_support_hardlight, blend_support_softlight) out;

  specifies that the HARDLIGHT_KHR and SOFTLIGHT_KHR equations are allowed
  when using the shader.  A draw-time error will be generated if an
  advanced blend equation is enabled in the API and a matching layout
  qualifier is not specified in the active fragment shader.

(1) What should we do about the BLEND_PREMULTIPLIED_SRC_NV blend parameter
    from NV_blend_equation_advanced?

  RESOLVED:  Remove this parameter for simplicity.  All equations in this
  extension assume that the source and destination colors are both
  premultiplied.

(2) What should we do about the BLEND_OVERLAP_NV blend parameter from
    NV_blend_equation_advanced?

  RESOLVED:  Remove this parameter for simplicitly.  All equations in this
  extension assume an UNCORRELATED_NV overlap mode.  Blending using the
  UNCORRELATED_NV overlap mode is usually mathematically simpler than
  blending using the DISJOINT_NV or CONJOINT_NV modes.

(3) What set of "complex" blending equations should we support in this
    extension?

  RESOLVED:  During standardization of this extensions, the set of
  equations provided in this extension has been reduced to a smaller
  subset for simplicitly.  The remaining equations are typically found in
  a wide collection of compositing standards.  In particular, the
  standarization process removed several classes of blend equations from
  the NV_blend_equation_advanced, as described in "differences" issue (0)
  above.

(4) Should we support the "Porter-Duff" blend equations (e.g.,
    SRC_OVER_NV) from NV_blend_equation_advanced?

  RESOLVED:  All of these blend equations should be supportable in
  unextended OpenGL ES 3.0, and have been removed for simplicity.  The
  primary rationale for this decision is to reduce the number of internal
  paths required by the driver; some implementations may have separate
  paths for traditional OpenGL blending and for the new advanced blending
  equations.  Redirecting "simple" advanced blending equations to
  traditional fixed-function blending hardware may involved more driver
  implementation work and may have different performance characteristics
  than other "complex" blending equations.

  This approach does mean that an application wanting to use both
  Porter-Duff blend equations and advanced blending equations provided by
  this extension will need GL_to program blending somewhat differently
  when using the Porter-Duff equations:

    if (isPorterDuff(equation)) {
      glBlendEquation(GL_FUNC_ADD);        // enable sf*S+df*D blending
      glBlendFunc(srcFactor, dstFactor);   // and program blend factors
    } else {
      glBlendEquation(equation);  // advanced eqs. don't use BlendFunc
    }

(5) Should we impose any requirements on fragment shaders when used in
    conjunction with advanced blend equations?

  RESOLVED:  Yes.  This extension adds fragment shader layout qualifiers
  allowing individual shaders to specify that they will be used with one
  or multiple advanced blending equations.  When using an advanced
  blending equation from this extension, it is necessary to use a fragment
  shader with a matching layout qualifier.  A draw-time error will be
  generated if the current fragment shader doesn't include a layout
  qualifier matching the current advanced blending mode.

  The rationale for this decision is that some implementations of this
  extension may require special fragment shader code when using advanced
  blending equations, and may perhaps perform the entire blending
  operation in the fragment shader.  Knowing the set of blending equations
  that a fragment shader will be used with at compile time may reduce the
  extent of run-time fragment shader re-compilation when the shader is
  used.

  Note that NV_blend_equation_advanced doesn't include layout qualifiers
  or the draw-time error specified here.

(6) How do we handle coherency when a fragment is hit multiple times?

  RESOLVED:  In this extension, blending equations will be done coherently
  and in primitive order by default, as is the case with traditional
  blending in OpenGL and OpenGL ES.

  The NVIDIA extension provides two separate extension string entries:

    * NV_blend_equation_advanced
    * NV_blend_equation_advanced_coherent

  Exposing the former without the latter signals that the implementation
  can support blending with these equations, but is unable to ensure that
  fragments are blended in order when the same (x,y) is touched multiple
  times.  To ensure coherent results and proper ordering using the
  non-coherent version of the extension, an application must separate its
  rendering into "passes" that touch each (x,y) at most once, and call
  BlendBarrierNV between passes.  There are important use cases (e.g.,
  many path rendering algorithms) where this limitation isn't too
  restrictive, and NVIDIA chose to expose the non-coherent version to
  allow the functionality to be used on a larger set of GPUs.

  This extension is functionally comparable to an implementation of the
  NVIDIA extension exposing both strings, where coherent behavior is
  enabled by default.  NV_blend_equation_advanced_coherent and this
  extension both provide the ability to opt out of this automatic
  coherence by disabling BLEND_ADVANCED_COHERENT_KHR and using
  BlendBarrierKHR manually.  This could theoretically result in higher
  performance -- see issue (32) of the NVIDIA extension for more
  discussion.

(7) How should the blend equations COLORDODGE_KHR and COLORBURN_KHR be
    expressed mathematically?

  RESOLVED:  NVIDIA changed the definition of these equations after the
  NV_blend_equation_advanced spec was originally published, as discussed
  below.  These changes add new special cases to the COLORDODGE_KHR and
  COLORBURN_KHR equations that are found in newer compositing standard
  specifications and in a number of implementations of old and new
  standards.  They believe that the omission of the special case in other
  older specifications is a bug.  They have no plans to add new blend
  equation tokens to support "equivalent" modes without the new special
  case.  We are adopting the same approach in this extension.

  Note, however, that older versions of this extension and older NVIDIA
  drivers implementing it will lack these special cases.  A driver update
  may be required to get the new behavior.

  There is some disagreement in different published specifications about
  how these two blend equations should be handled.  At the time the NVIDIA
  extension was initially developed, all specifications they found that
  specified blending equations mathematically (see issue 28 of
  NV_blend_equation_advanced) were written the same way.  Since then, they
  discovered that newer working drafts of the W3C Compositing and Blending
  Level 1 specification (for CSS and SVG) express "color-burn" as follows
  (translated to our nomenclature):

    if (Cd == 1)            // their Cb (backdrop) is our Cd (destination)
      f(Cs,Cd) = 1          // their B() is our f()
    else if (Cs == 0)
      f(Cs,Cd) = 0
    else
      f(Cs,Cd) = 1 - min(1, (1-Cd)/Cs)

  http://www.w3.org/TR/2013/WD-compositing-1-20131010/
    #blendingcolorburn

  Earlier versions of the same W3C specification, an older SVG compositing
  draft specification, the Adobe PDF specification (and the ISO 32000-1
  standard), and the KHR_advanced_blending extension to OpenVG all specify
  the following equation without the initial special case:

    if (Cs == 0)
      f(Cs,Cd) = 0
    else
      f(Cs,Cd) = 1 - min(1, (1-Cd)/Cs)

    http://www.w3.org/TR/2012/WD-compositing-20120816/
      #blendingcolorburn
    http://www.w3.org/TR/2011/WD-SVGCompositing-20110315/
    http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/
      pdfs/pdf_reference_1-7.pdf
    http://www.khronos.org/registry/vg/extensions/KHR/
      advanced_blending.txt

  For the Adobe PDF specification, the corrected blend equations are
  published in an Adobe supplement to ISO 32000-1 and are expected to be
  accepted in a future version of the standard:

    http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/
      devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf

  The author's understanding is that multiple shipping implementations of
  these blending modes implement the special case for "Cd==1" above,
  including various Adobe products and the open-source Ghostscript
  project.

  We believe that the extra special case in this specification is
  consistent with the physical model of color burning.  Burning is
  described in

    http://en.wikipedia.org/wiki/Dodging_and_burning

  as making a print with normal exposure, and then adding additional
  exposure to darken the overall image.  In the general equation:

    1 - min(1, (1-Cd)/Cs)

  Cs operates as a sort of fudge factor where a value of 1.0 implies no
  additional exposure time and 0.0 implies arbitrarily long additional
  exposure time, where the initial amount of exposure (1-Cd) is multiplied
  by 1/Cs and then clamped to maximum exposure by the min() operation.
  The Cd==1 special case here implies that we get zero exposure in the
  initial print, since 1-Cd==0.  No amount of extra exposure time will
  generate any additional exposure.  This would imply that the final
  result should have zero exposure and thus a final f() value of 1.  This
  matches the initial special case.  Without that special case, we would
  hit the second special case if Cs==0 (infinite exposure time), which
  would yield an incorrect final value of 0 (full exposure).

  A similar issue applies to COLORDODGE_KHR, where some specifications
  include a special case for Cb==0 while others do not.  We have added a
  special case there as well.

(8) The NV_blend_equation_advanced extension has two variants:
    NV_blend_equation_advanced and NV_blend_equation_advanced_coherent.
    Some implementations of that extension are not capable of performing
    fully coherent blending when samples are touched more than once
    without a barrier, and may expose only the former.  Should we follow
    this pattern here or support only the "coherent" variant?

  RESOLVED:  Yes.  The working group originally decided to support only
  the "coherent" variant (revision 4) for simplicity but later decided to
  support both extension string entries as some implementations on both
  OpenGL and OpenGL ES are unable to support the "coherent" variant.
  Applications not wanting to manage coherency manually should look for
  the KHR_blend_equation_advanced_coherent extension and ignore
  KHR_blend_equation_advanced.

(9) We don't permit the use of advanced blend equations with multiple draw
    buffers.  Should we produce compile-, link-, or draw-time errors if we
    encounter a shader that includes both (a) one or more layout
    qualifiers indicating that the shader wants to use advanced blending
    and (b) a color output with a location other than zero?

  RESOLVED:  No.

  In the current extension, there is a draw-time error generated if you
  try to use one of the new blend equations with multiple color targets
  (glDrawBuffers with a count > 1).  With this restriction, any "extra"
  fragment shader color outputs could never be successfully blended into
  the framebuffer with one of these equations.

  When only one draw buffer is enabled when using a shader with multiple
  outputs, "extra" outputs will simply be dropped and have no effect on
  the framebuffer.  You can already do this in unextended OpenGL and
  OpenGL ES without generating an error.  We didn't feel that the value of
  such a warning/error justifies the draw-time overhead needed to detect
  and report such a condition.

  Since this extension requires that you declare the intent to use
  advanced blending using layout qualifers, it is possible to identify a
  shader that may want to use "extra" color outputs with advanced blending
  at compile time, with no draw-time overhead.  We decided not to treat
  this condition as an error for several reasons:

   - Advanced blending layout qualifiers don't require that blending
     actually be enabled.  Multiple draw buffers with multiple outputs
     work just fine in that case.

   - If we treated this condition as an error and a future extension
     relaxed the DrawBuffers restriction, it would be necessary to also
     add a GLSL language feature to disable the now-undesirable error.

(10) What happens when converting a premultiplied color with an alpha of
     zero to a non-premultiplied color?

  RESOLVED:  We specify that a premultiplied color of (0,0,0,0) should
  produce non-premultiplied (R,G,B) values of (0,0,0).  A premultiplied
  color with an alpha of zero and a non-zero R, G, or B component is
  considered to be ill-formed and will produce undefined blending results.

  For a non-premultiplied color (R',G',B',A'), the corresponding
  premultiplied color (R,G,B,A) should satisfy the equation:

    (R,G,B,A) = (R'*A', G'*A', B'*A', A')

  If the alpha of a non-premultiplied color is zero, the corresponding
  premultiplied color (R,G,B,A) should be (0,0,0,0).

  We specify that ill-formed premultiplied colors produce undefined
  blending results to enable certain performance optimizations.  In many
  of these blending equations, the alpha component used as a denominator
  to compute the non-premultiplied color ends up being multiplied by the
  same alpha component in the coverage, resulting in cancellation.  For
  example, implementations may want to substitute a premultiplied
  destination color into the last term of the basic blend equation:

    R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
      =                                    ... + Z*Rd'*(Ad*(1-As))
      =                                    ... + Z*(Rd'*Ad)*(1-As)
      =                                    ... + Z* Rd * (1-As)

  This substitution would be invalid for ill-formed premultiplied
  destination colors.  We choose to specify undefined results for invalid
  input colors rather than requiring implementations to skip such
  optimizations or include logic to check for zero alpha values for each
  input.

(11) For "HSL" blend equations, the blend equation involves a clipping
     step where colors may be "clipped" if the blend would produce
     components are outside the range [0,1]. Are there inputs where this
     blend could produce ill-defined or nonsensical results?
     
  RESOLVED: Yes, the results of HSL blend equations are undefined if the
  input colors have components outside the range [0,1]. Even if the input
  colors are in-range, the basic color adjustment done in these blends
  could produce result components outside the range [0,1]. To compensate,
  the ClipColor() function in the specification interpolates the result
  color and a greyscale value that matches the luminance of the result.
  The math for the clipping operation assumes the luminance of the result
  color is in the range [0,1]. If that isn't the case, the clipping
  operation could result in a divide by zero (when all result components
  have the same out-of-bounds value) or perform an otherwise nonsensical
  computation.

Revision History

Revision 17, February 14, 2018

  Fix ClipColor() equation where in the "if (maxcol > 1.0)" body the
  "(color-lum)*lum" term should have been "(color-lum)*(1-lum)". Also
  add new issue 11 for the case where the inputs to SetLum() are outside
  the range [0..1] and could cause a divide-by-zero in ClipColor().

Revision 16, April 16, 2016 (from a September 30, 2014 edit that wasn't
                             published)

  Fix incorrectly specified color clamping in the HSL blend modes.

Revision 15, May 9, 2015

  Renumber as OpenGL ARB extension instead of vendor extension, by
  symmetry with other KHR Khronos-approved extensions. Add copyright
  notice.

Revision 14, March 14, 2014

  Cast as KHR extension.

Revisions 12 and 13, March 5, 2014

  For non-coherent blending, clarify that all writes to a sample are
  considered to "touch" that sample and require a BlendBarrierKHR call
  before blending overlapping geometry.  Clears, non-blended geometry, and
  copies by BlitFramebuffer or TexSubImage are all considered to "touch" a
  sample (bug 11738).  Specify that non-premultiplied values corresponding
  to ill-conditioned premultiplied colors such as (1,1,1,0) are undefined
  (bug 11739).  Add issue (10) related to the ill-conditioned
  premultiplied color issue.

Revision 11, January 30, 2014

  Cast as OES extension.

Revision 10, January 22, 2014

  Add issue (9), where we decided not to add compile- or link-time errors
  when using both advanced blending and multiple color outputs (bug
  11468).

Revision 9, January 2, 2014

  Fix typo in issue (0).

Revision 8, November 6, 2013

  Restore support for non-coherent-only implementations that was removed
  in revision 4.  Fix the language about non-coherent blending to specify
  that results are undefined only if an individual *sample* is touched
  more than once (instead of *pixel*).  Minor language tweaks to use
  "equations" consistently, instead of sometimes using "modes".

Revision 7, October 21, 2013

  Add a reference to the Adobe supplement to ISO 32000-1, which includes
  the corrected equations for COLORDODGE_NV and COLORBURN_NV.  Move
  "NVIDIA Implementation Details" down a bit in the spec.

Revision 6, October 16, 2013

  Add new special cases for COLORDODGE_KHR and COLORBURN_KHR, as described
  in issue (7).  Mark issue (7) as resolved.

Revision 5, October 15, 2013

  Remove Porter-Duff blend equations from the specification (issue 4).
  Add a Draw-time error if an advanced blending equation is used without
  specifying a matching layout qualifier in the fragment shader (issue 5).

  Add issues for the spec issues discussed during standardization in
  Khronos.  Remove OpenGL ES 2.0 and 3.0 interactions dealing with
  handling tokens present in OpenGL but not the core OpenGL ES
  specification, since the relevant equations (ZERO and XOR) have been
  removed.

Revision 4, September 6, 2013

  Removed support for non-coherent-only implementations.  Implementations
  that could support NV_blend_equation_advanced (app-managed coherency
  only) but not NV_blend_equation_advanced_coherent will be unable to
  support this extension.

Revision 3, August 19, 2013

  Fixed typos in the OpenGL ES 2.0 and 3.0 interactions section of
  NV_blend_equation_advanced.

Revision 2, August 13, 2013

  Removed issues from the original NV_blend_equation_advanced
  specification.  Rename "NV" prefixes and suffixes to "XXX" since the
  future status of this extension is unknown.  Remove the
  BlendParameterivNV function and the BLEND_PREMULTIPLIED_SRC_NV and
  BLEND_OVERLAP_NV parameters.  Source colors are assumed to be
  premultiplied.  The source and destination pixel coverage, derived from
  their respective alpha components, is assumed to be uncorrelated.
  Removed the miscellaneous blend modes (PLUS_NV, PLUS_CLAMPED_NV,
  PLUS_CLAMPED_ALPHA_NV, PLUS_DARKER_NV, MINUS_NV, MINUS_CLAMPED_NV,
  CONTRAST_NV, INVERT_OVG_NV, RED, GREEN, BLUE) from Table X.4 of
  NV_blend_equation_advanced.  Removed some of the less common "X/Y/Z"
  blend modes (INVERT, INVERT_RGB_NV, LINEARDODGE_NV, LINEARBURN_NV,
  VIVIDLIGHT_NV, LINEARLIGHT_NV, PINLIGHT_NV, HARDMIX_NV).  Add layout
  qualifiers to the OpenGL Shading Language to indicate the set of
  advanced blend equations are supported with a particular fragment
  shader; using blend equations not identified in the current fragment
  shader result in undefined blending results.

Revision 1, August 13, 2013

  Forked the original NV_blend_equation_advanced specification.