配置混合功能

在将输出值写入呈现目标之前,对每个像素着色器输出 (RGBA 值) 执行混合操作。 如果启用了多重采样,则对每个多重采样执行混合;否则,将在每个像素上执行混合。

创建混合状态

混合状态是用于控制混合的状态的集合。 D3D11_BLEND_DESC1 ) 中定义的 这些状态 (用于通过调用 ID3D11Device1::CreateBlendState1 来创建混合状态对象。

例如,下面是一个非常简单的混合状态创建示例,该示例禁用 alpha 混合,不使用每个分量像素掩码。

ID3D11BlendState1* g_pBlendStateNoBlend = NULL;

D3D11_BLEND_DESC1 BlendState;
ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC1));
BlendState.RenderTarget[0].BlendEnable = FALSE;
BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
pd3dDevice->CreateBlendState1(&BlendState, &g_pBlendStateNoBlend);

此示例类似于 HLSLWithoutFX10 示例

绑定混合状态

创建 blend-state 对象后,通过调用 ID3D11DeviceContext::OMSetBlendState 将 blend-state 对象绑定到输出合并阶段。

float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
UINT sampleMask   = 0xffffffff;

pd3dDevice->OMSetBlendState(g_pBlendStateNoBlend, blendFactor, sampleMask);

此 API 采用三个参数:混合状态对象、四分量混合因子和示例掩码。 可以为混合状态对象传入 NULL 以指定默认混合状态或传入混合状态对象。 如果使用 D3D11_BLEND_BLEND_FACTORD3D11_BLEND_INV_BLEND_FACTOR 创建了混合状态对象,则可以传递混合因子来调节像素着色器、呈现目标或两者的值。 如果未使用 D3D11_BLEND_BLEND_FACTORD3D11_BLEND_INV_BLEND_FACTOR创建混合状态对象,仍可以传递非 NULL 混合因子,但混合阶段不使用混合因子;运行时存储混合因子,稍后可以调用 ID3D11DeviceContext::OMGetBlendState 来检索混合因子。 如果传递 NULL,运行时将使用或存储等于 { 1, 1, 1, 1 } 的混合因子。 示例掩码是用户定义的掩码,用于确定在更新现有呈现目标之前如何对其进行采样。 默认采样掩码是0xffffffff用于指定点采样。

在大多数深度缓冲方案中,最接近相机的像素是绘制的像素。 设置深度模具状态时,D3D11_DEPTH_STENCIL_DESCDepthFunc 成员可以是任何D3D11_COMPARISON_FUNC。 通常,你会希望 DepthFuncD3D11_COMPARISON_LESS,以便最靠近相机的像素将覆盖它们后面的像素。 但是,根据应用程序的需求,可以使用任何其他比较函数来执行深度测试。

高级混合主题

Alpha-To-Coverage

Alpha 到覆盖是一种多重采样技术,对于密集的树叶等情况最有用,其中有多个重叠多边形使用 alpha 透明度来定义图面中的边缘。

可以使用 D3D11_BLEND_DESC1D3D11_BLEND_DESCAlphaToCoverageEnable 成员切换运行时是否在给定 n 样本 RenderTarget) 的情况下,将输出寄存器SV_Target 0 的.a 组件 (alpha) 转换为 n 步覆盖掩 (码。 运行时执行此掩码的 AND 操作,除了使用样本掩码) 确定要更新所有活动 RenderTarget中的样本外,基元 (中像素的典型样本覆盖率。

如果像素着色器输出 SV_Coverage,运行时将禁用 alpha-to-coverage。

注意

在多重采样中,运行时仅对所有 RenderTarget共享一个覆盖范围。 当 AlphaToCoverageEnable 为 TRUE 时,运行时读取 .a 并将其从输出SV_Target0 转换为覆盖,这一事实不会更改在 RenderTarget 0 处转到混合器的值 (如果 RenderTarget 恰好设置为) 。 通常,如果启用 alpha-to-coverage,则不会影响像素着色器的所有颜色输出如何通过输出合并阶段RenderTarget交互,只不过运行时使用 alpha 到覆盖掩码对覆盖蒙板执行 AND 操作。 Alpha-to-coverage 独立于运行时是否可以混合 RenderTarget ,或者是否在 RenderTarget 上使用混合。

 

图形硬件没有精确指定如何将像素着色器 SV_Target0.a (alpha) 转换为覆盖掩码,只不过 alpha 为 0 (或更小) 必须映射到无覆盖,1 (或更高) 的 alpha 必须映射到全覆盖 (,然后运行时才能使用实际基元覆盖) 执行 AND 操作。 当 alpha 从 0 到 1 时,生成的覆盖范围通常应单调增加。 但是,硬件可能会执行区域抖动,以提供一些更好的 alpha 值量化,但代价是空间分辨率和噪音。 Alpha 值 NaN (Not a Number) 会导致无覆盖 (零) 掩码。

Alpha 到覆盖率传统上还用于屏幕门透明度或为其他不透明子画面定义详细剪影。

混合像素着色器输出

此功能使输出合并可以同时使用两个像素着色器输出作为混合操作的输入源,与槽 0 处的单个呈现目标进行混合操作。

此示例采用两个结果并将其组合在一个传递中,其中一个结果与乘法混合到目标中,另一个结果与加法混合:

SrcBlend = D3D11_BLEND_ONE;
DestBlend = D3D11_BLEND_SRC1_COLOR;

此示例将第一个像素着色器输出配置为源颜色,将第二个输出配置为按颜色分量混合因子。

SrcBlend = D3D11_BLEND_SRC1_COLOR;
DestBlend = D3D11_BLEND_INV_SRC1_COLOR;

此示例演示混合因子必须与着色器重排匹配的方式:

SrcFactor = D3D11_BLEND_SRC1_ALPHA;
DestFactor = D3D11_BLEND_SRC_COLOR;
OutputWriteMask[0] = .ra; // pseudocode for setting the mask at
                          // RenderTarget slot 0 to .ra

混合因子和着色器代码一起意味着像素着色器至少需要输出 o0.r 和 o1.a。 额外的输出组件可以由着色器输出,但将被忽略,更少的组件将产生未定义的结果。

输出合并器阶段

管道阶段 (Direct3D 10)