1.D2D1_ALPHA_MODE_PREMULTIPLIED 含义

D2D1_ALPHA_MODE_PREMULTIPLIED 是 Direct2D 中定义的一种 Alpha 模式,用于描述像素颜色值和其 Alpha 通道(透明度)之间的关系。

在非预乘 Alpha (Straight or Unpremultiplied Alpha) 图像中,每个颜色分量(红、绿、蓝)是独立于 Alpha 值的。而在预乘 Alpha 图像中,每个颜色分量已经被其对应的 Alpha 通道所乘过了。这意味着,如果一个像素的 Alpha 值不是100%(即不完全不透明),那么它的颜色值也会被相应的淡化。

例如,在预乘 Alpha 的图像中,一个半透明的红色像素(Alpha = 0.5)的颜色值已经进行了 Alpha 混合处理,实际存储的是半强度的红色而不是全强度的红色。

使用 D2D1_ALPHA_MODE_PREMULTIPLIED 作为呈现目标或纹理的 Alpha 模式时,Direct2D 在进行绘制和混合操作时会假设输入的颜色数据已经是预乘的,并据此进行正确的透明度计算。这种模式有助于减少在执行多次透明度叠加时出现的颜色失真现象,尤其是在图形管线中有多层透明内容需要正确融合时。

2.Direct3D10中预乘设置

在Direct3D 10中处理透明度预乘主要涉及到纹理的格式选择和渲染状态的设置。以下是如何正确设置以实现Alpha预乘:

  1. 纹理格式选择

    • 如果要使用预乘Alpha,确保你的纹理包含预乘过的颜色值,通常选用支持预乘Alpha的纹理格式如 DXGI_FORMAT_B8G8R8A8_UNORM_SRGBDXGI_FORMAT_B8G8R8A8_UNORM 并且在加载或创建时已经进行了预乘。
  2. 像素着色器输出

    • 在像素着色器中,如果你从非预乘纹理采样并希望硬件执行预乘混合,你需要手动将每个颜色通道与Alpha通道相乘后输出到输出合并阶段(OM)。
  3. 渲染状态设置

    • 对于预乘Alpha的纹理,不需要特殊的混合模式,因为颜色值本身就是预乘后的结果,可以直接进行常规的混合操作。
    • 确保blend state不是针对非预乘Alpha设计的。对于预乘Alpha,通常会设置 blend state 的源因子为 (SrcAlpha, One)(One, SrcAlpha) 来利用预乘的颜色信息。
  4. 创建Blend State对象

    • 使用 ID3D10Device::CreateBlendState 方法创建一个blend state对象,设置其描述符(D3D10_BLEND_DESC)中的 SrcBlendDestBlend 成分来匹配预乘Alpha所需的混合模式。

例如,若要设置预乘Alpha的blend state,可以这样做:

D3D10_BLEND_DESC blendDesc;
ZeroMemory(&blendDesc, sizeof(blendDesc));
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE;
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend = D3D10_BLEND_ONE; // 源颜色使用预乘Alpha,即自身
blendDesc.RenderTarget[0].DestBlend = D3D10_BLEND_INV_SRC_ALPHA; // 目标颜色使用源颜色Alpha的反向值
blendDesc.RenderTarget[0].BlendOp = D3D10_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D10_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D10_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D10_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D10_COLOR_WRITE_ENABLE_ALL;

// 创建Blend State对象
ID3D10BlendState* pBlendState;
HRESULT hr = m_pDevice->CreateBlendState(&blendDesc, &pBlendState);
if (SUCCEEDED(hr))
{
    // 设置当前blend状态
    m_pDevice->OMSetBlendState(pBlendState, 0, 0xffffffff);
}

在绘制带预乘Alpha的纹理时,应用上述设置,并确保所有的颜色数据都已正确地进行了预乘计算。

3.清除背景颜色

在Direct2D中,您可以创建一个完全透明的背景来绘制对象。这通常是通过设置渲染目标(RenderTarget)的背景色或者清除渲染目标时指定完全透明的颜色来实现的。

  1. 设置背景色
    如果您是在窗口或位图上进行绘制,并希望其背景为全透明,首先确保您的渲染目标支持透明度,例如使用DXGI_FORMAT_B8G8R8A8_UNORM格式。然后,不需特别去“设置”背景色为透明,而是应当避免填充背景色,因为默认情况下未绘制区域就是透明的。

  2. 清除渲染目标
    若要清空整个渲染目标到透明状态,可以调用ID2D1RenderTarget::Clear()方法,并传入一个包含透明度值的颜色结构。比如,如果你使用的是包含Alpha通道的颜色结构(如D2D1_COLOR_F),则可以这样设置:

D2D1_COLOR_F clearColor = D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f); // RGBA,其中A=0表示全透明
d2dRenderTarget->Clear(clearColor);
  1. 窗口透明
    对于窗口级别的透明,还需要启用Windows Aero主题并且利用Desktop Window Manager (DWM) 的效果,可以通过启用DWM的透明效果来实现窗口内容的透明,同时 Direct2D 内容也会正确显示其透明度。

  2. 层叠顺序与混合模式
    要使Direct2D绘制的对象具有透明效果,不仅仅是背景透明,还涉及到绘制顺序以及绘制过程中使用的混合模式。通常,Direct2D会按照后绘制的内容覆盖前面内容的原则处理透明度,因此要确保正确的绘制顺序以实现预期的透明叠加效果。

总结起来,在Direct2D中绘制对象时,可以直接或间接地让背景保持透明,并且可以灵活控制每个绘制对象自身的透明度。

01-25 09:08