当我们创建管线构建器时,我们完全跳过了混合逻辑,将其设置为不混合。混合用于透明对象和一些图形效果,因此拥有它很重要。因此,我们将使我们在上一篇文章中渲染的矩形透明。
管线中的混合
我们无法真正从着色器控制混合,那是管线的属性。GPU 硬件本身为我们进行混合数学运算,并有许多选项。我们将在管线构建器中添加 2 种新的混合模式,一种是加法混合,它只是添加颜色,另一种是 alpha 混合,它将混合颜色。
让我们将这两个函数添加到管线构建器中
void PipelineBuilder::enable_blending_additive()
{
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
_colorBlendAttachment.blendEnable = VK_TRUE;
_colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
_colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
_colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
_colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
void PipelineBuilder::enable_blending_alphablend()
{
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
_colorBlendAttachment.blendEnable = VK_TRUE;
_colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
_colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
_colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
_colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
_colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
在 Vulkan 中设置混合选项时,我们需要填充颜色和 alpha 的公式。参数在颜色和 alpha 上工作方式相同。公式如下
outColor = srcColor * srcColorBlendFactor <op> dstColor * dstColorBlendFactor;
有一些可能的运算符,但在大多数情况下,我们将使用 VK_BLEND_OP_ADD
,因为它是最基本且保证可以工作的。还有许多其他更高级的运算符,但这些运算符带有扩展,我们不会使用它们。源(来自 srcColor 和混合因子)指的是我们在管线上处理的颜色,目标(dstColor 和混合因子)是我们正在渲染到的图像的当前值。
有了上面的公式,让我们解释一下加法混合的作用。
VK_BLEND_FACTOR_ONE
将混合因子设置为 1.0,因此不进行乘法运算。另一方面,VK_BLEND_FACTOR_SRC_ALPHA
将其乘以源的 alpha 值。我们的混合最终变成这个公式
outColor = srcColor.rgb * srcColor.a + dstColor.rgb * 1.0
alpha 混合的公式将如下所示。
outColor = srcColor.rgb * srcColor.a + dstColor.rgb * (1.0 - srcColor.a)
本质上使其成为由 srcColor alpha 控制的 lerp,这将来自我们的着色器。
让我们尝试使用它来看看它的作用。我们的着色器中没有设置 alpha,所以让我们尝试加法混合。更改 init_mesh_pipeline()
函数上的混合。
//pipelineBuilder.disable_blending();
pipelineBuilder.enable_blending_additive();
现在您应该看到猴子网格是半透明的,让下面的颜色显示出来。尝试使用不同的混合模式,看看它们会产生什么效果。
在我们进入第 4 章之前,让我们实现窗口调整大小。
下一步: 窗口调整大小