不透明度遮罩概觀
本主題描述如何使用點陣圖和筆刷來定義不透明度遮罩。 包含以下幾節。
- 先決條件
- 什麼是不透明度遮罩?
- 搭配 FillOpacityMask 方法使用點陣圖作為不透明度遮罩
- 搭配 FillGeometry 方法使用 Brush 作為不透明度遮罩
- 將不透明度遮罩套用至圖層
- 相關主題
必要條件
本概觀假設您已熟悉基本的 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 的影像,但您可以改用 ID2D1SolidColorBrush、 ID2D1LinearGradientBrush或 ID2D1RadialGradientBrush 。 下圖顯示產生的輸出。
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_GRAPHICS、 D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL和 D2D1_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) ,以及繪製的區域。 下圖顯示產生的輸出。
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時選擇性地將筆刷指定為不透明度遮罩。 這可讓您使用 ID2D1LinearGradientBrush 或 ID2D1RadialGradientBrus) h 從漸層 (建立不透明度遮罩,並使用 ID2D1Bitmap) 建立點陣圖 (。
FillGeometry方法採用三個參數:
- 第一個參數 ID2D1Geometry會定義要繪製的圖形。
- 第二個參數 ID2D1Brush會指定用來繪製幾何的筆刷。 此參數必須是 ID2D1BitmapBrush ,其 x 和 y 擴充模式設定為 D2D1_EXTEND_MODE_CLAMP。
- 第三個參數 ID2D1Brush會指定要作為不透明度遮罩的筆刷。 此筆刷可能是 ID2D1LinearGradientBrush、 ID2D1RadialGradientBrush或 ID2D1BitmapBrush。 (技術上,您可以使用 ID2D1SolidColorBrush,但使用純色筆刷作為不透明度遮罩不會產生有趣的結果。)
下列各節說明如何使用 ID2D1LinearGradientBrush 和 ID2D1RadialGradientBrush 物件作為不透明度遮罩。
使用線性漸層筆刷作為不透明度遮罩
下圖顯示將線性漸層筆刷套用至填滿花形圖的矩形的效果。
後續步驟說明如何重新建立此效果。
定義要遮罩的內容。 下列範例會建立 ID2D1BitmapBrush, m_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++ }
定義不透明度遮罩。 下一個程式碼範例會建立對角線線性漸層筆刷 (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();
}
- 使用 FillGeometry 方法。 最後一個範例會使用FillGeometry方法將ID2D1RectangleGeometry 填入 ID2D1RectangleGeometry (m_pRectGeo) ID2D1BitmapBrush (m_pLinearFadeFlowersBitmap) ,並套用不透明度遮罩 (m_pLinearGradientBrush) 。
m_pRenderTarget->FillGeometry(
m_pRectGeo,
m_pLinearFadeFlowersBitmapBrush,
m_pLinearGradientBrush
);
此範例中已省略程式碼。
使用星形漸層筆刷作為不透明度遮罩
下圖顯示將星形漸層筆刷套用至填滿葉形圖的矩形的視覺效果。
第一個範例會建立 ID2D1BitmapBrush, m_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++ |
---|
|
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
);
此範例中已省略程式碼。
將不透明度遮罩套用至圖層
當您呼叫 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;
}
如需使用圖層的詳細資訊,請參閱 圖層概觀。
相關主題