| // Copyright 2018-2021 The Khronos Group, Inc. |
| // |
| // SPDX-License-Identifier: CC-BY-4.0 |
| |
| [[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 a structure extending this |
| 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} |
| +++++++++++++++++++ |
| |
| 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 pname:dstPremultiplied is ename: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:. |
| |
| [open,refpage='VkBlendOverlapEXT',desc='Enumerant specifying the blend overlap parameter',type='enums'] |
| -- |
| 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} |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |==== |