The Framebuffer
Blending
Blending combines the incoming source fragment’s R, G, B, and A values with the destination R, G, B, and A values of each sample stored in the framebuffer at the fragment’s (xf,yf) location. Blending is performed for each color sample covered by the fragment, rather than just once for each fragment.
Source and destination values are combined according to the blend operation, quadruplets of source and destination weighting factors determined by the blend factors, and a blend constant, to obtain a new set of R, G, B, and A values, as described below.
Blending is computed and applied separately to each color attachment used by the subpass, with separate controls for each attachment.
Prior to performing the blend operation, signed and unsigned normalized fixed-point color components undergo an implied conversion to floating-point as specified by Conversion from Normalized Fixed-Point to Floating-Point. Blending computations are treated as if carried out in floating-point, and basic blend operations are performed with a precision and dynamic range no lower than that used to represent destination components. Advanced blending operations are 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.
Blending is only defined for floating-point, UNORM, SNORM, and sRGB formats.
Within those formats, the implementation may only support blending on some
subset of them.
Which formats support blending is indicated by
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
.
The pipeline blend state is included in the
VkPipelineColorBlendStateCreateInfo
structure during graphics pipeline
creation:
Blend Factors
Dual-Source Blending
Blend factors that use the secondary color input
(Rs1,Gs1,Bs1,As1) (VK_BLEND_FACTOR_SRC1_COLOR
,
VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
,
VK_BLEND_FACTOR_SRC1_ALPHA
, and
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
) may consume implementation
resources that could otherwise be used for rendering to multiple color
attachments.
Therefore, the number of color attachments that can be used in a
framebuffer may be lower when using dual-source blending.
Dual-source blending is only supported if the dualSrcBlend
feature is enabled.
The maximum number of color attachments that can be used in a subpass when
using dual-source blending functions is implementation-dependent and is
reported as the maxFragmentDualSrcAttachments
member of
VkPhysicalDeviceLimits
.
Color outputs can be bound to the first and second inputs of the blender
using the Index
decoration, as described in
Fragment Output Interface.
If the second color input to the blender is not written in the shader, or if
no output is bound to the second input of a blender, the value of the second
input is undefined:.
Blend Operations
If the numeric format of a framebuffer attachment
uses sRGB encoding, the R, G, and B destination color values (after
conversion from fixed-point to floating-point) are considered to be encoded
for the sRGB color space and hence are linearized prior to their use in
blending.
Each R, G, and B component is converted from nonlinear to linear as
described in the sRGB EOTF
section of the Khronos Data
Format Specification.
If the format is not sRGB, no linearization is performed.
If the numeric format of a framebuffer attachment uses sRGB encoding, then the final R, G and B values are converted into the nonlinear sRGB representation before being written to the framebuffer attachment as described in the sRGB EOTF -1 section of the Khronos Data Format Specification.
If the numeric format of a framebuffer color attachment is not sRGB encoded then the resulting cs values for R, G and B are unmodified. The value of A is never sRGB encoded. That is, the alpha component is always stored in memory as linear.
If the framebuffer color attachment is VK_ATTACHMENT_UNUSED
, no writes
are performed through that attachment.
Writes are not performed to framebuffer color attachments greater than or
equal to the VkSubpassDescription
::colorAttachmentCount
or VkSubpassDescription2
::colorAttachmentCount
value.
Advanced Blend Operations
The advanced blend operations are those listed in tables f/X/Y/Z Advanced Blend Operations, Hue-Saturation-Luminosity Advanced Blend Operations, and Additional RGB Blend Operations.
When using one of the operations in table f/X/Y/Z Advanced Blend Operations or Hue-Saturation-Luminosity Advanced Blend Operations, blending is performed according to the following equations:
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 srcPremultiplied
.
If srcPremultiplied
is set to VK_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:
If srcPremultiplied
is VK_FALSE
, the fragment color components
are used as the base color:
The R, G, and B components of the destination color used for blending are
derived according to dstPremultiplied
.
If dstPremultiplied
is set to VK_TRUE
, the destination
components are considered to have been premultiplied by the A component
prior to blending.
The base destination color (Rd',Gd',Bd') is obtained by dividing
through by the A component:
If dstPremultiplied
is VK_FALSE
, the destination color
components are used as the base color:
When blending using advanced blend operations, 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 is undefined:.
All of the advanced blend operation formulas in this chapter compute the
result as a premultiplied color.
If dstPremultiplied
is VK_FALSE
, that result color’s R, G, and B
components are divided by the A component before being written to the
framebuffer.
If any R, G, or B component of the color is non-zero and the A component is
zero, the result is considered ill-formed, and the corresponding component
of the blend result is undefined:.
If all components are zero, that value is unchanged.
If the A component of any input or result color is less than zero, the color is considered ill-formed, and all components of the blend result are undefined:.
Mode | Blend Coefficients |
---|---|
When using one of the HSL blend operations in table Hue-Saturation-Luminosity Advanced Blend Operations as the blend operation, 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 operation, and then converting the result back to RGB. 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 |
---|---|
When using one of the operations in table
Additional RGB Blend
Operations as the blend operation, the source and destination colors used
by these blending operations are interpreted according to
srcPremultiplied
and dstPremultiplied
.
The blending operations below are evaluated where the RGB source and
destination color components are both considered to have been premultiplied
by the corresponding A component.
Mode | Result |
---|---|
Logical Operations
The application can enable a logical operation between the fragment’s color values and the existing value in the framebuffer attachment. This logical operation is applied prior to updating the framebuffer attachment. Logical operations are applied only for signed and unsigned integer and normalized integer framebuffers. Logical operations are not applied to floating-point or sRGB format color attachments.