共用方式為


不透明度遮罩概觀

本主題描述如何使用位圖和筆刷來定義不透明度遮罩。 其中包含下列各節。

先決條件

本概觀假設您已熟悉基本的 Direct2D 繪圖作業,如 建立簡單的 Direct2D 應用程式 逐步解說中所述。 您也應該熟悉不同類型的筆刷,如 筆刷概觀中所述。

什麼是不透明度遮罩?

不透明度遮罩是一種由筆刷或點陣圖描述的遮罩,應用於其他物件以使該物件呈現部分或完全透明。 不透明度遮罩使用 alpha 通道資訊來指定物件來源圖元如何混合到最終的目的地目標。 遮罩的透明部分表示隱藏基礎影像的區域,而遮罩的不透明部分則表示遮罩物件的可見位置。

有數種方式可以套用不透明度遮罩:

  • 使用 ID2D1RenderTarget::FillOpacityMask 方法。 FillOpacityMask 方法會繪製轉譯目標的矩形區域,然後套用位圖所定義的不透明度遮罩。 當您不透明度遮罩是點陣圖,而且您想要填滿矩形區域時,請使用此方法。
  • 使用 ID2D1RenderTarget::FillGeometry 方法。 FillGeometry 方法會使用指定的 ID2D1BitmapBrush繪製幾何內部,然後套用由筆刷定義的不透明度遮罩。 當您想要將不透明度遮罩套用至幾何,或想要使用筆刷做為不透明度遮罩時,請使用此方法。
  • 使用 ID2D1Layer 來套用不透明度遮罩。 當您想要將不透明度遮罩套用至繪圖內容群組,而不只是單一圖形或影像時,請使用此方法。 如需詳細資訊,請參閱 層概觀

使用 FillOpacityMask 方法將位圖作為透明度遮罩

FillOpacityMask 方法會繪製渲染目標的矩形區域,然後套用由 ID2D1Bitmap定義的不透明度遮罩。 當您有需要使用位圖作為矩形區域的不透明度遮罩時,請使用這個方法。

下圖顯示將不透明度遮罩(ID2D1Bitmap,附帶花的影像)套用至一個包含蕨類植物影像的 ID2D1BitmapBrush 所產生的效果。 產生的影像是裁剪至花卉圖形之植物的點陣圖。

用作蕨類植物圖片上的不透明遮罩的花卉位圖圖像

下列程式代碼範例示範如何完成此作業。

第一個範例會載入下列點陣圖,m_pBitmapMask,以做為位圖遮罩。 下圖顯示產生的輸出。 請注意,雖然點陣圖的不透明部分顯示為黑色,但點陣圖中的色彩資訊對不透明度遮罩沒有影響;只會使用位圖中每個圖元的不透明度資訊。 此點陣圖中完全不透明的圖元已以黑色標示,僅供說明之用。

花位圖遮罩的圖例

在此範例中,ID2D1Bitmap 是由範例中其他地方定義的協助程式方法 LoadResourceBitmap 載入。

            if (SUCCEEDED(hr))
            {
                hr = LoadResourceBitmap(
                    m_pRenderTarget,
                    m_pWICFactory,
                    L"BitmapMask",
                    L"Image",
                    &m_pBitmapMask
                    );
            }

下一個範例定義了透明度遮罩所套用的筆刷 m_pFernBitmapBrush。 此範例使用包含蕨類植物影像的 ID2D1BitmapBrush,但您可以改用 ID2D1SolidColorBrushID2D1LinearGradientBrushID2D1RadialGradientBrush。 下圖顯示產生的輸出。

位圖筆刷所使用的點陣圖 圖例

            if (SUCCEEDED(hr))
            {
                D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                    D2D1::BitmapBrushProperties(
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                    );
                hr = m_pRenderTarget->CreateBitmapBrush(
                    m_pFernBitmap,
                    propertiesXClampYClamp,
                    &m_pFernBitmapBrush
                    );


            }

現在已定義不透明度遮罩和筆刷,您可以在應用程式的轉譯方法中使用 FillOpacityMask 方法。 當您呼叫 FillOpacityMask 方法時,您必須指定所使用的不透明度遮罩類型:D2D1_OPACITY_MASK_CONTENT_GRAPHICSD2D1_OPACITY_MASK_CONTENT_TEXT_NATURALD2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE。 如需這三種類型的意義,請參閱 D2D1_OPACITY_MASK_CONTENT

注意

從 Windows 8 開始,不需要 D2D1_OPACITY_MASK_CONTENT。 請參閱沒有 D2D1_OPACITY_MASK_CONTENT 參數的 ID2D1DeviceContext::FillOpacityMask 方法。

 

下一個範例會將轉譯目標的反鋸齒模式設定為 D2D1_ANTIALIAS_MODE_ALIASED,以確保不透明度遮罩能正常運作。 然後它會呼叫 FillOpacityMask 方法,並將不透明度遮罩(m_pBitmapMask)、套用不透明度遮罩的筆刷(m_pFernBitmapBrush)、不透明度遮罩(D2D1_OPACITY_MASK_CONTENT_GRAPHICS)內的內容類型,以及要繪製的區域傳遞給它。 下圖顯示產生的輸出。

套用不透明度遮罩的蕨類植物插圖

        D2D1_RECT_F rcBrushRect = D2D1::RectF(5, 5, 155, 155);


        // D2D1_ANTIALIAS_MODE_ALIASED must be set for FillOpacityMask to function properly
        m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
        m_pRenderTarget->FillOpacityMask(
            m_pBitmapMask,
            m_pFernBitmapBrush,
            D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
            &rcBrushRect
            );
        m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);

此範例已省略程序代碼。

使用 FillGeometry 方法將筆刷作為透明度遮罩

上一節說明如何使用 ID2D1Bitmap 作為不透明度遮罩。 Direct2D 也提供 ID2D1RenderTarget::FillGeometry 方法,可讓您在填滿 ID2D1Geometry時選擇性地指定筆刷作為不透明度遮罩。 這可讓您從漸層建立不透明度遮罩(使用 ID2D1LinearGradientBrushID2D1RadialGradientBrush) 和位圖 (使用 ID2D1Bitmap)。

FillGeometry 方法會採用三個參數:

下列各節說明如何使用 ID2D1LinearGradientBrushID2D1RadialGradientBrush 對象作為不透明度遮罩。

使用線性漸層筆刷作為不透明度遮罩

下圖顯示將線性漸層筆刷套用至填滿花卉位圖的矩形的效果。

套用線性漸層筆刷的花位圖圖表

後續步驟說明如何重新建立此效果。

  1. 定義要遮罩的內容。 下列範例建立了 ID2D1BitmapBrush,以及 m_pLinearFadeFlowersBitmapm_pLinearFadeFlowersBitmap 的擴充模式 x 和 y- 設定為 D2D1_EXTEND_MODE_CLAMP,以便可以使用不透明度遮罩與 FillGeometry 方法搭配。

    if (SUCCEEDED(hr))
    {
        // Create the bitmap to be used by the bitmap brush.
        hr = LoadResourceBitmap(
            m_pRenderTarget,
            m_pWICFactory,
            L"LinearFadeFlowers",
            L"Image",
            &m_pLinearFadeFlowersBitmap
            );
    }
    
    if (SUCCEEDED(hr))
        {
            D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                D2D1::BitmapBrushProperties(
                D2D1_EXTEND_MODE_CLAMP,
                D2D1_EXTEND_MODE_CLAMP,
                D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                );
    
    C++
                    if (SUCCEEDED(hr))
                    {
                        hr = m_pRenderTarget->CreateBitmapBrush(
                            m_pLinearFadeFlowersBitmap,
                            propertiesXClampYClamp,
                            &m_pLinearFadeFlowersBitmapBrush
                            );
                    }
    C++
                }
  2. 定義不透明度遮罩。 下一個程式代碼範例會建立一個對角線的線性漸層筆刷(m_pLinearGradientBrush),其效果是從位置 0 的完全不透明黑色逐漸變為位置 1 的完全透明白色。

                if (SUCCEEDED(hr))
                {
                    ID2D1GradientStopCollection *pGradientStops = NULL;

                    static const D2D1_GRADIENT_STOP gradientStops[] =
                    {
                        {   0.f,  D2D1::ColorF(D2D1::ColorF::Black, 1.0f)  },
                        {   1.f,  D2D1::ColorF(D2D1::ColorF::White, 0.0f)  },
                    };

                    hr = m_pRenderTarget->CreateGradientStopCollection(
                        gradientStops,
                        2,
                        &pGradientStops);


                    if (SUCCEEDED(hr))
                    {
                        hr = m_pRenderTarget->CreateLinearGradientBrush(
                            D2D1::LinearGradientBrushProperties(
                                D2D1::Point2F(0, 0),
                                D2D1::Point2F(150, 150)),
                            pGradientStops,
                            &m_pLinearGradientBrush);
                    }

    
                pGradientStops->Release();
                }
  1. 使用 FillGeometry 方法。 最後一個範例會使用 FillGeometry 方法將內容筆刷填滿 ID2D1RectangleGeometrym_pRectGeo) 與 ID2D1BitmapBrushm_pLinearFadeFlowersBitmap) 並套用不透明度遮罩 (m_pLinearGradientBrush)。
            m_pRenderTarget->FillGeometry(
                m_pRectGeo, 
                m_pLinearFadeFlowersBitmapBrush, 
                m_pLinearGradientBrush
                );

此範例已省略程序代碼。

使用放射漸層筆刷作為不透明度遮罩

下圖顯示將放射狀漸層筆刷套用至填滿樹葉位圖的矩形後的視覺效果。

套用放射漸層筆刷的樹葉位圖

第一個範例會建立 ID2D1BitmapBrushm_pRadialFadeFlowersBitmapBrush。 因此,FillGeometry 方法可將它與不透明度遮罩搭配使用,m_pRadialFadeFlowersBitmapBrush 的擴充模式 x 和 y- 會設定為 D2D1_EXTEND_MODE_CLAMP

            if (SUCCEEDED(hr))
            {
                // Create the bitmap to be used by the bitmap brush.
                hr = LoadResourceBitmap(
                    m_pRenderTarget,
                    m_pWICFactory,
                    L"RadialFadeFlowers",
                    L"Image",
                    &m_pRadialFadeFlowersBitmap
                    );
            }


            if (SUCCEEDED(hr))
            {
                D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                    D2D1::BitmapBrushProperties(
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                    );
C++
                if (SUCCEEDED(hr))
                {
                    hr = m_pRenderTarget->CreateBitmapBrush(
                        m_pLinearFadeFlowersBitmap,
                        propertiesXClampYClamp,
                        &m_pLinearFadeFlowersBitmapBrush
                        );
                }
C++
            }

下一個範例會定義將用作不透明度遮罩的放射狀漸層筆刷。

            if (SUCCEEDED(hr))
            {
                ID2D1GradientStopCollection *pGradientStops = NULL;

                static const D2D1_GRADIENT_STOP gradientStops[] =
                {
                    {   0.f,  D2D1::ColorF(D2D1::ColorF::Black, 1.0f)  },
                    {   1.f,  D2D1::ColorF(D2D1::ColorF::White, 0.0f)  },
                };

                hr = m_pRenderTarget->CreateGradientStopCollection(
                    gradientStops,
                    2,
                    &pGradientStops);




                if (SUCCEEDED(hr))
                {
                    hr = m_pRenderTarget->CreateRadialGradientBrush(
                        D2D1::RadialGradientBrushProperties(
                            D2D1::Point2F(75, 75),
                            D2D1::Point2F(0, 0),
                            75,
                            75),
                        pGradientStops,
                        &m_pRadialGradientBrush);
                }
                pGradientStops->Release();
            }

最終的程式代碼範例會使用 ID2D1BitmapBrushm_pRadialFadeFlowersBitmapBrush) 和不透明度遮罩 (m_pRadialGradientBrush) 來填滿 ID2D1RectangleGeometrym_pRectGeo)。

        m_pRenderTarget->FillGeometry(
            m_pRectGeo,
            m_pRadialFadeFlowersBitmapBrush, 
            m_pRadialGradientBrush
            );

此範例已省略程序代碼。

將透明遮罩套用到圖層

當您呼叫 PushLayer,將 ID2D1Layer 推送至渲染目標時,您可以使用 D2D1_LAYER_PARAMETERS 結構將筆刷套用為不透明度遮罩。 下列程式代碼範例使用 ID2D1RadialGradientBrush 作為不透明度遮罩。

HRESULT DemoApp::RenderWithLayerWithOpacityMask(ID2D1RenderTarget *pRT)
{   

    HRESULT hr = S_OK;

    // Create a layer.
    ID2D1Layer *pLayer = NULL;
    hr = pRT->CreateLayer(NULL, &pLayer);

    if (SUCCEEDED(hr))
    {
        pRT->SetTransform(D2D1::Matrix3x2F::Translation(300, 250));

        // Push the layer with the content bounds.
        pRT->PushLayer(
            D2D1::LayerParameters(
                D2D1::InfiniteRect(),
                NULL,
                D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
                D2D1::IdentityMatrix(),
                1.0,
                m_pRadialGradientBrush,
                D2D1_LAYER_OPTIONS_NONE),
            pLayer
            );

        pRT->DrawBitmap(m_pBambooBitmap, D2D1::RectF(0, 0, 190, 127));

        pRT->FillRectangle(
            D2D1::RectF(25.f, 25.f, 50.f, 50.f), 
            m_pSolidColorBrush
            );
        pRT->FillRectangle(
            D2D1::RectF(50.f, 50.f, 75.f, 75.f),
            m_pSolidColorBrush
            ); 
        pRT->FillRectangle(
            D2D1::RectF(75.f, 75.f, 100.f, 100.f),
            m_pSolidColorBrush
            );    
 
        pRT->PopLayer();
    }
    SafeRelease(&pLayer);
   
    return hr;
    
}

如需使用層次的詳細資訊,請參閱 層概觀

筆刷概觀

層概觀