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 parameter of Disable, Enable, and IsEnabled, and by
the 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 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 or
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
parameter) ... and must be one of
FUNC_ADD, FUNC_SUBTRACT, FUNC_REVERSE_SUBTRACT, MIN, or MAX as listed
in Table 4.1. 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 and override its luminosity
// with that of the RGB color .
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 and override its saturation with
// that of the RGB color . The override the luminosity of the
// result with that of the RGB color .
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 ,
// 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 :
where 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.