806 lines
39 KiB
Plaintext
806 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::../../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
|
|
<<features-limits-advancedBlendNonPremultipliedSrcColor,non-premultiplied
|
|
source color>> property is not supported, pname:srcPremultiplied must:
|
|
be ename:VK_TRUE
|
|
* [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-dstPremultiplied-01425]]
|
|
If the
|
|
<<features-limits-advancedBlendNonPremultipliedDstColor,non-premultiplied
|
|
destination color>> property is not supported, pname:dstPremultiplied
|
|
must: be ename:VK_TRUE
|
|
* [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-blendOverlap-01426]]
|
|
If the <<features-limits-advancedBlendCorrelatedOverlap,correlated
|
|
overlap>> property is not supported, pname:blendOverlap must: be
|
|
ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT
|
|
****
|
|
|
|
include::../../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::../../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)*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}
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|====
|