blob: bfe1115d01603433dc82b05cc66017f18f918ce8 [file] [log] [blame]
Name
NV_blend_equation_advanced
Name Strings
GL_NV_blend_equation_advanced
GL_NV_blend_equation_advanced_coherent
Contact
Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)
Contributors
Jeff Bolz, NVIDIA Corporation
Mathias Heyer, NVIDIA Corporation
Mark Kilgard, NVIDIA Corporation
Daniel Koch, NVIDIA Corporation
Rik Cabanier, Adobe
Status
NV_blend_equation_advanced is released in NVIDIA Driver Release
326.xx (June 2013).
Version
Last Modified Date: February 14, 2018
NVIDIA Revision: 10
Number
OpenGL Extension #433
OpenGL ES Extension #163
Dependencies
This extension is written against the OpenGL 4.1 Specification
(Compatibility Profile).
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:
- NV_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 BlendBarrierNV() is
provided to indicate a boundary between passes.
- NV_blend_equation_advanced_coherent: Provides the new blending
equations, and guarantees that blending is done coherently and in API
primitive ordering. An enable is provided to allow implementations to
opt out of fully coherent blending and instead behave as though only
NV_blend_equation_advanced were supported.
Some implementations may support NV_blend_equation_advanced without
supporting NV_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 colors, where
RGB colors stored in the framebuffer are considered to be multiplied by
alpha (coverage). The fragment color may be considered premultiplied or
non-premultiplied, according the BLEND_PREMULTIPLIED_SRC_NV blending
parameter (as specified by the new BlendParameteriNV function). If
fragment color is considered non-premultiplied, the (R,G,B) color
components are multiplied by the alpha component prior to blending. For
non-premultiplied color components in the range [0,1], the corresponding
premultiplied color component would have values in the range [0*A,1*A].
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. The blend parameter
BLEND_OVERLAP_NV can be used to specify a correlation between source and
destination pixel coverage. If set to CONJOINT_NV, the source and
destination are considered to have maximal overlap, as would be the case
if drawing two objects on top of each other. If set to DISJOINT_NV, the
source and destination are considered to have minimal overlap, as would be
the case when rendering a complex polygon tessellated into individual
non-intersecting triangles. If set to UNCORRELATED_NV (default), the
source and destination coverage are assumed to have no spatial correlation
within the pixel.
In addition to the coherency issues on implementations not supporting
NV_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 BlendParameteriNV(enum pname, int value);
void BlendBarrierNV(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_NV 0x9285
Note: The BLEND_ADVANCED_COHERENT_NV enable is provided if and only if
the NV_blend_equation_advanced_coherent extension is supported. On
implementations supporting only NV_blend_equation_advanced, this enable is
considered not to exist.
Accepted by the <pname> parameter of BlendParameteriNV, GetBooleanv,
GetIntegerv, GetInteger64v, GetFloatv, and GetDoublev:
BLEND_PREMULTIPLIED_SRC_NV 0x9280
BLEND_OVERLAP_NV 0x9281
Accepted by the <value> parameter of BlendParameteriNV when <pname> is
BLEND_PREMULTIPLIED_SRC_NV:
TRUE
FALSE
Accepted by the <value> parameter of BlendParameteriNV when <pname> is
BLEND_OVERLAP_NV:
UNCORRELATED_NV 0x9282
DISJOINT_NV 0x9283
CONJOINT_NV 0x9284
Accepted by the <mode> parameter of BlendEquation and BlendEquationi:
ZERO // reused from core
SRC_NV 0x9286
DST_NV 0x9287
SRC_OVER_NV 0x9288
DST_OVER_NV 0x9289
SRC_IN_NV 0x928A
DST_IN_NV 0x928B
SRC_OUT_NV 0x928C
DST_OUT_NV 0x928D
SRC_ATOP_NV 0x928E
DST_ATOP_NV 0x928F
XOR_NV 0x1506
MULTIPLY_NV 0x9294
SCREEN_NV 0x9295
OVERLAY_NV 0x9296
DARKEN_NV 0x9297
LIGHTEN_NV 0x9298
COLORDODGE_NV 0x9299
COLORBURN_NV 0x929A
HARDLIGHT_NV 0x929B
SOFTLIGHT_NV 0x929C
DIFFERENCE_NV 0x929E
EXCLUSION_NV 0x92A0
INVERT // reused from core
INVERT_RGB_NV 0x92A3
LINEARDODGE_NV 0x92A4
LINEARBURN_NV 0x92A5
VIVIDLIGHT_NV 0x92A6
LINEARLIGHT_NV 0x92A7
PINLIGHT_NV 0x92A8
HARDMIX_NV 0x92A9
HSL_HUE_NV 0x92AD
HSL_SATURATION_NV 0x92AE
HSL_COLOR_NV 0x92AF
HSL_LUMINOSITY_NV 0x92B0
PLUS_NV 0x9291
PLUS_CLAMPED_NV 0x92B1
PLUS_CLAMPED_ALPHA_NV 0x92B2
PLUS_DARKER_NV 0x9292
MINUS_NV 0x929F
MINUS_CLAMPED_NV 0x92B3
CONTRAST_NV 0x92A1
INVERT_OVG_NV 0x92B4
RED_NV 0x1903
GREEN_NV 0x1904
BLUE_NV 0x1905
NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha>
parameters of BlendEquationSeparate or BlendEquationSeparatei.
NOTE: The tokens XOR_NV, RED_NV, GREEN_NV, and BLUE_NV have the same
values as core OpenGL API enumerants with names without the "_NV"
suffixes. Either #define can be used, but the non-suffixed #defines are
not available in OpenGL ES 2.0 and XOR is not available in OpenGL ES 3.0.
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 values in Table 4.1,
or one of the blend equations listed in tables X.2, X.3, and X.4. ...
(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.2, X.3, and X.4, 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.2, X.3, and X.4.
Parameters related to the advanced blend equations can be set by calling
void BlendParameteriNV(enum pname, int param);
with <pname> set to BLEND_PREMULTIPLIED_SRC_NV or BLEND_OVERLAP_NV. When
<pname> is BLEND_PREMULTIPLIED_SRC_NV, the valid values for <param> are
TRUE or FALSE. When <pname> is BLEND_OVERLAP_NV, the valid values for
<param> are UNCORRELATED_NV, CONJOINT_NV, and DISJOINT_NV. An
INVALID_ENUM error is generated if <pname> is not
BLEND_PREMULTIPLIED_SRC_NV or BLEND_OVERLAP_NV, or if <param> is not a
legal value for <pname>.
When using one of the equations in table X.2 or X.3, 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
derived according to the premultiplied source color blending parameter,
which is set by calling BlendParameteriNV with <pname> set to
BLEND_PREMULTIPLIED_SRC_NV, and <param> set to TRUE or FALSE.
If the parameter is set to TRUE, the fragment color components 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
If the premultiplied source color parameter is FALSE, the fragment color
components are used as the base color:
(Rs', Gs', Bs') = (Rs, Gs, Bs)
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 component values
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 in table X.1. 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. These
functions are specified by the blend overlap parameter, which can be set
by calling BlendParameteriNV with <pname> set to BLEND_OVERLAP_NV. <param>
can be one of UNCORRELATED_NV (default), CONJOINT_NV, and DISJOINT_NV.
UNCORRELATED_NV indicates that there is no correlation between the source
and destination coverage. CONJOINT_NV and DISJOINT_NV indicate that the
source and destination coverage are considered to have maximal or minimal
overlap, respectively.
Overlap Mode Weighting Equations
--------------- --------------------------
UNCORRELATED_NV p0(As,Ad) = As*Ad
p1(As,Ad) = As*(1-Ad)
p2(As,Ad) = Ad*(1-As)
CONJOINT_NV p0(As,Ad) = min(As,Ad)
p1(As,Ad) = max(As-Ad,0)
p2(As,Ad) = max(Ad-As,0)
DISJOINT_NV p0(As,Ad) = max(As+Ad-1,0)
p1(As,Ad) = min(As,1-Ad)
p2(As,Ad) = min(Ad,1-As)
Table X.1, Advanced Blend Overlap Modes
Mode Blend Coefficients
-------------------- -----------------------------------
ZERO (X,Y,Z) = (0,0,0)
f(Cs,Cd) = 0
SRC_NV (X,Y,Z) = (1,1,0)
f(Cs,Cd) = Cs
DST_NV (X,Y,Z) = (1,0,1)
f(Cs,Cd) = Cd
SRC_OVER_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = Cs
DST_OVER_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = Cd
SRC_IN_NV (X,Y,Z) = (1,0,0)
f(Cs,Cd) = Cs
DST_IN_NV (X,Y,Z) = (1,0,0)
f(Cs,Cd) = Cd
SRC_OUT_NV (X,Y,Z) = (0,1,0)
f(Cs,Cd) = 0
DST_OUT_NV (X,Y,Z) = (0,0,1)
f(Cs,Cd) = 0
SRC_ATOP_NV (X,Y,Z) = (1,0,1)
f(Cs,Cd) = Cs
DST_ATOP_NV (X,Y,Z) = (1,1,0)
f(Cs,Cd) = Cd
XOR_NV (X,Y,Z) = (0,1,1)
f(Cs,Cd) = 0
MULTIPLY_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = Cs*Cd
SCREEN_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = Cs+Cd-Cs*Cd
OVERLAY_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
1-2*(1-Cs)*(1-Cd), otherwise
DARKEN_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = min(Cs,Cd)
LIGHTEN_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = max(Cs,Cd)
COLORDODGE_NV (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_NV (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_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
1-2*(1-Cs)*(1-Cd), otherwise
SOFTLIGHT_NV (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_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = abs(Cd-Cs)
EXCLUSION_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = Cs+Cd-2*Cs*Cd
INVERT (X,Y,Z) = (1,0,1)
f(Cs,Cd) = 1-Cd
INVERT_RGB_NV (X,Y,Z) = (1,0,1)
f(Cs,Cd) = Cs*(1-Cd)
LINEARDODGE_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) =
Cs+Cd, if Cs+Cd<=1
1, otherwise
LINEARBURN_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) =
Cs+Cd-1, if Cs+Cd>1
0, otherwise
VIVIDLIGHT_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) =
1-min(1,(1-Cd)/(2*Cs)), if 0 < Cs < 0.5
0, if Cs <= 0
min(1,Cd/(2*(1-Cs))), if 0.5 <= Cs < 1
1, if Cs >= 1
LINEARLIGHT_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) =
1, if 2*Cs+Cd>2
2*Cs+Cd-1, if 1 < 2*Cs+Cd <= 2
0, if 2*Cs+Cd<=1
PINLIGHT_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) =
0, if 2*Cs-1>Cd and Cs<0.5
2*Cs-1, if 2*Cs-1>Cd and Cs>=0.5
2*Cs, if 2*Cs-1<=Cd and Cs<0.5*Cd
Cd, if 2*Cs-1<=Cd and Cs>=0.5*Cd
???
HARDMIX_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = 0, if Cs+Cd<1
1, otherwise
Table X.2, Advanced Blend Equations
When using one of the HSL blend equations in table X.3 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_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = SetLumSat(Cs,Cd,Cd);
HSL_SATURATION_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = SetLumSat(Cd,Cs,Cd);
HSL_COLOR_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = SetLum(Cs,Cd);
HSL_LUMINOSITY_NV (X,Y,Z) = (1,1,1)
f(Cs,Cd) = SetLum(Cd,Cs);
Table X.3, Hue-Saturation-Luminosity Advanced Blend Equations
When using one of the equations in table X.4 as the blend equation, the
source color used by these blending equations is interpreted according to
the BLEND_PREMULTIPLIED_SRC_NV blending parameter. The blending equations
below are evaluated where the RGB source and destination color components
are both considered to have been premultiplied by the corresponding A
component.
(Rs', Gs', Bs') =
(Rs, Gs, Bs), if BLEND_PREMULTIPLIED_SRC_NV is TRUE
(Rs*As, Gs*As, Bs*As), if BLEND_PREMULTIPLIED_SRC_NV is FALSE
Mode Result
-------------------- ----------------------------------------
PLUS_NV (R,G,B,A) = (Rs'+Rd, Gs'+Gd, Bs'+Bd,As'+Ad)
PLUS_CLAMPED_NV (R,G,B,A) =
(min(1,Rs'+Rd), min(1,Gs'+Gd),
min(1,Bs'+Bd), min(1,As+Ad))
PLUS_CLAMPED_ALPHA_NV (R,G,B,A) =
(min(min(1,As+Ad),Rs'+Rd),
min(min(1,As+Ad),Gs'+Gd),
min(min(1,As+Ad),Bs'+Bd), min(1,As+Ad))
PLUS_DARKER_NV (R,G,B,A) =
(max(0,min(1,As+Ad)-((As-Rs')+(Ad-Rd))),
max(0,min(1,As+Ad)-((As-Gs')+(Ad-Gd))),
max(0,min(1,As+Ad)-((As-Bs')+(Ad-Bd))),
min(1,As+Ad))
MINUS_NV (R,G,B,A) = (Rd-Rs', Gd-Gs', Bd-Bs', Ad-As)
MINUS_CLAMPED_NV (R,G,B,A) =
(max(0,Rd-Rs'), max(0,Gd-Gs'),
max(0,Bd-Bs'), max(0,Ad-As))
CONTRAST_NV (R,G,B,A) =
(Ad/2 + 2*(Rd-Ad/2)*(Rs'-As/2),
Ad/2 + 2*(Gd-Ad/2)*(Gs'-As/2),
Ad/2 + 2*(Bd-Ad/2)*(Bs'-As/2),
Ad)
INVERT_OVG_NV (R,G,B,A) =
(As*(1-Rd)+(1-As)*Rd,
As*(1-Gd)+(1-As)*Gd,
As*(1-Bd)+(1-As)*Bd,
As+Ad-As*Ad)
RED_NV (R,G,B,A) = (Rs', Gd, Bd, Ad)
GREEN_NV (R,G,B,A) = (Rd, Gs', Bd, Ad)
BLUE_NV (R,G,B,A) = (Rd, Gd, Bs', Ad)
Table X.4, Additional RGB 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.2, X.3, or X.4, the error
INVALID_OPERATION is generated by [[Compatibility Profile: Begin or any
operation that implicitly calls Begin (such as DrawElements)]] [[Core
Profile: 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 NV_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 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 BlendBarrierNV(void);
specifies a boundary between passes when using advanced blend equations.
Any command that causes the value of a sample to be modified is considered
to touch the sample, including clears, blended or unblended primitives,
BlitFramebuffer copies, and direct updates by commands such as
TexSubImage2D.
[[ The following paragraph applies to NV_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_NV.
If coherent blending is disabled, applications should split their
rendering into a collection of blending passes, none of which touch an
individual sample 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 BlendBarrierNV(void);
specifies a boundary between passes when using advanced blend equations.
Any command that causes the value of a sample to be modified is considered
to touch the sample, including clears, blended or unblended primitives,
BlitFramebuffer copies, and direct updates by commands such as
TexSubImage2D.
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.
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 BlendBarrierNV()
command for both extensions:
[[ For NV_blend_equation_advanced only: ]]
The commands CoverFillPathNV, CoverFillPathInstancedNV,
CoverStrokePathNV, and CoverStrokePathInstancedNV are considered to
start a new blending pass, as though BlendBarrierNV 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 BlendBarrierNV after the cover
primitives to ensure defined blending results.
[[ For NV_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.2, X.3,
or X.4, 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.
If BlendParameteriNV is called and <pname> is not
BLEND_PREMULTIPLIED_SRC_NV or BLEND_OVERLAP_NV the error INVALID_ENUM is
generated.
If BlendParameteriNV is called with <pname> set to
BLEND_PREMULTIPLIED_SRC_NV the error INVALID_ENUM is generated if <param>
is not TRUE or FALSE.
If BlendParameteriNV is called with <pname> set to BLEND_OVERLAP_NV the
error INVALID_ENUM is generated if <param> is not one of UNCORRELATED_NV,
DISJOINT_NV, or CONJOINT_NV.
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_NV equations guaranteed to
be evaluated coherently?
BLEND_PREMULTIPLIED_ B GetBooleanv TRUE use premultiplied src 4.1.8 color-buffer
SRC_NV colors with advanced
blend equations
BLEND_OVERLAP_NV Z3 GetIntegerv UNCORRELATED correlation of src/dst 4.1.8 color-buffer
_NV coverage within a pixel
Note: The BLEND_ADVANCED_COHERENT_NV enable is provided if and only if
the NV_blend_equation_advanced_coherent extension is supported. On
implementations supporting only NV_blend_equation_advanced, this enable is
considered not to exist.
New Implementation Dependent State
None.
NVIDIA Implementation Details
Older versions of this extension specification and early shipping
implementations supported the COLORDODGE_NV and COLORBURN_NV equations
without the special case discussed in issue (34). This should be fixed for
newer driver releases.
Issues
(1) How should these new blending operations be supported?
RESOLVED: Provide a separate blend equation for each of the various
blending operations.
(2) Many of these blending operations involve complicated computations on
the RGB color components, but corresponding alpha operations are
typically very simple. How should blending on the alpha channel work?
RESOLVED: Each new blend equation provides one equation for color and
another for alpha. In this extension, separate advanced blend equations
for color and alpha are not supported; BlendEquationSeparate does not
accept these enums.
This extension contemplated separate blend equations for RGB and alpha,
perhaps with only basic equations for alpha, but we chose to tie RGB and
alpha blending together for simplicity.
(3) Should we provide explicit support for premultiplied colors?
RESOLVED: Yes. Many of the imaging APIs supporting similar blend
equations use premultiplied colors, some exclusively. Additionally,
many equations are simpler to express and compute with premultiplied
colors.
In this extension, we choose to treat the destination colors and the
blend result as premultiplied. We considered providing a blend
parameter supporting non-premultiplied destinations, but chose to
support only premultiplied destinations for mathematical simplicity.
(4) Should we support blending where some, but not all, colors are
premultiplied? For example, there may be cases where the source
fragment colors are not premultiplied, but where the destination
colors are premultiplied.
RESOLVED: Yes, we will provide support for non-premultiplied fragment
colors (via a blending parameter), in which case the RGB color
components are multiplied by alpha prior to blending.
We considered requiring premultiplication in the fragment shader, but
opted to provide a fixed-function premultiply operation for cases where
it was inconvenient to modify the fragment shader to perform the
multiplication, or where no fragment shader is executed (e.g.,
fixed-function fragment processing, blits via the NV_draw_texture
extension).
(5) Should we support different types of correlation between source and
destination coverage in partially covered pixels? If so, how?
RESOLVED: We will provide a blend parameter allowing for multiple
versions of many blending equations based on the "correlation" between
source and destination coverage. For pixels with partial opacity, there
might be three different blend cases: (a) where the portions of the
pixel covered by the primitives are considered to have minimal overlap
(e.g., abutting primitives in a mesh), (b) where the portions of the
pixel covered by the primitives are considered to have maximal overlap
(e.g., overlapping geometry), (c) where the portions of the pixel
covered by the primitives are considered uncorrelated.
(6) Should we support swapping source and destination coverage in advanced
blends? If so, how?
RESOLVED: In the current version, we don't support fully general
swapping. We do provide several pairs of blend equations that are
equivalent, other than swapping source and destination colors. For
example, we provide complementary blend equations SRC_OVER_NV, where the
source color is considered to be "over" the destination, and
DST_OVER_NV, where the destination color is considered to be "over the
source. Having pairs of equations such as "SRC_OVER" and "DST_OVER"
seems to be common practice in various imaging APIs.
Alternately, we could provide a blend parameter that simply swaps source
and destination for arbitrary blend equations. In the example above, we
could provide a single blend equation OVER_NV, where the source color is
considered "over" when unswapped and the destination color is considered
"over" when swapped.
(7) Should we generalize the blending operation, replacing the notions of
"source" and "destination" colors with more generic "A" and "B"
parameters, which might be obtained from a variety of sources
(fragment color, one of <N> color attachment points, some additional
source of textures/images)?
RESOLVED: Not in this extension; the only blending operation we support
takes a fragment color (which could be obtained from an arbitrary
source, either through a fragment shader, fixed function fragment
processing, or an imaging API such as NV_draw_texture) and a destination
color, performs a blend, and stores the result in the buffer from which
the destination color was extracted.
(8) How should we expose the various combinations of blending modes?
RESOLVED: The base blending equation is specified by the same
BlendEquation() API supported for regular OpenGL blending. Additional
parameters (such as pre-multiplied source colors, overlap mode, source
destination swapping, input selection) can be specified via the
BlendParameteriNV() API.
We could provide for a "general" blend equation API specifying multiple
parameters at once, such as:
void BlendEquationGeneralNV(enum blend, enum overlap,
boolean swapSrcDst);
but that API would require applications to pass parameters that are
always the same (e.g., overlap as UNCORRELATED_NV) and wouldn't be
easily extensible. Note that there are several features that we've
chosen not to include but might be usefully added as blend parameters in
the future -- see issues (3), (6), and (7), for example.
(9) What limitations apply to the new blend modes?
RESOLVED: In the current implementation, these blend equations are not
supported with more than one color buffer; if this is attempted, a
draw-time error is generated. This limitation is similar in nature to
one for dual-source blending, which implementations are not required to
support in conjunction with multiple color buffers. This limitation may
be relaxed in a future version of this extension.
(10) What precision is used in the computations for these blending
equations?
RESOLVED: There are no minimum precision requirements specified in
OpenGL 4.1, though one would expect implementations to blend with at
least the precision used to store destination color components. This
extension provides this as a minimum baseline for existing blending
equations.
For the new equations, we specify a minimum precision that is the
smaller of the precision of the destination buffer or the precision of
16-bit floating-point computations. For most formats, this meets the
limit for basic blend equations. However, there may be precision loss
if these new blending equations are used with 12-bit unsigned normalized
components, 16-bit unsigned or signed normalized components, or 32-bit
floating-point components.
This restriction is specified so that implementations are not required
to support the large number of blending equations specified here with
full 32-bit floating-point computations.
(11) When targeting a fixed-point buffer, are input color components
clamped to [-1,1] for signed normalized color buffers or to [0,1] for
unsigned normalized color buffers?
RESOLVED: We will use the same clamping behavior as for basic blend
equations, where fragment color components are clamped to [0,1] prior to
blending for unsigned normalized color targets.
Note that the OpenGL 4.1 specification, against which this spec is
written, had an oversight related signed normalized color buffers. It
specifies [0,1] clamping for all "fixed point" targets, which is clearly
not desired for signed normalized color buffers. Fragment shader color
outputs should be clamped to [-1,+1] in this case; this was fixed in
OpenGL 4.2 (bug 6849).
(12) 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.
(13) Should we provide "advanced" RGB blend equations for modes commonly
used in dedicated imaging APIs that can already be expressed with
current OpenGL blending modes?
RESOLVED: Yes; we will provide a number of "advanced" blend equations
for basic computations that can be done with existing blend equations.
This allows applications wanting to use these advanced modes to use them
exclusively, without having to figure out which blends are not supported
and generate separate BlendEquation/BlendFunc state for each.
(14) How do the advanced RGB blend equations interact with sRGB color
buffers? In particular, how does it interact with storing
premultiplied color values in the framebuffer?
RESOLVED: When targeting an sRGB color buffer with the blend equations
in this extension, we will convert the destination colors from sRGB to
linear and will convert the linear blend result back to sRGB when
writing it to the framebuffer. This approach is no different from
regular blends.
sRGB conversions will affect premultiplied colors differently than
non-premultiplied colors since:
linear_to_srgb(C*A) != A * linear_to_srgb(C)
When storing an sRGB-encoded value into an sRGB texture or renderbuffer,
we expect that the values will be extracted as sRGB colors in a
subsequent texturing, blending, or display operation. The fetched sRGB
color components will be converted back to linear. Except from rounding
errors in converting the color components to fixed-point, converting to
and from sRGB will not modify the color, with or without
premultiplication.
(15) The HSL blend equations are "color surgery" operations where
components from the source and destination colors are mixed. Are
there any problems using these equations with premultiplied color
components?
RESOLVED: Like all of the "f/X/Y/Z" blends, the function f() in HSL
blend equations are expressed in terms of non-premultiplied colors,
which implies a division operation prior to evaluating f(). However, it
may be possible to perform some or all of the blending operation using
pre-multiplied colors directly. In particular, the luminosity and
saturation of a color with components scaled by alpha is equal to alpha
times the luminosity or saturation of the un-scaled color:
lumv3(C*A) = A * lumv3(C)
satv3(C*A) = A * satv3(C)
(16) How should we express the blending equations?
RESOLVED: In general, we will use the formulation found in the PDF and
SVG specifications, which define each blend in terms of four parameters:
* a function f(Cs,Cd) specifies the blended color contribution in the
portion of the pixel containing both the source and destination;
* a constant X specifies whether the region containing both the source
and destination contributes to the final alpha;
* a constant Y specifies whether the region containing only the source
contributes to the final color and alpha; and
* a constant Z specifies whether the region containing only the
destination contributes to the final color and alpha.
This formulation is relatively compact and nicely illustrates the
contributions from the three relevant combinations of source and
destination coverage; the portion of the pixel covered by neither the
source nor the destination contributes nothing to color or alpha.
Additionally, we specify three functions p0(As,Ad), p1(As,Ad), and
p2(As,Ad) specifying the relative portion of the pixel covered by both
the source and destination, just the source, and just the destination,
respectively. These functions are defined according to the overlap
blend parameter; the most common mode (UNCORRELATED) defines:
p0(As,Ad) = As*Ad
p1(As,Ad) = As*(1-Ad)
p2(As,Ad) = Ad*(1-As)
There are certain special-purpose blending equations that don't fit
this general model (modes that mix RGB or HSL components from the
source and destination). These blends don't fit nicely into the
mathematical formulas above and are instead defined separately as a
component-by-component operation.
(17) How should we express the equations for the HSL blend equations?
RESOLVED: The equations used by this specification are loosely adapted
from similar code in the version 1.7 of the PDF (Portable Document
Format) specification. The equations have been modified to use
GLSL-style "vec3" syntax. Additionally, they use vector math in the
pseudocode overriding the saturation of a base color instead of using
"C_min", "C_mid", and "C_max" syntax effectively defining references to
the three components of the base color.
Alternately, we could have specified functions for converting (R,G,B)
colors to and from an (H,S,L) color space. But we decided not to do
that because actual (H,S,L) colors are never used in the pipeline.
(18) What issues apply to the PLUS and MINUS equations?
RESOLVED: The PLUS and MINUS equations provide arithmetically simple
operations; we simply perform a component-wise add or subtract
operations. The most interesting question is how and where clamping is
performed. The original Porter-Duff compositing specification provided
a "plus" equation intended to support blending between two images,
effectively performing:
weight * image1 + (1-weight) * image2
If the components of <image1>, <image2>, and <weight> are all in [0,1],
there is no need for clamping. However, in a general add with no
<weight> built in, there is no guarantee that adding components of two
images will remain inside the range [0,1]. When using fixed-point
unsigned normalized color buffers, the sum will automatically be clamped
to [0,1] when stored in the framebuffer. However, there may be cases
with floating-point color buffers where not clamping the sum also makes
sense.
Additionally, when storing premultiplied colors, it may also be
desirable to clamp R/G/B components to the range [0,A]. Premultiplied
colors effectively store "R*A" in the R channel, where "R" is the
non-premultiplied color and A is alpha. Clamping this value to A
ensures that the non-premultiplied form of R is in [0,1].
To handle all possible cases, we provide five "PLUS" and "MINUS"
equations.
PLUS_NV: Add color and alpha components without clamping.
PLUS_CLAMPED_NV: Add color and alpha components; clamp each sum to
1.0.
PLUS_CLAMPED_ALPHA_NV: Add color and alpha components. Clamp the
alpha sum to 1.0; clamp the color sums to the alpha result (i.e., the
clamped alpha sum). Note that if premultiplied inputs are clamped
properly where 0<=R,G,B<=A, this equation isn't needed since the color
sums will always be less than the alpha sum.
MINUS_NV: Subtract the source color and alpha components from the
destination without clamping.
MINUS_CLAMPED_NV: Subtract the source color and alpha components from
the destination; clamp the difference to 0.0.
We don't bother clamping in "unexpected" direction. We don't bother
clamping sums to be greater than or equal to zero or differences to be
less than or equal to one; either case would require an unclamped input
with a negative component.
Note that when blending to an unsigned fixed-point buffer, the clamped
and non-clamped versions of "PLUS" and "MINUS" produce the same results,
since inputs and outputs are both clamped to [0,1].
Note that the LINEARDODGE_NV equation is another form of "PLUS"; in the
area of intersection, the source and destination colors are added and
clamped to 1.0.
(19) Should we provide a blend parameter to clamp the destination color
(when read) to [0,1]? What about clamping premultiplied RGB
components to [0,a]?
RESOLVED: No. We expect the most common use case to involve unsigned
normalized color buffers, where components will automatically be clamped
to [0,1] by virtue of how they're stored in the framebuffer. It doesn't
seem worth the trouble to add a clamp-on-read feature to clamp to [0,a]
when it seems easy enough to program colors to stay in range.
(20) Should we provide a blend parameter to clamp final color or alpha
output components to [0,1]? What about clamping premultiplied RGB
outputs to [0,a]?
RESOLVED: As above, when writing the blend results to unsigned
normalized targets, output components will automatically be clamped to
[0,1] by virtue of how they're stored in the framebuffer. It doesn't
seem worth the trouble to clamp to [0,a], either. Most of the blend
equations supported by this extension will produce outputs with
premultiplied color component values in the range [0,a] as long as the
inputs also have that property. One exception is PLUS_NV, but we
explicitly provide a PLUS_CLAMPED_ALPHA_NV equation to for that case.
(21) Should we provide an equation like the VG_BLEND_SOFTLIGHT_SVG_KHR
blending equation in the KHR_advanced_blending extension to OpenVG?
RESOLVED: No. The KHR_advanced_blending appears to have specified a
equation implementing the "soft-light" compositing property in a working
draft of a SVG 1.2 specification, as described here:
http://www.w3.org/TR/2004/WD-SVG12-20041027/
rendering.html#compositing
This version of the specification appears to have been abandoned. The
equations for the "soft-light" property in the SVG Compositing
Specification at:
http://www.w3.org/TR/SVGCompositing/
match the SOFTLIGHT_NV equation provided by this extension and
VG_BLEND_SOFTLIGHT_KHR (no "SVG") in KHR_advanced_blending.
Additionally, the equations in the SVG 1.2 draft and the
KHR_advanced_blending extension both appear to contain clear errors in
the first and second cases. Both begin with "(cd*(as-(1-cd/ad)*..." in
the KHR spec but should be "(cd*(as+(1-cd/ad)*...". Both of these sign
errors are corrected in the "SVG" functions in this extension. With the
errors, there is a local minimum at Cs=0.5 (where we switch from the
first form to the second or third) and the function has a major
discontinuity at Cd=0.125 when Cs>0.5 (where we switch from the second
form to the third). For example, when Cs=0.8 and Cd=0.125, the second
form of the KHR extension would generate a result of -0.00625 and the
third form would generate a result of ~0.26213. Note that the corrected
equations still aren't continuous at Cd=0.125; the fixed second and
third forms generate 0.25625 and 0.26213, respectively, when Cs=0.8 and
Cd=0.125.
(22) What issues apply to the INVERT and INVERT_OVG_NV equations?
RESOLVED: The INVERT and INVERT_OVG_NV equations were included to
provide functionality similar to the same VG_BLEND_INVERT_KHR blend
equation provided by the KHR_advanced_blending extension to OpenVG and
similar equations in a few other compositing APIs/standards.
Unfortunately, the equation specified by the KHR extension has issues.
The apparent intent of this blend equation is to use the source alpha to
blend between the destination color and an inverted form of the
destination color. This description conceptually matches the
description in the KHR extension:
(1 - asrc) * c'dst + asrc * (1 - c'dst)
However, since source and destination colors are premultiplied, the
expression "1-c'dst" doesn't correctly invert the destination color. To
invert a premultiplied destination color, "adst-c'dst" should be used.
For example, if the premultiplied destination color is 50% gray and 50%
opaque (adst=0.5), the RGBA destination color will be
(0.25,0.25,0.25,0.5). Inverting the color components via "1-c'dst"
would yield RGB component values of 0.75, which isn't consistent with an
alpha of 0.5. Inverting via "adst-c'dst" would yield correct RGB
component values of 0.25.
Additionally, the alpha computed for this equation in the KHR extension
is the standard "asrc+adst*(1-asrc)", equivalent to X=Y=Z=1 in our
normal formulation. However, given that the source color doesn't
contribute at all, having "Y=1" doesn't make a whole lot of sense. The
INVERT equation used in this extension uses X=Z=1 and Y=0, which means
that blending with this equation never changes destination alpha.
We provide a separate blend equation INVERT_OVG_NV to provide
compatibility with the formulation in the KHR extension. The math in
the KHR extension does perform a "valid" blending operation -- it will
produce results that remain in [0,1] when inputs are in [0,1], and its
results are continuous. It can't be expressed directly via our f/X/Y/Z
parameterization, but it does match our general f/X/Y/Z model if you
consider all three areas to contribute where:
* the intersection area contributes the inverted destination color
* the destination-only area contributes the destination color
* the source-only area contributes full white
Note that INVERT and INVERT_OVG_NV equations are mathematically
equivalent when the destination is opaque (i.e., adst=1.0); in this
case, "1-c'dst" and "adst-c'dst" are equivalent. In our f/X/Y/Z model,
the full destination coverage means there is no "source-only" area in
this case.
(23) What issues apply to the PLUS_DARKER_NV blend equation?
RESOLVED: The PLUS_DARKER_NV equation corresponds to an equation
provided in the Quartz 2D API from Apple. The public documentation for
this equation specifies the color computed by this operation as:
R = MAX(0, 1 - ((1 - D) + (1 - S)))
This equation appears to want to invert the source and destination
colors, add the two inverted colors, and then invert the result.
However, this equation appears to assume opaque source and destination
colors. As noted in the discussion for INVERT_OVG_NV, inverting a color
via "1-C" doesn't make any sense. We've reformulated the equations to
use pre-multipled colors and invert with "A-C" in a manner similar to
that described in this email thread:
http://www.mail-archive.com/whatwg@lists.whatwg.org/msg06536.html
which appears to be the "darker" mode implemented in the Safari browser
(at least in 2007). Our formulation is equivalent to the one in the
Quartz 2D documentation when As=Ad=1.
(24) Should we apply the f/X/Y/Z formulation to blend equations where the
equations can be expressed this way only if one or more of X, Y, or
Z are neither zero nor one?
RESOLVED: No. The f/X/Y/Z model subdivides a pixel into four regions
based on the alpha of the source and the destination, three of which
(intersection, source only, destination only) either contribute or don't
contribute color and coverage based on the given blend equation. The
figure below depicts a pixel where the source and destination both have
coverage of 0.5 (50%). The picture assigns source coverage to the upper
left portion of the pixel and the destination coverage to the upper
right, and assumes an UNCORRELATED model. In this case, the pixel is
divided into four areas of equal size. The area of intersection is at
the top, and its color and coverage are controlled by the f() and X
parameters. The source-only and destination-only regions are on the
left and right, respectively, and color and coverage are both controlled
by the Y and Z parameters.
+-----------+
|\_ f/X _/|
source | \_ _/ | destination
(upper ==>| Y \_/ Z | (upper
left) | _/ \_ | <== right)
| _/ \_ |
|/ \|
+-----------+
The PLUS_NV equation could be expressed with f(Cs,Cd) = Cs+Cd, X=2, Y=1,
and Z=1. The X=2 term effectively has the source and destination *both*
contribute coverage in the area of intersection. The MINUS_NV equation
could be expressed with f(Cs,Cd) = Cd-Cs, X=1, Y=-1, and Z=1. The Y=-1
term effectively has the source-only portion of the pixel *remove*
coverage. Both of these don't match the physical model, and would yield
odd results when combined with conjoint or disjoint overlap modes.
(25) Should we provide more specialized versions of CONJOINT_NV and
DISJOINT_NV?
RESOLVED: Not in this extension. In the future, we could add new
overlap modes such as:
NON_INTERSECTING_NV: Like DISJOINT_NV, except that it assumes that
As+Ad<=1. This might be interesting when rendering polygons with
POLYGON_SMOOTH?
DST_INSIDE_NV, SRC_INSIDE_NV: Like CONJOINT_NV, except that it
assumes that the destination coverage is fully inside the source or
vice versa. For DST_INSIDE, the p0/p1/p2 terms would be Ad, As-Ad,
and 0, respectively.
For all three of these modes, the specialized versions would have
simpler and possibly more efficient math. We're not going to add any of
these modes in this extension, however.
(26) Should the blend equations have a common prefix (e.g.,
"BLEND_SRC_OVER") or just use forms without a prefix?
RESOLVED: Use forms without a prefix where the tokens are only used in
the context of blending (i.e., via the BlendEquation API). We will use
a "BLEND_" prefix to identify BlendParameter <pname> values because
those tokens can also be used in the general GetIntegerv API. Note that
in current OpenGL, some parameters have their own Get* API (e.g.,
TexParameter), while others use the general GetInteger queries (e.g.,
PointParameter).
(27) Should we use standard GL enums for the blend equations that already
have these names?
RESOLVED: Yes, to minimize the number of new enums. The primary risk
is that reusing standard enum definitions would be problematic if a
future core version wanted to use these parameters in the same place
with a different meaning. However, all such names are in common use in
various compositing standards and our semantics are consistent with
those standards.
(28) What other APIs support blend equations similar to the ones provided
here, and how does the feature set compare?
RESOLVED: Khronos' OpenVG 1.1 vector graphics library provides a
variety of basic blending equations, with additional modes provided by
the KHR_advanced_blending extension:
* http://www.khronos.org/registry/vg/specs/openvg-1.1.pdf
* http://www.khronos.org/registry/vg/extensions/KHR/advanced_blending.txt
The World Wide Web Consortium (W3C)'s Scalable Vector Graphics format
supports a variety of blending equations in its compositing
specification:
* http://www.w3.org/TR/SVGCompositing
W3C also has a CSS standard (Compositing and Blending Level 1):
* http://www.w3.org/TR/compositing-1/
Adobe's widely-used Portable Document Format (PDF) specification
provides numerous blending equations in its "Transparency" section:
* http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/
pdf_reference_1-7.pdf
Adobe's SWF (Flash) File Format Specification
* http://www.adobe.com/go/swfspec
Various "2D" graphics APIs, including Oracle's JavaFX, Apple's Quartz
2D, Qt's QPainter class, and X Window System's X Rendering Extension
also support a variety of blending equations:
* http://docs.oracle.com/javafx/2/api/javafx/scene/effect/BlendMode.html
* http://developer.apple.com/library/ios/#documentation/GraphicsImaging/
Reference/CGContext/Reference/reference.html
* http://doc.qt.digia.com/4.7/qpainter.html#composition-modes
* http://www.x.org/releases/current/doc/renderproto/renderproto.txt
The following table indicates the set of blend equations from this
extension that are supported in these various standards or APIs. "X"
indicates that the equation is supported. For OpenVG, "E" indicates
that the equation is supported by the KHR_advanced_blending extension.
"XO" that the indicates that the equation is supported with conjoint and
disjoint overlap modes; others support only the uncorrelated overlap
mode.
Blending Equation OVG SVG PDF SWF JFX Q2D QPT XRE
-------------------- ----- ----- ----- ----- ----- ----- ----- -----
ZERO E X - - - X X XO
SRC_NV X X - X - X X XO
DST_NV E X - - - - X XO
SRC_OVER_NV X X X X X X X XO
DST_OVER_NV X X - - - X X XO
SRC_IN_NV X X - - - X X XO
DST_IN_NV X X - X - X X XO
SRC_OUT_NV E X - - - X X XO
DST_OUT_NV E X - X - X X XO
SRC_ATOP_NV E X - - X X X XO
DST_ATOP_NV E X - - - X X XO
XOR_NV E X - - - X X XO
MULTIPLY_NV X X X X X X X X
SCREEN_NV X X X X X X X X
OVERLAY_NV E X X X X X X X
DARKEN_NV X X X X X X X X
LIGHTEN_NV X X X X X X X X
COLORDODGE_NV E X X - X X X X
COLORBURN_NV E X X - X X X X
HARDLIGHT_NV E X X X X X X X
SOFTLIGHT_NV E X X - X X X X
DIFFERENCE_NV E X X X X X X X
EXCLUSION_NV E X X - X X X X
INVERT - - - X - - - -
INVERT_RGB_NV - - - - - - - -
LINEARDODGE_NV E - - - - - - -
LINEARBURN_NV E - - - - - - -
VIVIDLIGHT_NV E - - - - - - -
LINEARLIGHT_NV E - - - - - - -
PINLIGHT_NV E - - - - - - -
HARDMIX_NV E - - - - - - -
HSL_HUE_NV - - X - - X - X
HSL_SATURATION_NV - - X - - X - X
HSL_COLOR_NV - - X - - X - X
HSL_LUMINOSITY_NV - - X - - X - X
PLUS_NV /
PLUS_CLAMPED_NV / X X - X X X X X
PLUS_CLAMPED_ALPHA_NV
PLUS_DARKER_NV - - - - - X - -
MINUS_NV / E - - X - - - -
MINUS_CLAMPED_NV
CONTRAST_NV - - - - - - - -
INVERT_OVG_NV E - - - - - - -
RED_NV - - - - X - - -
GREEN_NV - - - - X - - -
BLUE_NV - - - - X - - -
OpenGL COLOR_LOGIC_OP - - - - - - X -
(not in this extension)
Notes:
* The PLUS_NV, PLUS_CLAMPED_NV, and PLUS_CLAMPED_ALPHA_NV equations
are very similar and may be indistinguishable when the destination
buffer components are stored in normalized [0,1] numeric spaces, as
is the case in most of these standards. The MINUS_NV and
MINUS_CLAMPED_NV equations behave similarly.
* The SWF specification has a mode called "invert", but it's not clear
whether the mode is implemented using INVERT, INVERT_OVG_NV, or some
other equation.
(29) Should we provide an extension that can be supported on
implementations that may not provide fully coherent blending when
using the new equations? If so, how will this support be provided
and what limitations apply?
RESOLVED: Yes, this functionality is useful not just for general 3D
rendering, but also for 2D rendering operations (where the primitives
rendered may be less complex). As indicated in the issue above, the
blend equations provided by this extension are already very commonly
used in 2D rendering. Accelerating them on a wide range of GPUs, old
and new, would be very useful.
Older NVIDIA GPUs are able to support these blending equations as long
as rendering is split into distinct passes and no pixel is touched more
than once in any given pass. For such GPUs, we specify that the results
of blending are undefined if a single pixel (or sample) is touched more
than once in a pass, and provide the command BlendBarrierNV() to allow
applications to delimit boundaries between passes. As long as rendering
commands can be split into passes with barriers, advanced blending will
work "normally" even on these older GPUs.
Since there are two distinct levels of capability, we will advertise two
different extension string entries:
- GL_NV_blend_equation_advanced: Provides the new blending
functionality without support for full coherence (older GPUs).
- GL_NV_blend_equation_advanced_coherent: Provides the new blending
functionality with full coherence.
Since the functionality of these two extensions is nearly identical, we
document them in a single extension specification.
(30) On implementations that don't support fully coherent blending, should
we provide any convenience features so that "2D" applications aren't
required to manually sprinkle BlendBarrierNV() throughout the code?
RESOLVED: Yes. When using NV_blend_equation_advanced in conjunction
with NV_path_rendering commands like CoverFillPathNV and
CoverStrokePathNV, the driver will assist in ensuring coherent and
properly ordered blending by inserting implicit blend barriers before
rendering each cover primitive.
(31) When we generate fragments using the automatic coherence guarantees
from NV_path_rendering commands like CoverFillPathNV, what happens if
a pixel touched by CoverFillPathNV had already been touched by a
previous non-NVpr rendering command without an intervening call to
BlendBarrierNV? What happens if a pixel touched by CoverFillPathNV
is subsequently touched by a subsequent non-NVpr without an
intervening call to BlendBarrierNV?
RESOLVED: We specify that a blend barrier is inserted prior to each
cover primitives, so that cover primitives are blended coherently
relative to geometry from previous primitives (cover or otherwise). We
do not guarantee that a blend barrier is inserted after each cover
primitive, so applications need to call BlendBarrierNV manually if
subsequent non-cover primitives are rendered to the same set of pixels.
(32) On implementations supporting fully coherent blending, should we
provide some mode allowing implementations to opt out of coherent
blending?
RESOLVED: Yes. We will provide an enable allowing applications to
disable coherent blending in case where (a) implementations are able to
provide higher-performance implementations if they don't have to worry
about full coherence and/or ordering and (b) applications are willing to
use BlendBarrierNV() to take advantage of the higher-performance
implementation. The enable will be on by default, which means that
advanced blending on fully capable implementations will be "safe" unless
explicitly disabled.
(33) When fully coherent blending is disabled or not supported,
BlendBarrierNV() is used to indicate boundaries between passes.
Should any other commands in the OpenGL API also implicitly serve as
blend barriers?
RESOLVED: In general, no. Except for the NV_path_rendering case above,
we will require applications manually use BlendBarrierNV(). There may
be other operations that indirectly cause blend results to become
coherent (in an implementation-dependent way), but we don't attempt to
provide any explicit guarantees. Except for path rendering cover
primitives (see issues 30 and 31), applications should always call
BlendBarrierNV() between possibly overlapping passes.
Note that implementations of this extension may use texture mapping
hardware to source the framebuffer for blending and may end up caching
pre-blended texel values. This can cause subsequent texture fetches to
return stale values unless the texture is re-bound, the
TextureBarrierNV() command from the NV_texture_barrier extension is
used, or some other action is taken to break the "rendering feedback
loop". The existing spec already defines that texel fetches produce
undefined results when a texture object is bound both as a texture and
attached to the current draw framebuffer, with or without advanced blend
equations. See the "Rendering Feedback Loops" section (p. 316 in the
OpenGL 4.1 Compatibility Profile specification) for more information.
(34) How should the blend equations COLORDODGE_NV and COLORBURN_NV be
expressed mathematically?
RESOLVED: We 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_NV and
COLORBURN_NV equations that are found in newer compositing standard
specifications and in a number of implementations of old and new
standards. We believe that the omission of the special case in other
older specifications is a bug. We have no plans to add new blend
equation tokens to support "equivalent" modes without the new special
case.
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 this
extension was initially developed, all specifications we found that
specified blending equations mathematically (see issue 28) were written
the same way. Since then, we 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_NV, where some specifications
include a special case for Cb==0 while others do not. We have added a
special case there as well.
(35) 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
Rev. Date Author Changes
---- -------- -------- ----------------------------------------------
10 02/14/18 pdaniell 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 35 for the case where the
inputs to SetLum() are outside the range
[0..1] and could cause a divide-by-zero in
ClipColor().
9 09/30/14 pbrown Fix incorrectly specified color clamping in
the HSL blend modes.
8 02/26/14 pbrown For non-coherent blending, clarify that all
writes to a sample are considered to "touch"
that sample and require a BlendBarrierOES 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). Update issue (12) related to
ill-conditioned premultiplied colors.
7 11/06/13 pbrown 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".
6 10/21/13 pbrown Add NV-suffixed names for tokens reusing values
from core OpenGL enums (XOR, RED, GREEN, BLUE)
that are not in core OpenGL ES 2.0. This allows
code targeting both APIs to use the same
NV-suffixed #defines. Some older versions of
the OpenGL "glext.h" header will not have the
NV-suffixed names.
5 10/21/13 pbrown 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.
4 10/16/13 pbrown Modify the definition of COLORDODGE_NV and
COLORBURN_NV to match de facto standard
implemenations and new CSS/SVG compositing
spec; add issue (34).
3 08/19/13 pbrown Fix typos in the OpenGL ES 2.0 and 3.0
interactions sections.
2 07/25/13 mjk Add W3C CSS compositing reference.
1 pbrown Internal revisions.