Jon Leech 57b7cd572d Change log for July 14, 2019 Vulkan 1.1.115 spec update:
* Update release number to 115.

GitHub issues:

  * Add valid usage statements to slink:VkWriteDescriptorSet and
    slink:VkCopyDescriptorSet specifying that updating immutable descriptors
    with ename:VK_DESCRIPTOR_TYPE_SAMPLER is invalid, and that updating
    ename:VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ignores the update's
    samplers (public issue 985).
  * Document that the `manhtmlpages` target requires building with all
    extensions enabled, in `BUILD.adoc` (public issue 992).
  * Fix reference to the wrong subpass in valid usage statement for
    slink:VkRenderPassCreateInfo (public pull request 994).

Internal Issues:

  * Rename slink:VkPhysicalDeviceShaderIntegerFunctions2INTEL and
    ename:VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS2_FEATURES_INTEL
    for consistency with global naming conventions, and to help code
    generation in other projects (internal issue 1685).
  * Update valid usage statements for image code:Offset / code:ConstOffset
    usage in the <<textures-gather, Texel Gathering>> and
    <<spirvenv-module-validation, Validation Rules within a Module>>
    sections, and for the <<limits-minTexelGatherOffset>> and
    <<limits-maxTexelGatherOffset>> limits (internal issue 1723).
  * Require code:code:OpGroupNonUniformBroadcast to take a constant `Id`
    operand in the <<spirvenv-module-validation, Validation Rules within a
    Module>> sections (internal issue 1726).
  * Note that the swapchain specified in slink:VkImageSwapchainCreateInfoKHR
    when creating an image must match the one specified in
    slink:VkBindImageMemorySwapchainInfoKHR when binding memory to the image
    (internal issue 1729).
  * Remove stext:KHR suffix from some structure cross-references that were
    promoted to Vulkan 1.1 (internal issue 1730).
  * Fix structure name in `structextends` attribute for
    slink:VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT in `vk.xml`
    (internal issue 1740).
  * Fix an error in the code:ClipColor() pseudocode for
    <<VK_EXT_blend_operation_advanced>> (internal issue 1741).
  * Add a row for
    ename:VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV to the
    description of elink:VkQueryType, and make a few related minor text
    cleanups.
  * Rename slink:VkPhysicalDeviceFloat16Int8FeaturesKHR to
    slink:VkPhysicalDeviceShaderFloat16Int8FeaturesKHR for consistency,
    retaining aliases of the old structure name and structure type enum for
    backwards compatibility.
2019-07-14 06:04:09 -07:00

804 lines
39 KiB
Plaintext

[[framebuffer-blend-advanced]]
=== Advanced Blend Operations
The _advanced blend operations_ are those listed in tables
<<framebuffer-blend-advanced-fxyz-modes,f/X/Y/Z Advanced Blend Operations>>,
<<framebuffer-blend-advanced-hsl-modes,Hue-Saturation-Luminosity Advanced
Blend Operations>>, and
<<framebuffer-blend-advanced-additional-rgb,Additional RGB Blend
Operations>>.
[open,refpage='VkPipelineColorBlendAdvancedStateCreateInfoEXT',desc='Structure specifying parameters that affect advanced blend operations',type='structs']
--
If the pname:pNext chain of slink:VkPipelineColorBlendStateCreateInfo
includes a sname:VkPipelineColorBlendAdvancedStateCreateInfoEXT structure,
then that structure includes parameters that affect advanced blend
operations.
The sname:VkPipelineColorBlendAdvancedStateCreateInfoEXT structure is
defined as:
include::{generated}/api/structs/VkPipelineColorBlendAdvancedStateCreateInfoEXT.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:srcPremultiplied specifies whether the source color of the blend
operation is treated as premultiplied.
* pname:dstPremultiplied specifies whether the destination color of the
blend operation is treated as premultiplied.
* pname:blendOverlap is a elink:VkBlendOverlapEXT value specifying how the
source and destination sample's coverage is correlated.
If this structure is not present, pname:srcPremultiplied and
pname:dstPremultiplied are both considered to be ename:VK_TRUE, and
pname:blendOverlap is considered to be
ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT.
.Valid Usage
****
* [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-srcPremultiplied-01424]]
If the <<limits-advancedBlendNonPremultipliedSrcColor,non-premultiplied
source color>> property is not supported, pname:srcPremultiplied must:
be ename:VK_TRUE
* [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-dstPremultiplied-01425]]
If the <<limits-advancedBlendNonPremultipliedDstColor,non-premultiplied
destination color>> property is not supported, pname:dstPremultiplied
must: be ename:VK_TRUE
* [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-blendOverlap-01426]]
If the <<limits-advancedBlendCorrelatedOverlap,correlated overlap>>
property is not supported, pname:blendOverlap must: be
ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT
****
include::{generated}/validity/structs/VkPipelineColorBlendAdvancedStateCreateInfoEXT.txt[]
--
When using one of the operations in table
<<framebuffer-blend-advanced-fxyz-modes,f/X/Y/Z Advanced Blend Operations>>
or <<framebuffer-blend-advanced-hsl-modes,Hue-Saturation-Luminosity Advanced
Blend Operations>>, blending is performed according to the following
equations:
[latexmath]
+++++++++++++++++++
\begin{aligned}
R & = & f(R_s',R_d')*p_0(A_s,A_d) & + & Y*R_s'*p_1(A_s,A_d) & + & Z*R_d'*p_2(A_s,A_d) \\
G & = & f(G_s',G_d')*p_0(A_s,A_d) & + & Y*G_s'*p_1(A_s,A_d) & + & Z*G_d'*p_2(A_s,A_d) \\
B & = & f(B_s',B_d')*p_0(A_s,A_d) & + & Y*B_s'*p_1(A_s,A_d) & + & Z*B_d'*p_2(A_s,A_d) \\
A & = & X*p_0(A_s,A_d) & + & Y*p_1(A_s,A_d) & + & Z*p_2(A_s,A_d)
\end{aligned}
+++++++++++++++++++
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 pname:srcPremultiplied.
If pname:srcPremultiplied is set to ename:VK_TRUE, the fragment color
components are considered to have been premultiplied by the A component
prior to blending.
The base source color [eq]#(R~s~',G~s~',B~s~')# is obtained by dividing
through by the A component:
[latexmath]
+++++++++++++++++++
\begin{aligned}
(R_s', G_s', B_s') & =
\begin{cases}
(0, 0, 0) & A_s = 0 \\
(\frac{R_s}{A_s}, \frac{G_s}{A_s}, \frac{B_s}{A_s}) & \text{otherwise}
\end{cases}
\end{aligned}
+++++++++++++++++++
If pname:srcPremultiplied is ename:VK_FALSE, the fragment color components
are used as the base color:
[latexmath]
+++++++++++++++++++
\begin{aligned}
(R_s', G_s', B_s') & = (R_s, G_s, B_s)
\end{aligned}
+++++++++++++++++++
The R, G, and B components of the destination color used for blending are
derived according to pname:dstPremultiplied.
If pname:dstPremultiplied is set to ename:VK_TRUE, the destination
components are considered to have been premultiplied by the A component
prior to blending.
The base destination color [eq]#(R~d~',G~d~',B~d~')# is obtained by dividing
through by the A component:
[latexmath]
+++++++++++++++++++
\begin{aligned}
(R_d', G_d', B_d') & =
\begin{cases}
(0, 0, 0) & A_d = 0 \\
(\frac{R_d}{A_d}, \frac{G_d}{A_d}, \frac{B_d}{A_d}) & \text{otherwise}
\end{cases}
\end{aligned}
+++++++++++++++++++
If pname:dstPremultiplied is ename:VK_FALSE, the destination color
components are used as the base color:
[latexmath]
+++++++++++++++++++
\begin{aligned}
(R_d', G_d', B_d') & = (R_d, G_d, B_d)
\end{aligned}
+++++++++++++++++++
[open,refpage='VkBlendOverlapEXT',desc='Enumerant specifying the blend overlap parameter',type='enums']
--
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:.
The weighting functions [eq]#p~0~#, [eq]#p~1~#, and [eq]#p~2~# are defined
in table <<framebuffer-blend-advanced-overlap-modes,Advanced Blend Overlap
Modes>>.
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 [eq]#p~0~#, [eq]#p~1~#, and [eq]#p~2~# 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.
Possible values of
slink:VkPipelineColorBlendAdvancedStateCreateInfoEXT::pname:blendOverlap,
specifying the blend overlap functions, are:
include::{generated}/api/enums/VkBlendOverlapEXT.txt[]
* ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT specifies that there is no
correlation between the source and destination coverage.
* ename:VK_BLEND_OVERLAP_CONJOINT_EXT specifies that the source and
destination coverage are considered to have maximal overlap.
* ename:VK_BLEND_OVERLAP_DISJOINT_EXT specifies that the source and
destination coverage are considered to have minimal overlap.
[[framebuffer-blend-advanced-overlap-modes]]
.Advanced Blend Overlap Modes
[width="80%",options="header"]
|====
| Overlap Mode | Weighting Equations
| ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
p_0(A_s,A_d) & = A_sA_d \\
p_1(A_s,A_d) & = A_s(1-A_d) \\
p_2(A_s,A_d) & = A_d(1-A_s) \\
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OVERLAP_CONJOINT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
p_0(A_s,A_d) & = min(A_s,A_d) \\
p_1(A_s,A_d) & = max(A_s-A_d,0) \\
p_2(A_s,A_d) & = max(A_d-A_s,0) \\
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OVERLAP_DISJOINT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
p_0(A_s,A_d) & = max(A_s+A_d-1,0) \\
p_1(A_s,A_d) & = min(A_s,1-A_d) \\
p_2(A_s,A_d) & = min(A_d,1-A_s) \\
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|====
--
[[framebuffer-blend-advanced-fxyz-modes]]
.f/X/Y/Z Advanced Blend Operations
[width="80%",options="header"]
|====
| Mode | Blend Coefficients
| ename:VK_BLEND_OP_ZERO_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (0,0,0) \\
f(C_s,C_d) & = 0
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SRC_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,0) \\
f(C_s,C_d) & = C_s
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DST_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,1) \\
f(C_s,C_d) & = C_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SRC_OVER_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = C_s
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DST_OVER_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = C_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SRC_IN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,0) \\
f(C_s,C_d) & = C_s
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DST_IN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,0) \\
f(C_s,C_d) & = C_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SRC_OUT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (0,1,0) \\
f(C_s,C_d) & = 0
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DST_OUT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (0,0,1) \\
f(C_s,C_d) & = 0
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SRC_ATOP_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,1) \\
f(C_s,C_d) & = C_s
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DST_ATOP_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,0) \\
f(C_s,C_d) & = C_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_XOR_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (0,1,1) \\
f(C_s,C_d) & = 0
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_MULTIPLY_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = C_sC_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SCREEN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = C_s+C_d-C_sC_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_OVERLAY_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
2 C_sC_d & C_d \leq 0.5 \\
1-2 (1-C_s)(1-C_d) & \text{otherwise}
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DARKEN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = min(C_s,C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_LIGHTEN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = max(C_s,C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_COLORDODGE_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
0 & C_d \leq 0 \\
min(1,\frac{C_d}{1-C_s}) & C_d \gt 0 \text{ and } C_s \lt 1 \\
1 & C_d \gt 0 \text{ and } C_s \geq 1
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_COLORBURN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
1 & C_d \geq 1 \\
1 - min(1,\frac{1-C_d}{C_s}) & C_d \lt 1 \text{ and } C_s \gt 0 \\
0 & C_d \lt 1 \text{ and } C_s \leq 0
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_HARDLIGHT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
2 C_sC_d & C_s \leq 0.5 \\
1-2 (1-C_s)(1-C_d) & \text{otherwise}
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_SOFTLIGHT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
C_d-(1-2 C_s)C_d(1-C_d) & C_s \leq 0.5 \\
C_d+(2 C_s-1)C_d((16 C_d-12)C_d+3) & C_s \gt 0.5 \text{ and } C_d \leq 0.25 \\
C_d+(2 C_s-1)(\sqrt{C_d}-C_d) & C_s \gt 0.5 \text{ and } C_d \gt 0.25
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_DIFFERENCE_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = \lvert C_d-C_s \rvert
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_EXCLUSION_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = C_s+C_d-2C_sC_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_INVERT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,1) \\
f(C_s,C_d) & = 1-C_d
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_INVERT_RGB_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,0,1) \\
f(C_s,C_d) & = C_s(1-C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_LINEARDODGE_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
C_s+C_d & C_s+C_d \leq 1 \\
1 & \text{otherwise}
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_LINEARBURN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
C_s+C_d-1 & C_s+C_d \gt 1 \\
0 & \text{otherwise}
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_VIVIDLIGHT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
1-min(1,\frac{1-C_d}{2C_s}) & 0 \lt C_s \lt 0.5 \\
0 & C_s \leq 0 \\
min(1,\frac{C_d}{2(1-C_s)}) & 0.5 \leq C_s \lt 1 \\
1 & C_s \geq 1
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_LINEARLIGHT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
1 & 2C_s+C_d \gt 2 \\
2C_s+C_d-1 & 1 \lt 2C_s+C_d \leq 2 \\
0 & 2C_s+C_d \leq 1
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_PINLIGHT_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
0 & 2C_s-1 \gt C_d \text{ and } C_s \lt 0.5 \\
2C_s-1 & 2C_s-1 \gt C_d \text{ and } C_s \geq 0.5 \\
2C_s & 2C_s-1 \leq C_d \text{ and } C_s \lt 0.5C_d \\
C_d & 2C_s-1 \leq C_d \text{ and } C_s \geq 0.5C_d
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_HARDMIX_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & =
\begin{cases}
0 & C_s+C_d \lt 1 \\
1 & \text{otherwise}
\end{cases}
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|====
When using one of the HSL blend operations in table
<<framebuffer-blend-advanced-hsl-modes,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:
[source,c++]
----------------------------------------
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);
}
----------------------------------------
[[framebuffer-blend-advanced-hsl-modes]]
.Hue-Saturation-Luminosity Advanced Blend Operations
[width="80%",options="header"]
|====
| Mode | Result
| ename:VK_BLEND_OP_HSL_HUE_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = SetLumSat(C_s,C_d,C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_HSL_SATURATION_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = SetLumSat(C_d,C_s,C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_HSL_COLOR_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = SetLum(C_s,C_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_HSL_LUMINOSITY_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(X,Y,Z) & = (1,1,1) \\
f(C_s,C_d) & = SetLum(C_d,C_s)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|====
When using one of the operations in table
<<framebuffer-blend-advanced-additional-rgb,Additional RGB Blend
Operations>> as the blend operation, the source and destination colors used
by these blending operations are interpreted according to
pname:srcPremultiplied and pname: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.
[latexmath]
+++++++++++++++++++
\begin{aligned}
(R_s', G_s', B_s') & =
\begin{cases}
(R_s, G_s, B_s) & \text{if srcPremultiplied is VK\_TRUE} \\
(R_sA_s, G_sA_s, B_sA_s) & \text{if srcPremultiplied is VK\_FALSE}
\end{cases} \\
(R_d', G_d', B_d') & =
\begin{cases}
(R_d, G_d, B_d) & \text{if dstPremultiplied is VK\_TRUE} \\
(R_dA_d, G_dA_d, B_dA_d) & \text{if dstPremultiplied is VK\_FALSE}
\end{cases}
\end{aligned}
+++++++++++++++++++
[[framebuffer-blend-advanced-additional-rgb]]
.Additional RGB Blend Operations
[width="80%",options="header"]
|====
| Mode | Result
| ename:VK_BLEND_OP_PLUS_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & R_s'+R_d', \\
& G_s'+G_d', \\
& B_s'+B_d', \\
& A_s+A_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_PLUS_CLAMPED_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & min(1,R_s'+R_d'), \\
& min(1,G_s'+G_d'), \\
& min(1,B_s'+B_d'), \\
& min(1,A_s+A_d))
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & min(min(1,A_s+A_d),R_s'+R_d'), \\
& min(min(1,A_s+A_d),G_s'+G_d'), \\
& min(min(1,A_s+A_d),B_s'+B_d'), \\
& min(1,A_s+A_d))
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_PLUS_DARKER_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & max(0,min(1,A_s+A_d)-((A_s-R_s')+(A_d-R_d'))), \\
& max(0,min(1,A_s+A_d)-((A_s-G_s')+(A_d-G_d'))), \\
& max(0,min(1,A_s+A_d)-((A_s-B_s')+(A_d-B_d'))), \\
& min(1,A_s+A_d))
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_MINUS_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & R_d'-R_s', \\
& G_d'-G_s', \\
& B_d'-B_s', \\
& A_d-A_s)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_MINUS_CLAMPED_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & max(0,R_d'-R_s'), \\
& max(0,G_d'-G_s'), \\
& max(0,B_d'-B_s'), \\
& max(0,A_d-A_s))
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_CONTRAST_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & \frac{A_d}{2} + 2(R_d'-\frac{A_d}{2})(R_s'-\frac{A_s}{2}), \\
& \frac{A_d}{2} + 2(G_d'-\frac{A_d}{2})(G_s'-\frac{A_s}{2}), \\
& \frac{A_d}{2} + 2(B_d'-\frac{A_d}{2})(B_s'-\frac{A_s}{2}), \\
& A_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_INVERT_OVG_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) = ( & A_s(1-R_d') + (1-A_s)R_d', \\
& A_s(1-G_d') + (1-A_s)G_d', \\
& A_s(1-B_d') + (1-A_s)B_d', \\
& A_s+A_d-A_sA_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_RED_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) & = (R_s', G_d', B_d', A_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_GREEN_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) & = (R_d', G_s', B_d', A_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| ename:VK_BLEND_OP_BLUE_EXT a|
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\begin{aligned}
(R,G,B,A) & = (R_d', G_d', B_s', A_d)
\end{aligned}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|====