1// Copyright 2018-2023 The Khronos Group Inc. 2// 3// SPDX-License-Identifier: CC-BY-4.0 4 5[[framebuffer-blend-advanced]] 6=== Advanced Blend Operations 7 8The _advanced blend operations_ are those listed in tables 9<<framebuffer-blend-advanced-fxyz-modes,f/X/Y/Z Advanced Blend Operations>>, 10<<framebuffer-blend-advanced-hsl-modes,Hue-Saturation-Luminosity Advanced 11Blend Operations>>, and 12<<framebuffer-blend-advanced-additional-rgb,Additional RGB Blend 13Operations>>. 14 15[open,refpage='VkPipelineColorBlendAdvancedStateCreateInfoEXT',desc='Structure specifying parameters that affect advanced blend operations',type='structs'] 16-- 17If the pname:pNext chain of slink:VkPipelineColorBlendStateCreateInfo 18includes a sname:VkPipelineColorBlendAdvancedStateCreateInfoEXT structure, 19then that structure includes parameters that affect advanced blend 20operations. 21 22The sname:VkPipelineColorBlendAdvancedStateCreateInfoEXT structure is 23defined as: 24 25include::{generated}/api/structs/VkPipelineColorBlendAdvancedStateCreateInfoEXT.adoc[] 26 27 * pname:sType is a elink:VkStructureType value identifying this structure. 28 * pname:pNext is `NULL` or a pointer to a structure extending this 29 structure. 30 * pname:srcPremultiplied specifies whether the source color of the blend 31 operation is treated as premultiplied. 32 * pname:dstPremultiplied specifies whether the destination color of the 33 blend operation is treated as premultiplied. 34 * pname:blendOverlap is a elink:VkBlendOverlapEXT value specifying how the 35 source and destination sample's coverage is correlated. 36 37If this structure is not present, pname:srcPremultiplied and 38pname:dstPremultiplied are both considered to be ename:VK_TRUE, and 39pname:blendOverlap is considered to be 40ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT. 41 42.Valid Usage 43**** 44 * [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-srcPremultiplied-01424]] 45 If the <<limits-advancedBlendNonPremultipliedSrcColor, non-premultiplied 46 source color>> property is not supported, pname:srcPremultiplied must: 47 be ename:VK_TRUE 48 * [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-dstPremultiplied-01425]] 49 If the <<limits-advancedBlendNonPremultipliedDstColor, non-premultiplied 50 destination color>> property is not supported, pname:dstPremultiplied 51 must: be ename:VK_TRUE 52 * [[VUID-VkPipelineColorBlendAdvancedStateCreateInfoEXT-blendOverlap-01426]] 53 If the <<limits-advancedBlendCorrelatedOverlap, correlated overlap>> 54 property is not supported, pname:blendOverlap must: be 55 ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT 56**** 57 58include::{generated}/validity/structs/VkPipelineColorBlendAdvancedStateCreateInfoEXT.adoc[] 59-- 60 61ifdef::VK_EXT_extended_dynamic_state3,VK_EXT_shader_object[] 62[open,refpage='vkCmdSetColorBlendAdvancedEXT',desc='Specify the advanced color blend state dynamically for a command buffer',type='protos'] 63-- 64To <<pipelines-dynamic-state, dynamically set>> the advanced blend state, 65call: 66 67include::{generated}/api/protos/vkCmdSetColorBlendAdvancedEXT.adoc[] 68 69 * pname:commandBuffer is the command buffer into which the command will be 70 recorded. 71 * pname:firstAttachment the first color attachment the advanced blend 72 parameters apply to. 73 * pname:attachmentCount the number of slink:VkColorBlendAdvancedEXT 74 elements in the pname:pColorBlendAdvanced array. 75 * pname:pColorBlendAdvanced an array of slink:VkColorBlendAdvancedEXT 76 structs that specify the advanced color blend parameters for the 77 corresponding attachments. 78 79This command sets the advanced blend operation parameters of the specified 80attachments for subsequent drawing commands 81ifdef::VK_EXT_shader_object[] 82ifdef::VK_EXT_extended_dynamic_state3[when drawing using <<shaders-objects, shader objects>>, or] 83ifndef::VK_EXT_extended_dynamic_state3[when drawing using <<shaders-objects, shader objects>>.] 84endif::VK_EXT_shader_object[] 85ifdef::VK_EXT_extended_dynamic_state3[] 86when the graphics pipeline is created with 87ename:VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT set in 88slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates. 89endif::VK_EXT_extended_dynamic_state3[] 90Otherwise, this state is specified by the 91slink:VkPipelineColorBlendAdvancedStateCreateInfoEXT::pname:srcPremultiplied, 92slink:VkPipelineColorBlendAdvancedStateCreateInfoEXT::pname:dstPremultiplied, 93and slink:VkPipelineColorBlendAdvancedStateCreateInfoEXT::pname:blendOverlap 94values used to create the currently active pipeline. 95 96:refpage: vkCmdSetColorBlendAdvancedEXT 97:requiredfeature: extendedDynamicState3ColorBlendAdvanced 98 99.Valid Usage 100**** 101include::{chapters}/commonvalidity/dynamic_state3_feature_common.adoc[] 102**** 103 104include::{generated}/validity/protos/vkCmdSetColorBlendAdvancedEXT.adoc[] 105-- 106 107[open,refpage='VkColorBlendAdvancedEXT',desc='Structure specifying the advanced blend operation parameters for an attachment',type='structs'] 108-- 109The sname:VkColorBlendAdvancedEXT structure is defined as: 110 111include::{generated}/api/structs/VkColorBlendAdvancedEXT.adoc[] 112 113 * pname:advancedBlendOp selects which blend operation is used to calculate 114 the RGB values to write to the color attachment. 115 * pname:srcPremultiplied specifies whether the source color of the blend 116 operation is treated as premultiplied. 117 * pname:dstPremultiplied specifies whether the destination color of the 118 blend operation is treated as premultiplied. 119 * pname:blendOverlap is a elink:VkBlendOverlapEXT value specifying how the 120 source and destination sample's coverage is correlated. 121 * pname:clampResults specifies the results must be clamped to the [0,1] 122 range before writing to the attachment, which is useful when the 123 attachment format is not normalized fixed-point. 124 125.Valid Usage 126**** 127 * [[VUID-VkColorBlendAdvancedEXT-srcPremultiplied-07505]] 128 If the <<limits-advancedBlendNonPremultipliedSrcColor, non-premultiplied 129 source color>> property is not supported, pname:srcPremultiplied must: 130 be ename:VK_TRUE 131 * [[VUID-VkColorBlendAdvancedEXT-dstPremultiplied-07506]] 132 If the <<limits-advancedBlendNonPremultipliedDstColor, non-premultiplied 133 destination color>> property is not supported, pname:dstPremultiplied 134 must: be ename:VK_TRUE 135 * [[VUID-VkColorBlendAdvancedEXT-blendOverlap-07507]] 136 If the <<limits-advancedBlendCorrelatedOverlap, correlated overlap>> 137 property is not supported, pname:blendOverlap must: be 138 ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT 139**** 140 141include::{generated}/validity/structs/VkColorBlendAdvancedEXT.adoc[] 142-- 143endif::VK_EXT_extended_dynamic_state3,VK_EXT_shader_object[] 144 145When using one of the operations in table 146<<framebuffer-blend-advanced-fxyz-modes,f/X/Y/Z Advanced Blend Operations>> 147or <<framebuffer-blend-advanced-hsl-modes,Hue-Saturation-Luminosity Advanced 148Blend Operations>>, blending is performed according to the following 149equations: 150 151[latexmath] 152+++++++++++++++++++ 153\begin{aligned} 154 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) \\ 155 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) \\ 156 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) \\ 157 A & = & X*p_0(A_s,A_d) & + & Y*p_1(A_s,A_d) & + & Z*p_2(A_s,A_d) 158\end{aligned} 159+++++++++++++++++++ 160 161where the function f and terms X, Y, and Z are specified in the table. 162The R, G, and B components of the source color used for blending are derived 163according to pname:srcPremultiplied. 164If pname:srcPremultiplied is set to ename:VK_TRUE, the fragment color 165components are considered to have been premultiplied by the A component 166prior to blending. 167The base source color [eq]#(R~s~',G~s~',B~s~')# is obtained by dividing 168through by the A component: 169 170[latexmath] 171+++++++++++++++++++ 172\begin{aligned} 173 (R_s', G_s', B_s') & = 174 \begin{cases} 175 (0, 0, 0) & A_s = 0 \\ 176 (\frac{R_s}{A_s}, \frac{G_s}{A_s}, \frac{B_s}{A_s}) & \text{otherwise} 177 \end{cases} 178\end{aligned} 179+++++++++++++++++++ 180 181If pname:srcPremultiplied is ename:VK_FALSE, the fragment color components 182are used as the base color: 183 184[latexmath] 185+++++++++++++++++++ 186\begin{aligned} 187 (R_s', G_s', B_s') & = (R_s, G_s, B_s) 188\end{aligned} 189+++++++++++++++++++ 190 191The R, G, and B components of the destination color used for blending are 192derived according to pname:dstPremultiplied. 193If pname:dstPremultiplied is set to ename:VK_TRUE, the destination 194components are considered to have been premultiplied by the A component 195prior to blending. 196The base destination color [eq]#(R~d~',G~d~',B~d~')# is obtained by dividing 197through by the A component: 198 199[latexmath] 200+++++++++++++++++++ 201\begin{aligned} 202 (R_d', G_d', B_d') & = 203 \begin{cases} 204 (0, 0, 0) & A_d = 0 \\ 205 (\frac{R_d}{A_d}, \frac{G_d}{A_d}, \frac{B_d}{A_d}) & \text{otherwise} 206 \end{cases} 207\end{aligned} 208+++++++++++++++++++ 209 210If pname:dstPremultiplied is ename:VK_FALSE, the destination color 211components are used as the base color: 212 213[latexmath] 214+++++++++++++++++++ 215\begin{aligned} 216 (R_d', G_d', B_d') & = (R_d, G_d, B_d) 217\end{aligned} 218+++++++++++++++++++ 219 220When blending using advanced blend operations, we expect that the R, G, and 221B components of premultiplied source and destination color inputs be stored 222as the product of non-premultiplied R, G, and B component values and the A 223component of the color. 224If any R, G, or B component of a premultiplied input color is non-zero and 225the A component is zero, the color is considered ill-formed, and the 226corresponding component of the blend result is undefined:. 227 228All of the advanced blend operation formulas in this chapter compute the 229result as a premultiplied color. 230If pname:dstPremultiplied is ename:VK_FALSE, that result color's R, G, and B 231components are divided by the A component before being written to the 232framebuffer. 233If any R, G, or B component of the color is non-zero and the A component is 234zero, the result is considered ill-formed, and the corresponding component 235of the blend result is undefined:. 236If all components are zero, that value is unchanged. 237 238If the A component of any input or result color is less than zero, the color 239is considered ill-formed, and all components of the blend result are 240undefined:. 241 242[open,refpage='VkBlendOverlapEXT',desc='Enumerant specifying the blend overlap parameter',type='enums'] 243-- 244The weighting functions [eq]#p~0~#, [eq]#p~1~#, and [eq]#p~2~# are defined 245in table <<framebuffer-blend-advanced-overlap-modes,Advanced Blend Overlap 246Modes>>. 247In these functions, the A components of the source and destination colors 248are taken to indicate the portion of the pixel covered by the fragment 249(source) and the fragments previously accumulated in the pixel 250(destination). 251The functions [eq]#p~0~#, [eq]#p~1~#, and [eq]#p~2~# approximate the 252relative portion of the pixel covered by the intersection of the source and 253destination, covered only by the source, and covered only by the 254destination, respectively. 255 256Possible values of 257slink:VkPipelineColorBlendAdvancedStateCreateInfoEXT::pname:blendOverlap, 258specifying the blend overlap functions, are: 259 260include::{generated}/api/enums/VkBlendOverlapEXT.adoc[] 261 262 * ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT specifies that there is no 263 correlation between the source and destination coverage. 264 * ename:VK_BLEND_OVERLAP_CONJOINT_EXT specifies that the source and 265 destination coverage are considered to have maximal overlap. 266 * ename:VK_BLEND_OVERLAP_DISJOINT_EXT specifies that the source and 267 destination coverage are considered to have minimal overlap. 268 269[[framebuffer-blend-advanced-overlap-modes]] 270.Advanced Blend Overlap Modes 271[width="80%",options="header"] 272|==== 273| Overlap Mode | Weighting Equations 274| ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT a| 275[latexmath] 276++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 277 \begin{aligned} 278 p_0(A_s,A_d) & = A_sA_d \\ 279 p_1(A_s,A_d) & = A_s(1-A_d) \\ 280 p_2(A_s,A_d) & = A_d(1-A_s) \\ 281 \end{aligned} 282++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 283 284| ename:VK_BLEND_OVERLAP_CONJOINT_EXT a| 285[latexmath] 286++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 287 \begin{aligned} 288 p_0(A_s,A_d) & = min(A_s,A_d) \\ 289 p_1(A_s,A_d) & = max(A_s-A_d,0) \\ 290 p_2(A_s,A_d) & = max(A_d-A_s,0) \\ 291 \end{aligned} 292++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 293| ename:VK_BLEND_OVERLAP_DISJOINT_EXT a| 294[latexmath] 295++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 296 \begin{aligned} 297 p_0(A_s,A_d) & = max(A_s+A_d-1,0) \\ 298 p_1(A_s,A_d) & = min(A_s,1-A_d) \\ 299 p_2(A_s,A_d) & = min(A_d,1-A_s) \\ 300 \end{aligned} 301++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 302|==== 303-- 304 305[[framebuffer-blend-advanced-fxyz-modes]] 306.f/X/Y/Z Advanced Blend Operations 307[width="80%",options="header"] 308|==== 309| Mode | Blend Coefficients 310| ename:VK_BLEND_OP_ZERO_EXT a| 311[latexmath] 312++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 313 \begin{aligned} 314 (X,Y,Z) & = (0,0,0) \\ 315 f(C_s,C_d) & = 0 316 \end{aligned} 317++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 318 319 320| ename:VK_BLEND_OP_SRC_EXT a| 321[latexmath] 322++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 323 \begin{aligned} 324 (X,Y,Z) & = (1,1,0) \\ 325 f(C_s,C_d) & = C_s 326 \end{aligned} 327++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 328 329| ename:VK_BLEND_OP_DST_EXT a| 330[latexmath] 331++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 332 \begin{aligned} 333 (X,Y,Z) & = (1,0,1) \\ 334 f(C_s,C_d) & = C_d 335 \end{aligned} 336++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 337 338| ename:VK_BLEND_OP_SRC_OVER_EXT a| 339[latexmath] 340++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 341 \begin{aligned} 342 (X,Y,Z) & = (1,1,1) \\ 343 f(C_s,C_d) & = C_s 344 \end{aligned} 345++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 346 347| ename:VK_BLEND_OP_DST_OVER_EXT a| 348[latexmath] 349++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 350 \begin{aligned} 351 (X,Y,Z) & = (1,1,1) \\ 352 f(C_s,C_d) & = C_d 353 \end{aligned} 354++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 355 356| ename:VK_BLEND_OP_SRC_IN_EXT a| 357[latexmath] 358++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 359 \begin{aligned} 360 (X,Y,Z) & = (1,0,0) \\ 361 f(C_s,C_d) & = C_s 362 \end{aligned} 363++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 364 365| ename:VK_BLEND_OP_DST_IN_EXT a| 366[latexmath] 367++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 368 \begin{aligned} 369 (X,Y,Z) & = (1,0,0) \\ 370 f(C_s,C_d) & = C_d 371 \end{aligned} 372++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 373 374| ename:VK_BLEND_OP_SRC_OUT_EXT a| 375[latexmath] 376++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 377 \begin{aligned} 378 (X,Y,Z) & = (0,1,0) \\ 379 f(C_s,C_d) & = 0 380 \end{aligned} 381++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 382 383| ename:VK_BLEND_OP_DST_OUT_EXT a| 384[latexmath] 385++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 386 \begin{aligned} 387 (X,Y,Z) & = (0,0,1) \\ 388 f(C_s,C_d) & = 0 389 \end{aligned} 390++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 391 392| ename:VK_BLEND_OP_SRC_ATOP_EXT a| 393[latexmath] 394++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 395 \begin{aligned} 396 (X,Y,Z) & = (1,0,1) \\ 397 f(C_s,C_d) & = C_s 398 \end{aligned} 399++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 400 401| ename:VK_BLEND_OP_DST_ATOP_EXT a| 402[latexmath] 403++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 404 \begin{aligned} 405 (X,Y,Z) & = (1,1,0) \\ 406 f(C_s,C_d) & = C_d 407 \end{aligned} 408++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 409 410| ename:VK_BLEND_OP_XOR_EXT a| 411[latexmath] 412++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 413 \begin{aligned} 414 (X,Y,Z) & = (0,1,1) \\ 415 f(C_s,C_d) & = 0 416 \end{aligned} 417++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 418 419| ename:VK_BLEND_OP_MULTIPLY_EXT a| 420[latexmath] 421++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 422 \begin{aligned} 423 (X,Y,Z) & = (1,1,1) \\ 424 f(C_s,C_d) & = C_sC_d 425 \end{aligned} 426++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 427 428| ename:VK_BLEND_OP_SCREEN_EXT a| 429[latexmath] 430++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 431 \begin{aligned} 432 (X,Y,Z) & = (1,1,1) \\ 433 f(C_s,C_d) & = C_s+C_d-C_sC_d 434 \end{aligned} 435++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 436 437 438| ename:VK_BLEND_OP_OVERLAY_EXT a| 439[latexmath] 440++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 441 \begin{aligned} 442 (X,Y,Z) & = (1,1,1) \\ 443 f(C_s,C_d) & = 444 \begin{cases} 445 2 C_sC_d & C_d \leq 0.5 \\ 446 1-2 (1-C_s)(1-C_d) & \text{otherwise} 447 \end{cases} 448 \end{aligned} 449++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 450 451| ename:VK_BLEND_OP_DARKEN_EXT a| 452[latexmath] 453++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 454 \begin{aligned} 455 (X,Y,Z) & = (1,1,1) \\ 456 f(C_s,C_d) & = min(C_s,C_d) 457 \end{aligned} 458++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 459 460| ename:VK_BLEND_OP_LIGHTEN_EXT a| 461[latexmath] 462++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 463 \begin{aligned} 464 (X,Y,Z) & = (1,1,1) \\ 465 f(C_s,C_d) & = max(C_s,C_d) 466 \end{aligned} 467++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 468 469| ename:VK_BLEND_OP_COLORDODGE_EXT a| 470[latexmath] 471++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 472 \begin{aligned} 473 (X,Y,Z) & = (1,1,1) \\ 474 f(C_s,C_d) & = 475 \begin{cases} 476 0 & C_d \leq 0 \\ 477 min(1,\frac{C_d}{1-C_s}) & C_d \gt 0 \text{ and } C_s \lt 1 \\ 478 1 & C_d \gt 0 \text{ and } C_s \geq 1 479 \end{cases} 480 \end{aligned} 481++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 482 483| ename:VK_BLEND_OP_COLORBURN_EXT a| 484[latexmath] 485++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 486 \begin{aligned} 487 (X,Y,Z) & = (1,1,1) \\ 488 f(C_s,C_d) & = 489 \begin{cases} 490 1 & C_d \geq 1 \\ 491 1 - min(1,\frac{1-C_d}{C_s}) & C_d \lt 1 \text{ and } C_s \gt 0 \\ 492 0 & C_d \lt 1 \text{ and } C_s \leq 0 493 \end{cases} 494 \end{aligned} 495++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 496 497| ename:VK_BLEND_OP_HARDLIGHT_EXT a| 498[latexmath] 499++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 500 \begin{aligned} 501 (X,Y,Z) & = (1,1,1) \\ 502 f(C_s,C_d) & = 503 \begin{cases} 504 2 C_sC_d & C_s \leq 0.5 \\ 505 1-2 (1-C_s)(1-C_d) & \text{otherwise} 506 \end{cases} 507 \end{aligned} 508++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 509 510| ename:VK_BLEND_OP_SOFTLIGHT_EXT a| 511[latexmath] 512++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 513 \begin{aligned} 514 (X,Y,Z) & = (1,1,1) \\ 515 f(C_s,C_d) & = 516 \begin{cases} 517 C_d-(1-2 C_s)C_d(1-C_d) & C_s \leq 0.5 \\ 518 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 \\ 519 C_d+(2 C_s-1)(\sqrt{C_d}-C_d) & C_s \gt 0.5 \text{ and } C_d \gt 0.25 520 \end{cases} 521 \end{aligned} 522++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 523 524| ename:VK_BLEND_OP_DIFFERENCE_EXT a| 525[latexmath] 526++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 527 \begin{aligned} 528 (X,Y,Z) & = (1,1,1) \\ 529 f(C_s,C_d) & = \lvert C_d-C_s \rvert 530 \end{aligned} 531++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 532 533| ename:VK_BLEND_OP_EXCLUSION_EXT a| 534[latexmath] 535++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 536 \begin{aligned} 537 (X,Y,Z) & = (1,1,1) \\ 538 f(C_s,C_d) & = C_s+C_d-2C_sC_d 539 \end{aligned} 540++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 541 542| ename:VK_BLEND_OP_INVERT_EXT a| 543[latexmath] 544++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 545 \begin{aligned} 546 (X,Y,Z) & = (1,0,1) \\ 547 f(C_s,C_d) & = 1-C_d 548 \end{aligned} 549++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 550 551| ename:VK_BLEND_OP_INVERT_RGB_EXT a| 552[latexmath] 553++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 554 \begin{aligned} 555 (X,Y,Z) & = (1,0,1) \\ 556 f(C_s,C_d) & = C_s(1-C_d) 557 \end{aligned} 558++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 559 560| ename:VK_BLEND_OP_LINEARDODGE_EXT a| 561[latexmath] 562++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 563 \begin{aligned} 564 (X,Y,Z) & = (1,1,1) \\ 565 f(C_s,C_d) & = 566 \begin{cases} 567 C_s+C_d & C_s+C_d \leq 1 \\ 568 1 & \text{otherwise} 569 \end{cases} 570 \end{aligned} 571++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 572 573| ename:VK_BLEND_OP_LINEARBURN_EXT a| 574[latexmath] 575++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 576 \begin{aligned} 577 (X,Y,Z) & = (1,1,1) \\ 578 f(C_s,C_d) & = 579 \begin{cases} 580 C_s+C_d-1 & C_s+C_d \gt 1 \\ 581 0 & \text{otherwise} 582 \end{cases} 583 \end{aligned} 584++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 585 586| ename:VK_BLEND_OP_VIVIDLIGHT_EXT a| 587[latexmath] 588++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 589 \begin{aligned} 590 (X,Y,Z) & = (1,1,1) \\ 591 f(C_s,C_d) & = 592 \begin{cases} 593 1-min(1,\frac{1-C_d}{2C_s}) & 0 \lt C_s \lt 0.5 \\ 594 0 & C_s \leq 0 \\ 595 min(1,\frac{C_d}{2(1-C_s)}) & 0.5 \leq C_s \lt 1 \\ 596 1 & C_s \geq 1 597 \end{cases} 598 \end{aligned} 599++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 600 601| ename:VK_BLEND_OP_LINEARLIGHT_EXT a| 602[latexmath] 603++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 604 \begin{aligned} 605 (X,Y,Z) & = (1,1,1) \\ 606 f(C_s,C_d) & = 607 \begin{cases} 608 1 & 2C_s+C_d \gt 2 \\ 609 2C_s+C_d-1 & 1 \lt 2C_s+C_d \leq 2 \\ 610 0 & 2C_s+C_d \leq 1 611 \end{cases} 612 \end{aligned} 613++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 614 615| ename:VK_BLEND_OP_PINLIGHT_EXT a| 616[latexmath] 617++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 618 \begin{aligned} 619 (X,Y,Z) & = (1,1,1) \\ 620 f(C_s,C_d) & = 621 \begin{cases} 622 0 & 2C_s-1 \gt C_d \text{ and } C_s \lt 0.5 \\ 623 2C_s-1 & 2C_s-1 \gt C_d \text{ and } C_s \geq 0.5 \\ 624 2C_s & 2C_s-1 \leq C_d \text{ and } C_s \lt 0.5C_d \\ 625 C_d & 2C_s-1 \leq C_d \text{ and } C_s \geq 0.5C_d 626 \end{cases} 627 \end{aligned} 628++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 629 630| ename:VK_BLEND_OP_HARDMIX_EXT a| 631[latexmath] 632++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 633 \begin{aligned} 634 (X,Y,Z) & = (1,1,1) \\ 635 f(C_s,C_d) & = 636 \begin{cases} 637 0 & C_s+C_d \lt 1 \\ 638 1 & \text{otherwise} 639 \end{cases} 640 \end{aligned} 641++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 642 643|==== 644 645 646When using one of the HSL blend operations in table 647<<framebuffer-blend-advanced-hsl-modes,Hue-Saturation-Luminosity Advanced 648Blend Operations>> as the blend operation, the RGB color components produced 649by the function f are effectively obtained by converting both the 650non-premultiplied source and destination colors to the HSL (hue, saturation, 651luminosity) color space, generating a new HSL color by selecting H, S, and L 652components from the source or destination according to the blend operation, 653and then converting the result back to RGB. 654In the equations below, a blended RGB color is produced according to the 655following pseudocode: 656 657[source,c++] 658---- 659 float minv3(vec3 c) { 660 return min(min(c.r, c.g), c.b); 661 } 662 float maxv3(vec3 c) { 663 return max(max(c.r, c.g), c.b); 664 } 665 float lumv3(vec3 c) { 666 return dot(c, vec3(0.30, 0.59, 0.11)); 667 } 668 float satv3(vec3 c) { 669 return maxv3(c) - minv3(c); 670 } 671 672 // If any color components are outside [0,1], adjust the color to 673 // get the components in range. 674 vec3 ClipColor(vec3 color) { 675 float lum = lumv3(color); 676 float mincol = minv3(color); 677 float maxcol = maxv3(color); 678 if (mincol < 0.0) { 679 color = lum + ((color-lum)*lum) / (lum-mincol); 680 } 681 if (maxcol > 1.0) { 682 color = lum + ((color-lum)*(1-lum)) / (maxcol-lum); 683 } 684 return color; 685 } 686 687 // Take the base RGB color <cbase> and override its luminosity 688 // with that of the RGB color <clum>. 689 vec3 SetLum(vec3 cbase, vec3 clum) { 690 float lbase = lumv3(cbase); 691 float llum = lumv3(clum); 692 float ldiff = llum - lbase; 693 vec3 color = cbase + vec3(ldiff); 694 return ClipColor(color); 695 } 696 697 // Take the base RGB color <cbase> and override its saturation with 698 // that of the RGB color <csat>. The override the luminosity of the 699 // result with that of the RGB color <clum>. 700 vec3 SetLumSat(vec3 cbase, vec3 csat, vec3 clum) 701 { 702 float minbase = minv3(cbase); 703 float sbase = satv3(cbase); 704 float ssat = satv3(csat); 705 vec3 color; 706 if (sbase > 0) { 707 // Equivalent (modulo rounding errors) to setting the 708 // smallest (R,G,B) component to 0, the largest to <ssat>, 709 // and interpolating the "middle" component based on its 710 // original value relative to the smallest/largest. 711 color = (cbase - minbase) * ssat / sbase; 712 } else { 713 color = vec3(0.0); 714 } 715 return SetLum(color, clum); 716 } 717---- 718 719[[framebuffer-blend-advanced-hsl-modes]] 720.Hue-Saturation-Luminosity Advanced Blend Operations 721[width="80%",options="header"] 722|==== 723| Mode | Result 724| ename:VK_BLEND_OP_HSL_HUE_EXT a| 725[latexmath] 726++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 727 \begin{aligned} 728 (X,Y,Z) & = (1,1,1) \\ 729 f(C_s,C_d) & = SetLumSat(C_s,C_d,C_d) 730 \end{aligned} 731++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 732 733| ename:VK_BLEND_OP_HSL_SATURATION_EXT a| 734[latexmath] 735++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 736 \begin{aligned} 737 (X,Y,Z) & = (1,1,1) \\ 738 f(C_s,C_d) & = SetLumSat(C_d,C_s,C_d) 739 \end{aligned} 740++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 741 742| ename:VK_BLEND_OP_HSL_COLOR_EXT a| 743[latexmath] 744++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 745 \begin{aligned} 746 (X,Y,Z) & = (1,1,1) \\ 747 f(C_s,C_d) & = SetLum(C_s,C_d) 748 \end{aligned} 749++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 750 751| ename:VK_BLEND_OP_HSL_LUMINOSITY_EXT a| 752[latexmath] 753++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 754 \begin{aligned} 755 (X,Y,Z) & = (1,1,1) \\ 756 f(C_s,C_d) & = SetLum(C_d,C_s) 757 \end{aligned} 758++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 759|==== 760 761 762When using one of the operations in table 763<<framebuffer-blend-advanced-additional-rgb,Additional RGB Blend 764Operations>> as the blend operation, the source and destination colors used 765by these blending operations are interpreted according to 766pname:srcPremultiplied and pname:dstPremultiplied. 767The blending operations below are evaluated where the RGB source and 768destination color components are both considered to have been premultiplied 769by the corresponding A component. 770 771[latexmath] 772+++++++++++++++++++ 773\begin{aligned} 774 (R_s', G_s', B_s') & = 775 \begin{cases} 776 (R_s, G_s, B_s) & \text{if srcPremultiplied is VK\_TRUE} \\ 777 (R_sA_s, G_sA_s, B_sA_s) & \text{if srcPremultiplied is VK\_FALSE} 778 \end{cases} \\ 779 (R_d', G_d', B_d') & = 780 \begin{cases} 781 (R_d, G_d, B_d) & \text{if dstPremultiplied is VK\_TRUE} \\ 782 (R_dA_d, G_dA_d, B_dA_d) & \text{if dstPremultiplied is VK\_FALSE} 783 \end{cases} 784\end{aligned} 785+++++++++++++++++++ 786 787[[framebuffer-blend-advanced-additional-rgb]] 788.Additional RGB Blend Operations 789[width="80%",options="header"] 790|==== 791| Mode | Result 792| ename:VK_BLEND_OP_PLUS_EXT a| 793[latexmath] 794++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 795 \begin{aligned} 796 (R,G,B,A) = ( & R_s'+R_d', \\ 797 & G_s'+G_d', \\ 798 & B_s'+B_d', \\ 799 & A_s+A_d) 800 \end{aligned} 801++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 802 803| ename:VK_BLEND_OP_PLUS_CLAMPED_EXT a| 804[latexmath] 805++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 806 \begin{aligned} 807 (R,G,B,A) = ( & min(1,R_s'+R_d'), \\ 808 & min(1,G_s'+G_d'), \\ 809 & min(1,B_s'+B_d'), \\ 810 & min(1,A_s+A_d)) 811 \end{aligned} 812++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 813 814| ename:VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT a| 815[latexmath] 816++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 817 \begin{aligned} 818 (R,G,B,A) = ( & min(min(1,A_s+A_d),R_s'+R_d'), \\ 819 & min(min(1,A_s+A_d),G_s'+G_d'), \\ 820 & min(min(1,A_s+A_d),B_s'+B_d'), \\ 821 & min(1,A_s+A_d)) 822 \end{aligned} 823++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 824 825| ename:VK_BLEND_OP_PLUS_DARKER_EXT a| 826[latexmath] 827++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 828 \begin{aligned} 829 (R,G,B,A) = ( & max(0,min(1,A_s+A_d)-((A_s-R_s')+(A_d-R_d'))), \\ 830 & max(0,min(1,A_s+A_d)-((A_s-G_s')+(A_d-G_d'))), \\ 831 & max(0,min(1,A_s+A_d)-((A_s-B_s')+(A_d-B_d'))), \\ 832 & min(1,A_s+A_d)) 833 \end{aligned} 834++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 835 836| ename:VK_BLEND_OP_MINUS_EXT a| 837[latexmath] 838++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 839 \begin{aligned} 840 (R,G,B,A) = ( & R_d'-R_s', \\ 841 & G_d'-G_s', \\ 842 & B_d'-B_s', \\ 843 & A_d-A_s) 844 \end{aligned} 845++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 846 847| ename:VK_BLEND_OP_MINUS_CLAMPED_EXT a| 848[latexmath] 849++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 850 \begin{aligned} 851 (R,G,B,A) = ( & max(0,R_d'-R_s'), \\ 852 & max(0,G_d'-G_s'), \\ 853 & max(0,B_d'-B_s'), \\ 854 & max(0,A_d-A_s)) 855 \end{aligned} 856++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 857 858| ename:VK_BLEND_OP_CONTRAST_EXT a| 859[latexmath] 860++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 861 \begin{aligned} 862 (R,G,B,A) = ( & \frac{A_d}{2} + 2(R_d'-\frac{A_d}{2})(R_s'-\frac{A_s}{2}), \\ 863 & \frac{A_d}{2} + 2(G_d'-\frac{A_d}{2})(G_s'-\frac{A_s}{2}), \\ 864 & \frac{A_d}{2} + 2(B_d'-\frac{A_d}{2})(B_s'-\frac{A_s}{2}), \\ 865 & A_d) 866 \end{aligned} 867++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 868 869| ename:VK_BLEND_OP_INVERT_OVG_EXT a| 870[latexmath] 871++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 872 \begin{aligned} 873 (R,G,B,A) = ( & A_s(1-R_d') + (1-A_s)R_d', \\ 874 & A_s(1-G_d') + (1-A_s)G_d', \\ 875 & A_s(1-B_d') + (1-A_s)B_d', \\ 876 & A_s+A_d-A_sA_d) 877 \end{aligned} 878++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 879 880| ename:VK_BLEND_OP_RED_EXT a| 881[latexmath] 882++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 883 \begin{aligned} 884 (R,G,B,A) & = (R_s', G_d', B_d', A_d) 885 \end{aligned} 886++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 887 888| ename:VK_BLEND_OP_GREEN_EXT a| 889[latexmath] 890++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 891 \begin{aligned} 892 (R,G,B,A) & = (R_d', G_s', B_d', A_d) 893 \end{aligned} 894++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 895 896| ename:VK_BLEND_OP_BLUE_EXT a| 897[latexmath] 898++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 899 \begin{aligned} 900 (R,G,B,A) & = (R_d', G_d', B_s', A_d) 901 \end{aligned} 902++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 903|==== 904