帧缓冲
混合
混合将传入的源片段的 R、G、B 和 A 值与帧缓冲区中片段 (xf,yf) 位置处存储的每个样本的目标 R、G、B 和 A 值组合。混合是为片段覆盖的每个颜色样本执行的,而不是每个片段只执行一次。
混合是为子通道使用的每个颜色附件单独计算和应用的,每个附件都有单独的控制。
在执行混合操作之前,带符号和无符号归一化定点颜色分量会进行隐式转换为浮点数,如从归一化定点转换为浮点数所述。混合计算被视为以浮点数执行,并且基本混合操作的精度和动态范围不低于用于表示目标分量的精度和动态范围。高级混合操作的执行精度和动态范围不低于用于表示目标分量的精度和动态范围或用于表示 16 位浮点值的精度和动态范围的较小者。
混合仅针对浮点数、UNORM、SNORM 和 sRGB 格式定义。在这些格式中,实现可能仅支持在其中某些子集上进行混合。哪些格式支持混合由 |
管线混合状态包含在图形管线创建期间的 VkPipelineColorBlendStateCreateInfo
结构中
VkPipelineColorBlendStateCreateInfo
结构的定义如下
// Provided by VK_VERSION_1_0
typedef struct VkPipelineColorBlendStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineColorBlendStateCreateFlags flags;
VkBool32 logicOpEnable;
VkLogicOp logicOp;
uint32_t attachmentCount;
const VkPipelineColorBlendAttachmentState* pAttachments;
float blendConstants[4];
} VkPipelineColorBlendStateCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
为NULL
或指向扩展此结构的结构的指针。 -
flags
是 VkPipelineColorBlendStateCreateFlagBits 的位掩码,用于指定其他颜色混合信息。 -
logicOpEnable
控制是否应用逻辑操作。 -
logicOp
选择要应用的逻辑操作。 -
attachmentCount
是pAttachments
中 VkPipelineColorBlendAttachmentState 元素的数量。如果管线是使用VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT
、VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT
和VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT
动态状态集创建的,并且设置了VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
或未启用 advancedBlendCoherentOperations 功能,则此值将被忽略。 -
pAttachments
是指向 VkPipelineColorBlendAttachmentState 结构数组的指针,该数组为每个颜色附件定义混合状态。如果管线是使用VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT
、VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT
和VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT
动态状态集创建的,并且设置了VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
或未启用 advancedBlendCoherentOperations 功能,则此值将被忽略。 -
blendConstants
是一个指向四个值的数组的指针,这些值用作混合常量中的 R、G、B 和 A 分量,具体取决于混合因子。
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineColorBlendStateCreateFlags;
VkPipelineColorBlendStateCreateFlags
是一个位掩码类型,用于设置零个或多个 VkPipelineColorBlendStateCreateFlagBits 的掩码。
可以在 VkPipelineColorBlendStateCreateInfo::flags
参数中设置的位是:
// Provided by VK_EXT_rasterization_order_attachment_access
typedef enum VkPipelineColorBlendStateCreateFlagBits {
// Provided by VK_EXT_rasterization_order_attachment_access
VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0x00000001,
// Provided by VK_ARM_rasterization_order_attachment_access
VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT,
} VkPipelineColorBlendStateCreateFlagBits;
-
VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT
指定对颜色和输入附件的访问将具有隐式的帧缓冲区本地内存依赖关系,允许应用程序在片段着色器中表达自定义混合操作。
当管道中包含 VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT
时,它为该管道的绘制命令生成的每个片段形成一个帧缓冲区本地内存依赖关系,其范围如下:
VkPipelineColorBlendAttachmentState
结构体定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkPipelineColorBlendAttachmentState {
VkBool32 blendEnable;
VkBlendFactor srcColorBlendFactor;
VkBlendFactor dstColorBlendFactor;
VkBlendOp colorBlendOp;
VkBlendFactor srcAlphaBlendFactor;
VkBlendFactor dstAlphaBlendFactor;
VkBlendOp alphaBlendOp;
VkColorComponentFlags colorWriteMask;
} VkPipelineColorBlendAttachmentState;
-
blendEnable
控制是否为相应的颜色附件启用混合。如果未启用混合,则该附件的源片段颜色将不做修改地传递。 -
srcColorBlendFactor
选择哪个混合因子用于确定源因子 (Sr,Sg,Sb)。 -
dstColorBlendFactor
选择哪个混合因子用于确定目标因子 (Dr,Dg,Db)。 -
colorBlendOp
选择哪个混合操作用于计算要写入颜色附件的 RGB 值。 -
srcAlphaBlendFactor
选择哪个混合因子用于确定源因子 Sa。 -
dstAlphaBlendFactor
选择哪个混合因子用于确定目标因子 Da。 -
alphaBlendOp
选择哪个混合操作用于计算要写入颜色附件的 alpha 值。 -
colorWriteMask
是一个 VkColorComponentFlagBits 的位掩码,指定 R、G、B 和/或 A 分量中的哪些分量被启用进行写入,如 颜色写入掩码 中所述。
要动态设置 blendEnable
,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetColorBlendEnableEXT(
VkCommandBuffer commandBuffer,
uint32_t firstAttachment,
uint32_t attachmentCount,
const VkBool32* pColorBlendEnables);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
firstAttachment
是颜色混合启用所应用的第一个颜色附件。 -
attachmentCount
是pColorBlendEnables
数组中颜色混合启用的数量。 -
pColorBlendEnables
是一个布尔值数组,用于指示是否为相应的附件启用了颜色混合。
当使用着色器对象进行绘制时,或者当使用 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置的 VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT
创建图形管线时,此命令设置后续绘图命令的指定颜色附件的颜色混合启用。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendAttachmentState::blendEnable
值指定。
要动态设置颜色混合因子和操作,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetColorBlendEquationEXT(
VkCommandBuffer commandBuffer,
uint32_t firstAttachment,
uint32_t attachmentCount,
const VkColorBlendEquationEXT* pColorBlendEquations);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
firstAttachment
是颜色混合因子和操作所应用的第一个颜色附件。 -
attachmentCount
是pColorBlendEquations
数组中 VkColorBlendEquationEXT 元素的数量。 -
pColorBlendEquations
是一个 VkColorBlendEquationEXT 结构体数组,用于指定相应附件的颜色混合因子和操作。
此命令设置指定附件的颜色混合因子和操作,以便在使用着色器对象进行绘制时,或者当图形管线使用 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置的 VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT
创建时,用于后续的绘制命令。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendAttachmentState::srcColorBlendFactor
、VkPipelineColorBlendAttachmentState::dstColorBlendFactor
、VkPipelineColorBlendAttachmentState::colorBlendOp
、VkPipelineColorBlendAttachmentState::srcAlphaBlendFactor
、VkPipelineColorBlendAttachmentState::dstAlphaBlendFactor
和 VkPipelineColorBlendAttachmentState::alphaBlendOp
值指定。
VkColorBlendEquationEXT
结构的定义如下
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
typedef struct VkColorBlendEquationEXT {
VkBlendFactor srcColorBlendFactor;
VkBlendFactor dstColorBlendFactor;
VkBlendOp colorBlendOp;
VkBlendFactor srcAlphaBlendFactor;
VkBlendFactor dstAlphaBlendFactor;
VkBlendOp alphaBlendOp;
} VkColorBlendEquationEXT;
-
srcColorBlendFactor
选择哪个混合因子用于确定源因子 (Sr,Sg,Sb)。 -
dstColorBlendFactor
选择哪个混合因子用于确定目标因子 (Dr,Dg,Db)。 -
colorBlendOp
选择哪个混合操作用于计算要写入颜色附件的 RGB 值。 -
srcAlphaBlendFactor
选择哪个混合因子用于确定源因子 Sa。 -
dstAlphaBlendFactor
选择哪个混合因子用于确定目标因子 Da。 -
alphaBlendOp
选择用于计算要写入颜色附件的 alpha 值的混合操作。
要动态设置颜色写入掩码,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetColorWriteMaskEXT(
VkCommandBuffer commandBuffer,
uint32_t firstAttachment,
uint32_t attachmentCount,
const VkColorComponentFlags* pColorWriteMasks);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
firstAttachment
是颜色写入掩码应用到的第一个颜色附件。 -
attachmentCount
是pColorWriteMasks
数组中 VkColorComponentFlags 值的数量。 -
pColorWriteMasks
是一个 VkColorComponentFlags 值的数组,指定相应附件的颜色写入掩码。
此命令设置指定附件的颜色写入掩码,以便在使用着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT
的情况下创建时,用于后续的绘制命令。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendAttachmentState::colorWriteMask
值指定。
在 VkColorComponentFlagBits 指定的组件之间共享位的格式(例如 |
混合因子
源和目标颜色以及 alpha 混合因子是从枚举中选择的
// Provided by VK_VERSION_1_0
typedef enum VkBlendFactor {
VK_BLEND_FACTOR_ZERO = 0,
VK_BLEND_FACTOR_ONE = 1,
VK_BLEND_FACTOR_SRC_COLOR = 2,
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3,
VK_BLEND_FACTOR_DST_COLOR = 4,
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5,
VK_BLEND_FACTOR_SRC_ALPHA = 6,
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7,
VK_BLEND_FACTOR_DST_ALPHA = 8,
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9,
VK_BLEND_FACTOR_CONSTANT_COLOR = 10,
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11,
VK_BLEND_FACTOR_CONSTANT_ALPHA = 12,
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13,
VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14,
VK_BLEND_FACTOR_SRC1_COLOR = 15,
VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
VK_BLEND_FACTOR_SRC1_ALPHA = 17,
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
} VkBlendFactor;
下面表格描述了枚举值的语义
VkBlendFactor | RGB 混合因子 (Sr,Sg,Sb) 或 (Dr,Dg,Db) | Alpha 混合因子 (Sa 或 Da) |
---|---|---|
|
(0,0,0) |
0 |
|
(1,1,1) |
1 |
|
(Rs0,Gs0,Bs0) |
As0 |
|
(1-Rs0,1-Gs0,1-Bs0) |
1-As0 |
|
(Rd,Gd,Bd) |
Ad |
|
(1-Rd,1-Gd,1-Bd) |
1-Ad |
|
(As0,As0,As0) |
As0 |
|
(1-As0,1-As0,1-As0) |
1-As0 |
|
(Ad,Ad,Ad) |
Ad |
|
(1-Ad,1-Ad,1-Ad) |
1-Ad |
|
(Rc,Gc,Bc) |
Ac |
|
(1-Rc,1-Gc,1-Bc) |
1-Ac |
|
(Ac,Ac,Ac) |
Ac |
|
(1-Ac,1-Ac,1-Ac) |
1-Ac |
|
(f,f,f); f = min(As0,1-Ad) |
1 |
|
(Rs1,Gs1,Bs1) |
As1 |
|
(1-Rs1,1-Gs1,1-Bs1) |
1-As1 |
|
(As1,As1,As1) |
As1 |
|
(1-As1,1-As1,1-As1) |
1-As1 |
在此表格中,使用以下约定
-
Rs0,Gs0,Bs0 和 As0 分别表示与正在混合的颜色附件对应的片段输出位置的第一个源颜色 R、G、B 和 A 分量。
-
Rs1,Gs1,Bs1 和 As1 分别表示在双源混合模式中,用于混合的颜色附件对应的片段输出位置的第二个源颜色 R、G、B 和 A 分量。
-
Rd,Gd,Bd 和 Ad 表示目标颜色的 R、G、B 和 A 分量。也就是说,此片段/采样对应的颜色附件中当前的颜色。
-
Rc,Gc,Bc 和 Ac 分别表示混合常量 R、G、B 和 A 分量。
要动态设置和更改混合常量,请调用
// Provided by VK_VERSION_1_0
void vkCmdSetBlendConstants(
VkCommandBuffer commandBuffer,
const float blendConstants[4]);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
blendConstants
是一个指向四个值的数组的指针,指定用于混合的混合常量颜色的 Rc、Gc、Bc 和 Ac 分量,具体取决于 混合因子。
当使用 着色器对象进行绘制时,或当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_BLEND_CONSTANTS
时创建时,此命令会为后续的绘制命令设置混合常量。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendStateCreateInfo::blendConstants
值指定。
双源混合
使用第二个颜色输入 (Rs1,Gs1,Bs1,As1) (VK_BLEND_FACTOR_SRC1_COLOR
、VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
、VK_BLEND_FACTOR_SRC1_ALPHA
和 VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
) 的混合因子可能会消耗实现资源,否则这些资源可以用于渲染到多个颜色附件。因此,当使用双源混合时,帧缓冲区中可以使用的颜色附件的数量可能会减少。
只有在启用了dualSrcBlend
功能时,才支持双源混合。
当使用双源混合功能时,子通道中可以使用的最大颜色附件数量取决于实现,并作为 VkPhysicalDeviceLimits
的 maxFragmentDualSrcAttachments
成员报告。
可以使用 Index
修饰符将颜色输出绑定到混合器的第一个和第二个输入,如片段输出接口中所述。如果着色器中未写入混合器的第二个颜色输入,或者如果没有输出绑定到混合器的第二个输入,则第二个输入的值是未定义的。
混合操作
一旦选择了源和目标混合因子,它们将与源和目标分量一起传递到混合操作。RGB 和 alpha 分量可以使用不同的操作。VkBlendOp 的可能值指定了操作,它们是
// Provided by VK_VERSION_1_0
typedef enum VkBlendOp {
VK_BLEND_OP_ADD = 0,
VK_BLEND_OP_SUBTRACT = 1,
VK_BLEND_OP_REVERSE_SUBTRACT = 2,
VK_BLEND_OP_MIN = 3,
VK_BLEND_OP_MAX = 4,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_ZERO_EXT = 1000148000,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SRC_EXT = 1000148001,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DST_EXT = 1000148002,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SRC_OVER_EXT = 1000148003,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DST_OVER_EXT = 1000148004,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SRC_IN_EXT = 1000148005,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DST_IN_EXT = 1000148006,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SRC_OUT_EXT = 1000148007,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DST_OUT_EXT = 1000148008,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SRC_ATOP_EXT = 1000148009,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DST_ATOP_EXT = 1000148010,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_XOR_EXT = 1000148011,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_MULTIPLY_EXT = 1000148012,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SCREEN_EXT = 1000148013,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_OVERLAY_EXT = 1000148014,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DARKEN_EXT = 1000148015,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_LIGHTEN_EXT = 1000148016,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_COLORDODGE_EXT = 1000148017,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_COLORBURN_EXT = 1000148018,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HARDLIGHT_EXT = 1000148019,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_DIFFERENCE_EXT = 1000148021,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_EXCLUSION_EXT = 1000148022,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_INVERT_EXT = 1000148023,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_INVERT_RGB_EXT = 1000148024,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_LINEARDODGE_EXT = 1000148025,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_LINEARBURN_EXT = 1000148026,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_PINLIGHT_EXT = 1000148029,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HARDMIX_EXT = 1000148030,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HSL_HUE_EXT = 1000148031,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HSL_COLOR_EXT = 1000148033,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_PLUS_EXT = 1000148035,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_MINUS_EXT = 1000148039,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_CONTRAST_EXT = 1000148041,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_INVERT_OVG_EXT = 1000148042,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_RED_EXT = 1000148043,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_GREEN_EXT = 1000148044,
// Provided by VK_EXT_blend_operation_advanced
VK_BLEND_OP_BLUE_EXT = 1000148045,
} VkBlendOp;
基本混合操作的语义如下表所述
VkBlendOp | RGB 分量 | Alpha 分量 |
---|---|---|
|
R = Rs0 × Sr + Rd × Dr |
A = As0 × Sa + Ad × Da |
|
R = Rs0 × Sr - Rd × Dr |
A = As0 × Sa - Ad × Da |
|
R = Rd × Dr - Rs0 × Sr |
A = Ad × Da - As0 × Sa |
|
R = min(Rs0,Rd) |
A = min(As0,Ad) |
|
R = max(Rs0,Rd) |
A = max(As0,Ad) |
在此表格中,使用以下约定
-
Rs0, Gs0, Bs0 和 As0 分别表示第一个源颜色 R、G、B 和 A 分量。
-
Rd, Gd, Bd 和 Ad 表示目标颜色的 R、G、B 和 A 分量。也就是说,此片段/采样对应的颜色附件中当前的颜色。
-
Sr, Sg, Sb 和 Sa 分别表示源混合因子 R、G、B 和 A 分量。
-
Dr, Dg, Db 和 Da 分别表示目标混合因子 R、G、B 和 A 分量。
混合操作产生一组新的值 R, G, B 和 A,这些值被写入到帧缓冲附件中。如果此附件未启用混合,则 R, G, B 和 A 分别被赋值为 Rs0, Gs0, Bs0 和 As0。
如果颜色附件是定点格式,则在计算混合操作之前,源值和目标值以及混合因子的分量都分别被钳制到 [0,1] 或 [-1,1] 范围,具体取决于无符号归一化或有符号归一化颜色附件。如果颜色附件是浮点格式,则不进行钳制。
如果帧缓冲附件的数值格式使用 sRGB 编码,则 R、G 和 B 目标颜色值(从定点转换为浮点后)被认为是为 sRGB 颜色空间编码的,因此在混合之前会进行线性化。每个 R、G 和 B 分量都按照Khronos 数据格式规范的“sRGB EOTF”部分所述从非线性转换为线性。如果格式不是 sRGB,则不执行线性化。
如果帧缓冲附件的数值格式使用 sRGB 编码,则最终的 R、G 和 B 值在写入帧缓冲附件之前,会按照 Khronos 数据格式规范的“sRGB EOTF -1”部分所述转换为非线性 sRGB 表示形式。
如果帧缓冲颜色附件的数值格式未使用 sRGB 编码,则 R、G 和 B 的最终 cs 值保持不变。A 的值永远不会进行 sRGB 编码。也就是说,alpha 分量始终以线性形式存储在内存中。
如果帧缓冲颜色附件是 VK_ATTACHMENT_UNUSED
,则不会通过该附件执行写入操作。不会对大于或等于 VkSubpassDescription
::colorAttachmentCount
或 VkSubpassDescription2
::colorAttachmentCount
值的帧缓冲颜色附件执行写入操作。
高级混合操作
高级混合操作是指在表 f/X/Y/Z 高级混合操作、色调-饱和度-亮度高级混合操作和附加 RGB 混合操作中列出的操作。
如果 VkPipelineColorBlendStateCreateInfo 的 pNext
链包含 VkPipelineColorBlendAdvancedStateCreateInfoEXT
结构,则该结构包含影响高级混合操作的参数。
VkPipelineColorBlendAdvancedStateCreateInfoEXT
结构的定义如下:
// Provided by VK_EXT_blend_operation_advanced
typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkBool32 srcPremultiplied;
VkBool32 dstPremultiplied;
VkBlendOverlapEXT blendOverlap;
} VkPipelineColorBlendAdvancedStateCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
为NULL
或指向扩展此结构的结构的指针。 -
srcPremultiplied
指定混合操作的源颜色是否被视为预乘。 -
dstPremultiplied
指定混合操作的目标颜色是否被视为预乘。 -
blendOverlap
是一个 VkBlendOverlapEXT 值,指定源样本和目标样本的覆盖率是如何关联的。
如果此结构不存在,则 srcPremultiplied
和 dstPremultiplied
都被认为是 VK_TRUE
,并且 blendOverlap
被认为是 VK_BLEND_OVERLAP_UNCORRELATED_EXT
。
要动态设置高级混合状态,请调用
// Provided by VK_EXT_blend_operation_advanced with VK_EXT_extended_dynamic_state3, VK_EXT_blend_operation_advanced with VK_EXT_shader_object
void vkCmdSetColorBlendAdvancedEXT(
VkCommandBuffer commandBuffer,
uint32_t firstAttachment,
uint32_t attachmentCount,
const VkColorBlendAdvancedEXT* pColorBlendAdvanced);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
firstAttachment
是高级混合参数应用到的第一个颜色附件。 -
attachmentCount
是pColorBlendAdvanced
数组中 VkColorBlendAdvancedEXT 元素的数量。 -
pColorBlendAdvanced
是一个 VkColorBlendAdvancedEXT 结构数组,指定相应附件的高级颜色混合参数。
此命令设置指定附件的高级混合操作参数,以便在使用着色器对象进行绘制时,或者当使用 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置的 VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
创建图形管线时,进行后续的绘制命令。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendAdvancedStateCreateInfoEXT::srcPremultiplied
、VkPipelineColorBlendAdvancedStateCreateInfoEXT::dstPremultiplied
和 VkPipelineColorBlendAdvancedStateCreateInfoEXT::blendOverlap
值指定。
VkColorBlendAdvancedEXT
结构定义如下:
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
typedef struct VkColorBlendAdvancedEXT {
VkBlendOp advancedBlendOp;
VkBool32 srcPremultiplied;
VkBool32 dstPremultiplied;
VkBlendOverlapEXT blendOverlap;
VkBool32 clampResults;
} VkColorBlendAdvancedEXT;
-
advancedBlendOp
选择用于计算写入颜色附件的 RGB 值的混合操作。 -
srcPremultiplied
指定混合操作的源颜色是否被视为预乘。 -
dstPremultiplied
指定混合操作的目标颜色是否被视为预乘。 -
blendOverlap
是一个 VkBlendOverlapEXT 值,指定源样本和目标样本的覆盖率是如何关联的。 -
clampResults
指定结果在写入附件之前必须钳制到 [0,1] 范围内,当附件格式不是归一化定点格式时,此项很有用。
当使用表 f/X/Y/Z 高级混合操作 或 色调-饱和度-亮度高级混合操作 中的一种操作时,混合将根据以下公式执行
其中函数 f 和项 X、Y 和 Z 在表中指定。用于混合的源颜色的 R、G 和 B 分量根据 srcPremultiplied
导出。如果 srcPremultiplied
为 VK_TRUE
,则认为片段颜色分量在混合之前已乘以 A 分量。基本源颜色 (Rs',Gs',Bs') 通过除以 A 分量获得
如果 srcPremultiplied
为 VK_FALSE
,则片段颜色分量用作基本颜色
用于混合的目标颜色的 R、G 和 B 分量根据 dstPremultiplied
导出。如果 dstPremultiplied
为 VK_TRUE
,则认为目标分量在混合之前已乘以 A 分量。基本目标颜色 (Rd',Gd',Bd') 通过除以 A 分量获得
如果 dstPremultiplied
为 VK_FALSE
,则目标颜色分量用作基本颜色
当使用高级混合操作进行混合时,我们期望预乘源颜色和目标颜色的 R、G 和 B 分量存储为非预乘 R、G 和 B 分量值与颜色 A 分量的乘积。如果预乘输入颜色的任何 R、G 或 B 分量为非零值,并且 A 分量为零,则认为该颜色格式不正确,并且混合结果的相应分量是未定义的。
本章中的所有高级混合操作公式都将结果计算为预乘颜色。如果 dstPremultiplied
为 VK_FALSE
,则该结果颜色的 R、G 和 B 分量在写入帧缓冲区之前除以 A 分量。如果颜色的任何 R、G 或 B 分量为非零值,并且 A 分量为零,则认为结果格式不正确,并且混合结果的相应分量是未定义的。如果所有分量均为零,则该值保持不变。
如果任何输入或结果颜色的 A 分量小于零,则认为该颜色格式不正确,并且混合结果的所有分量都是未定义的。
权重函数 p0、p1 和 p2 在表 高级混合重叠模式 中定义。在这些函数中,源颜色和目标颜色的 A 分量被视为指示片段(源)覆盖的像素部分以及先前在像素中累积的片段(目标)。函数 p0、p1 和 p2 分别近似于源和目标相交覆盖的像素相对部分、仅由源覆盖的像素部分以及仅由目标覆盖的像素部分。
VkPipelineColorBlendAdvancedStateCreateInfoEXT::blendOverlap
的可能值,指定混合重叠函数,是
// Provided by VK_EXT_blend_operation_advanced
typedef enum VkBlendOverlapEXT {
VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0,
VK_BLEND_OVERLAP_DISJOINT_EXT = 1,
VK_BLEND_OVERLAP_CONJOINT_EXT = 2,
} VkBlendOverlapEXT;
-
VK_BLEND_OVERLAP_UNCORRELATED_EXT
指定源和目标覆盖之间没有相关性。 -
VK_BLEND_OVERLAP_CONJOINT_EXT
指定认为源和目标覆盖具有最大重叠。 -
VK_BLEND_OVERLAP_DISJOINT_EXT
指定认为源和目标覆盖具有最小重叠。
重叠模式 | 权重方程 |
---|---|
|
|
|
|
|
模式 | 混合系数 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
当使用表 色调-饱和度-亮度高级混合操作 中的一种 HSL 混合操作作为混合操作时,函数 f 生成的 RGB 颜色分量实际上是通过将非预乘源颜色和目标颜色都转换为 HSL(色调、饱和度、亮度)颜色空间获得的,根据混合操作从源或目标中选择 H、S 和 L 分量生成新的 HSL 颜色,然后将结果转换回 RGB。在下面的公式中,根据以下伪代码生成混合的 RGB 颜色
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);
}
模式 | 结果 |
---|---|
|
|
|
|
|
|
|
当使用表 其他 RGB 混合操作 中的一种操作作为混合操作时,这些混合操作使用的源颜色和目标颜色会根据 srcPremultiplied
和 dstPremultiplied
进行解释。下面的混合操作的计算方式是,RGB 源颜色和目标颜色分量都被认为已乘以相应的 A 分量。
模式 | 结果 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
逻辑操作
应用程序可以启用片段颜色值与帧缓冲区附件中现有值之间的逻辑操作。此逻辑操作在更新帧缓冲区附件之前应用。逻辑操作仅应用于带符号和无符号整数以及归一化整数帧缓冲区。逻辑操作不应用于浮点或 sRGB 格式的颜色附件。
逻辑操作由 VkPipelineColorBlendStateCreateInfo 的 logicOpEnable
和 logicOp
成员控制。如果图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT
,则 logicOpEnable
状态也可以由 vkCmdSetLogicOpEnableEXT 控制。如果图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LOGIC_OP_EXT
,则 logicOp
状态也可以由 vkCmdSetLogicOpEXT 控制。如果 logicOpEnable
为 VK_TRUE
,则在每个颜色附件和片段的相应输出值之间应用由 logicOp
选择的逻辑操作,并且所有附件的混合都被视为已禁用。任何使用不支持逻辑操作的颜色格式的附件都只是传递未修改的颜色值。逻辑操作独立应用于红色、绿色、蓝色和 alpha 分量中的每一个。logicOp
从以下操作中选择
// Provided by VK_VERSION_1_0
typedef enum VkLogicOp {
VK_LOGIC_OP_CLEAR = 0,
VK_LOGIC_OP_AND = 1,
VK_LOGIC_OP_AND_REVERSE = 2,
VK_LOGIC_OP_COPY = 3,
VK_LOGIC_OP_AND_INVERTED = 4,
VK_LOGIC_OP_NO_OP = 5,
VK_LOGIC_OP_XOR = 6,
VK_LOGIC_OP_OR = 7,
VK_LOGIC_OP_NOR = 8,
VK_LOGIC_OP_EQUIVALENT = 9,
VK_LOGIC_OP_INVERT = 10,
VK_LOGIC_OP_OR_REVERSE = 11,
VK_LOGIC_OP_COPY_INVERTED = 12,
VK_LOGIC_OP_OR_INVERTED = 13,
VK_LOGIC_OP_NAND = 14,
VK_LOGIC_OP_SET = 15,
} VkLogicOp;
Vulkan 支持的逻辑操作在下表中总结,其中
-
¬ 是按位取反,
-
∧ 是按位与,
-
∨ 是按位或,
-
⊕ 是按位异或,
-
s 是与正在更新的颜色附件对应的片段输出的片段的 Rs0, Gs0, Bs0 或 As0 分量值,以及
-
d 是颜色附件的 R, G, B 或 A 分量值
模式 | 操作 |
---|---|
|
0 |
|
s ∧ d |
|
s ∧ ¬ d |
|
s |
|
¬ s ∧ d |
|
d |
|
s ⊕ d |
|
s ∨ d |
|
¬ (s ∨ d) |
|
¬ (s ⊕ d) |
|
¬ d |
|
s ∨ ¬ d |
|
¬ s |
|
¬ s ∨ d |
|
¬ (s ∧ d) |
|
全部为 1 |
然后,逻辑操作的结果根据组件写入掩码写入颜色附件,如混合操作中所述。
要动态设置是否启用逻辑操作,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetLogicOpEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 logicOpEnable);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
logicOpEnable
指定是否启用逻辑操作。
当使用着色器对象进行绘制,或者当使用在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT
创建图形管线时,此命令设置后续绘制命令是否启用逻辑操作。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendStateCreateInfo::logicOpEnable
值指定。
要动态设置应用于混合状态的逻辑操作,请调用
// Provided by VK_EXT_extended_dynamic_state2, VK_EXT_shader_object
void vkCmdSetLogicOpEXT(
VkCommandBuffer commandBuffer,
VkLogicOp logicOp);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
logicOp
指定应用于混合状态的逻辑操作。
当使用着色器对象进行绘制,或者当使用在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LOGIC_OP_EXT
创建图形管线时,此命令设置后续绘制命令的混合状态的逻辑操作。否则,此状态由用于创建当前活动管线的 VkPipelineColorBlendStateCreateInfo::logicOp
值指定。
颜色写入掩码
可以在 VkPipelineColorBlendAttachmentState::colorWriteMask
中设置的位,确定最终的颜色值 R, G, B 和 A 是否写入帧缓冲区附件,是
// Provided by VK_VERSION_1_0
typedef enum VkColorComponentFlagBits {
VK_COLOR_COMPONENT_R_BIT = 0x00000001,
VK_COLOR_COMPONENT_G_BIT = 0x00000002,
VK_COLOR_COMPONENT_B_BIT = 0x00000004,
VK_COLOR_COMPONENT_A_BIT = 0x00000008,
} VkColorComponentFlagBits;
-
VK_COLOR_COMPONENT_R_BIT
指定将 R 值写入相应样本的颜色附件。否则,内存中的值不会被修改。 -
VK_COLOR_COMPONENT_G_BIT
指定将 G 值写入相应样本的颜色附件。否则,内存中的值不会被修改。 -
VK_COLOR_COMPONENT_B_BIT
指定将 B 值写入相应样本的颜色附件。否则,内存中的值不会被修改。 -
VK_COLOR_COMPONENT_A_BIT
指定将 A 值写入相应样本的颜色附件。否则,内存中的值不会被修改。
无论是否启用混合,都会应用颜色写入掩码操作。
只有在为相应附件启用了颜色写入启用时,才会应用颜色写入掩码操作。否则,颜色写入掩码将被忽略,并且对附件所有分量的写入都将被禁用。
// Provided by VK_VERSION_1_0
typedef VkFlags VkColorComponentFlags;
VkColorComponentFlags
是一种位掩码类型,用于设置零个或多个 VkColorComponentFlagBits 的掩码。
颜色写入启用
VkPipelineColorWriteCreateInfoEXT
结构的定义如下
// Provided by VK_EXT_color_write_enable
typedef struct VkPipelineColorWriteCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t attachmentCount;
const VkBool32* pColorWriteEnables;
} VkPipelineColorWriteCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
为NULL
或指向扩展此结构的结构的指针。 -
attachmentCount
是pColorWriteEnables
中VkBool32
元素的数量。 -
pColorWriteEnables
是指向每个目标附件的布尔值数组的指针,该数组指定是否为给定的附件启用颜色写入。
当此结构体包含在 VkPipelineColorBlendStateCreateInfo 的 pNext
链中时,它定义了每个附件的颜色写入状态。如果此结构体未包含在 pNext
链中,则等效于指定此结构体的 attachmentCount
等于 VkPipelineColorBlendStateCreateInfo 的 attachmentCount
成员,并且 pColorWriteEnables
指向一个包含多个 VK_TRUE
值的数组,其数量与 attachmentCount
成员的值相同。
如果 colorWriteEnable
特性未启用,则 pColorWriteEnables
数组中的所有 VkBool32
元素必须为 VK_TRUE
。
颜色写入启用与 颜色写入掩码 的交互方式如下
-
如果
colorWriteEnable
为VK_TRUE
,则对附件的写入由colorWriteMask
决定。 -
如果
colorWriteEnable
为VK_FALSE
,则忽略colorWriteMask
,并且禁用对附件所有组件的写入。这等效于指定colorWriteMask
为 0。
要动态启用或禁用对颜色附件的写入,请调用
// Provided by VK_EXT_color_write_enable
void vkCmdSetColorWriteEnableEXT(
VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkBool32* pColorWriteEnables);
-
commandBuffer
是将要记录命令的命令缓冲区。 -
attachmentCount
是pColorWriteEnables
中VkBool32
元素的数量。 -
pColorWriteEnables
是指向每个目标附件的布尔值数组的指针,该数组指定是否为给定的附件启用颜色写入。
当使用着色器对象进行绘制时,或当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT
时,此命令会设置后续绘制命令的颜色写入启用状态。 否则,此状态由用于创建当前活动管线的 VkPipelineColorWriteCreateInfoEXT::pColorWriteEnables
值指定。
帧缓冲区查询指令
要从帧缓冲区中的附件查询瓦片属性,请调用
// Provided by VK_QCOM_tile_properties
VkResult vkGetFramebufferTilePropertiesQCOM(
VkDevice device,
VkFramebuffer framebuffer,
uint32_t* pPropertiesCount,
VkTilePropertiesQCOM* pProperties);
-
device
是与帧缓冲区关联的逻辑设备。 -
framebuffer
是要查询的帧缓冲区的句柄。 -
pPropertiesCount
是一个指向整数的指针,该整数与可用或查询的瓦片属性数量相关,如下所述。 -
pProperties
是NULL
或指向 VkTilePropertiesQCOM 结构体数组的指针。
如果 pProperties
为 NULL
,则可用的瓦片属性数量将在 pPropertiesCount
中返回。否则,pPropertiesCount
必须指向一个由应用程序设置为 pProperties
数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties
的属性数量覆盖。如果 pPropertiesCount
小于可用的瓦片属性数量,则最多写入 pPropertiesCount
个结构,并且返回 VK_INCOMPLETE
而不是 VK_SUCCESS
,以指示并非返回了所有可用的属性。
可用瓦片属性的数量由合并子通路的数量决定,每个瓦片属性与一个合并的子通路关联。属性数量最多与渲染通道内的子通路数量相同。要获取给定合并子通路的瓦片属性,可以使用 VkRenderPassSubpassFeedbackInfoEXT 中提供的 postMergeIndex
值对 pProperties
数组进行索引。