不透明度マスクの概要
このトピックでは、ビットマップとブラシを使用して不透明度マスクを定義する方法について説明します。 以下のセクションが含まれます。
- 必要条件
- 不透明度マスクとは
- FillOpacityMask メソッドでビットマップを不透明度マスクとして使用する
- FillGeometry メソッドでブラシを不透明度マスクとして使用する
- レイヤーに不透明度マスクを適用する
- 関連トピック
前提条件
この概要では、「単純な Direct2D アプリケーションを作成する」のチュートリアルで説明されているように、基本的 な Direct2D 描画操作について理解していることを前提としています。 「ブラシの概要」で説明されているように、さまざまな種類のブラシについても理解 しておく必要があります。
不透明度マスクとは
不透明度マスクは、ブラシまたはビットマップによって記述されるマスクであり、そのオブジェクトを部分的または完全に透明にするために別のオブジェクトに適用されます。 不透明度マスクでは、アルファ チャネル情報を使用して、オブジェクトのソース ピクセルを最終的なターゲットにブレンドする方法を指定します。 マスクの透明部分は、基になるイメージが非表示になっている領域を示し、マスクの不透明な部分はマスクされたオブジェクトが表示される場所を示します。
不透明度マスクを適用するには、いくつかの方法があります。
- ID2D1RenderTarget::FillOpacityMask メソッドを使用します。 FillOpacityMask メソッドは、レンダー ターゲットの四角形領域を描画し、ビットマップによって定義された不透明度マスクを適用します。 不透明度マスクがビットマップであり、四角形の領域を塗りつぶす場合は、このメソッドを使用します。
- ID2D1RenderTarget::FillGeometry メソッドを使用します。 FillGeometry メソッドは、指定した ID2D1BitmapBrush を使用してジオメトリの内部を塗りつぶし、ブラシで定義された不透明度マスクを適用します。 このメソッドは、不透明度マスクをジオメトリに適用する場合、またはブラシを不透明度マスクとして使用する場合に使用します。
- ID2D1Layer を使用して不透明度マスクを適用します。 この方法は、単一の図形や画像だけでなく、描画コンテンツのグループに不透明度マスクを適用する場合に使用します。 詳細については、「 レイヤーの概要」を参照してください。
FillOpacityMask メソッドでビットマップを不透明度マスクとして使用する
FillOpacityMask メソッドは、レンダー ターゲットの四角形領域を描画し、ID2D1Bitmap で定義された不透明度マスクを適用します。 四角形領域の不透明度マスクとして使用するビットマップがある場合は、このメソッドを使用します。
次の図は、シダ植物の画像を含む ID2D1BitmapBrush に不透明度マスク (花の画像を含む ID2D1Bitmap) を適用する効果を示しています。 結果の画像は、花の形にクリップされた植物のビットマップです。
これを実現する方法を次のコード例に示します。
最初の例では、ビットマップ マスクとして使用するために、 次のビットマップ (m_pBitmapMask) を読み込みます。 次の図は、生成される出力を示しています。 ビットマップの不透明な部分は黒で表示されますが、ビットマップ内の色情報は不透明度マスクには影響しません。ビットマップ内の各ピクセルの不透明度情報のみが使用されます。 このビットマップ内の完全に不透明なピクセルは、説明のみを目的として黒に色付けされています。
この例では、 ID2D1Bitmap は、サンプルの他の場所で定義されているヘルパー メソッド LoadResourceBitmap によって読み込まれます。
if (SUCCEEDED(hr))
{
hr = LoadResourceBitmap(
m_pRenderTarget,
m_pWICFactory,
L"BitmapMask",
L"Image",
&m_pBitmapMask
);
}
次の例では、不透明度マスクを適用するブラシ m_pFernBitmapBrushを定義します。 この例では、シダの画像を含む ID2D1BitmapBrush を使用しますが、代わりに 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) を指定する必要があります。 これら 3 つの型の意味については、「 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 を塗りつぶすときに必要に応じてブラシを不透明度マスクとして指定できます。 これにより、グラデーション (ID2D1LinearGradientBrush または ID2D1RadialGradientBrush を使用) とビットマップ (ID2D1Bitmap を使用) から不透明度マスクを作成できます。
FillGeometry メソッドは、次の 3 つのパラメーターを受け取ります。
- 最初のパラメーター ID2D1Geometry は、描画する図形を定義します。
- 2 番目のパラメーター ID2D1Brush は、ジオメトリの描画に使用するブラシを指定します。 このパラメーターは、x および y 拡張モードが D2D1_EXTEND_MODE_CLAMP に設定されている ID2D1BitmapBrush である必要があります。
- 3 番目のパラメーター ID2D1Brush は、不透明度マスクとして使用するブラシを指定します。 このブラシには、 ID2D1LinearGradientBrush、 ID2D1RadialGradientBrush、または ID2D1BitmapBrush を指定できます。 (技術的には、 ID2D1SolidColorBrush を使用できますが、不透明度マスクとして純色ブラシを使用しても興味深い結果は得られません)。
次のセクションでは、 ID2D1LinearGradientBrush オブジェクトと ID2D1RadialGradientBrush オブジェクトを不透明度マスクとして使用する方法について説明します。
不透明度マスクとして線形グラデーション ブラシを使用する
次の図は、花のビットマップで塗りつぶされた四角形に線形グラデーション ブラシを適用する効果を示しています。
次の手順では、この効果を再作成する方法について説明します。
マスクするコンテンツを定義します。 次の例では、 ID2D1BitmapBrushm_pLinearFadeFlowersBitmapを作成します。 m_pLinearFadeFlowersBitmapの拡張モード x と y- は、FillGeometry メソッドで不透明度マスクと共に使用できるように、D2D1_EXTEND_MODE_CLAMPに設定されます。
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 (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;
}
レイヤーの使用の詳細については、「レイヤーの 概要」を参照してください。
関連トピック