共用方式為


不透明度遮罩概觀

本主題描述如何使用點陣圖和筆刷來定義不透明度遮罩。 包含以下幾節。

必要條件

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

什麼是不透明度遮罩?

不透明度遮罩是由筆刷或點陣圖所描述的遮罩,會套用至另一個物件,讓該物件部分或完全透明。 不透明度遮罩會使用 Alpha 色板資訊來指定物件的來源圖元如何混合到最終目的地目標。 遮罩的透明部分表示隱藏基礎影像的區域,而遮罩的不透明部分則表示遮罩物件可見的位置。

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

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

搭配 FillOpacityMask 方法使用點陣圖作為不透明度遮罩

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

下圖顯示將不透明度遮罩套用 (ID2D1Bitmap 的效果,其中包含花) 的影像套用至 ID2D1BitmapBrush ,其影像為 fern 植物。 產生的影像是裁剪至花形的植物點陣圖。

在植物圖片上做為不透明度遮罩的花狀點陣圖圖表

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

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

花狀點陣圖遮罩的圖例

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

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

下一個範例會定義套用不透明度遮罩的筆刷 m_pFernBitmapBrush。 此範例使用 ID2D1BitmapBrush ,其中包含 fern 的影像,但您可以改用 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。 請參閱 ID2D1DeviceCoNtext::FillOpacityMask 方法,這個方法沒有 D2D1_OPACITY_MASK_CONTENT 參數。

 

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

套用不透明度遮罩的 Fern 植物圖片圖例

        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 方法使用 Brush 作為不透明度遮罩

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

FillGeometry方法採用三個參數:

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

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

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

套用線性漸層筆刷的花形圖圖

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

  1. 定義要遮罩的內容。 下列範例會建立 ID2D1BitmapBrushm_pLinearFadeFlowersBitmap。 適用于 m_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方法將ID2D1RectangleGeometry 填入 ID2D1RectangleGeometry (m_pRectGeo) ID2D1BitmapBrush (m_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();
            }

最後的程式碼範例會使用ID2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) 和不透明度遮罩 (m_pRadialGradientBrush) 填滿ID2D1RectangleGeometry (m_pRectGeo)

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

此範例中已省略程式碼。

將不透明度遮罩套用至圖層

當您呼叫 PushLayerID2D1Layer 推送至轉譯目標時,您可以使用 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;
    
}

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

筆刷概觀

圖層概觀