ブラシの概要

この概要では、ID2D1SolidColorBrushID2D1LinearGradientBrush、ID2D1RadialGradientBrushID2D1BitmapBrush オブジェクトを作成して使用して、純色、グラデーション、ビットマップで領域を塗りつぶす方法について説明します。 以下のセクションが含まれます。

前提条件

この概要では、「単純な Direct2D アプリケーションを作成する」の説明に従って、基本的な Direct2D アプリケーションの構造を理解していることを前提としています。

ブラシの種類

ブラシは、その出力で領域を "塗りつぶす"。 ブラシが異なれば、出力の種類も異なります。 Direct2D には、4 種類のブラシが用意されています。 ID2D1SolidColorBrush は、単色の領域を塗りつぶします。 ID2D1LinearGradientBrush は線形グラデーション、 ID2D1RadialGradientBrush は放射状グラデーション、 ID2D1BitmapBrush はビットマップで塗りつぶします。

Note

Windows 8以降では、ビットマップ ブラシに似た ID2D1ImageBrush を使用することもできますが、プリミティブも使用できます。

すべてのブラシは ID2D1Brush を継承し、一連の共通機能 (不透明度の設定と取得、ブラシの変換) を共有します。これらは ID2D1RenderTarget によって作成され、デバイスに依存するリソースです。アプリケーションは、ブラシが使用されるレンダー ターゲットを初期化した後にブラシを作成し、レンダー ターゲットを再作成する必要がある場合は常にブラシを再作成する必要があります。 (リソースの詳細については、「リソースの 概要」を参照してください)。

次の図は、さまざまなブラシの種類の例を示しています。

純色ブラシ、線形グラデーション ブラシ、放射状グラデーション ブラシ、ビットマップ ブラシの視覚効果の図

色の基本

ID2D1SolidColorBrush またはグラデーション ブラシで塗りつぶす前に、色を選択する必要があります。 Direct2D では、色は D2D1_COLOR_F 構造体 (実際には Direct3D、 D3DCOLORVALUE によって使用される構造体の新しい名前) で表されます。

Windows 8より前のD2D1_COLOR_Fでは、sRGB エンコードが使用されます。 sRGB エンコードでは、色が赤、緑、青、アルファの 4 つのコンポーネントに分割されます。 各コンポーネントは、浮動小数点値の、通常は 0.0 ~ 1.0 の範囲で表されます。 値が 0.0 の場合はその色がまったく含まれないことを意味し、値が 1.0 の場合はその色が完全に表示されていることを意味します。 アルファ コンポーネントの場合、0.0 は完全に透明な色を表し、1.0 は完全に不透明な色を表します。

Windows 8以降、D2D1_COLOR_Fは scRGB エンコードも受け入れます。 scRGB は のスーパーセットであり、1.0 以上 0.0 未満の色の値を許可します。

色を定義するには、 D2D1_COLOR_F 構造を使用してそのフィールドを自分で初期化するか、 D2D1::ColorF クラスを使用して色を作成できます。 ColorF クラスには、色を定義するためのコンストラクターがいくつか用意されています。 コンストラクターでアルファ値が指定されていない場合、既定値は 1.0 になります。

  • ColorF(Enum, FLOAT) コンストラクターを使用して、定義済みの色とアルファ チャネル値を指定します。 アルファ チャネル値の範囲は 0.0 から 1.0 です。ここで、0.0 は完全に透明な色を表し、1.0 は完全に不透明な色を表します。 次の図は、いくつかの定義済みの色と、16 進数に相当する色を示しています。 定義済みの色の完全な一覧については、 ColorF クラスの Color 定数に関するセクションを参照してください。

    定義済みの色の図

    次の例では、定義済みの色を作成し、それを使用して ID2D1SolidColorBrush の色を指定します。

hr = m_pRenderTarget->CreateSolidColorBrush(
    D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
    &m_pBlackBrush
    );
  • ColorF(FLOAT, FLOAT, FLOAT, FLOAT, FLOAT) コンストラクターを使用して、赤、緑、青、アルファのシーケンスで色を指定します。各要素の値は 0.0 ~ 1.0 です。

    次の例では、色の赤、緑、青、アルファの値を指定します。

    ID2D1SolidColorBrush *pGridBrush = NULL;
    hr = pCompatibleRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0.93f, 0.94f, 0.96f, 1.0f)),
        &pGridBrush
        );
  • 次の例に示すように 、ColorF(UINT32, FLOAT) コンストラクターを使用して、色の 16 進値とアルファ値を指定します。
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );

アルファ モード

ブラシを使用するレンダー ターゲットのアルファ モードに関係なく、 D2D1_COLOR_F 値は常に直線アルファとして解釈されます。

純色ブラシの使用

純色ブラシを作成するには、HRESULT オブジェクトと ID2D1SolidColorBrush オブジェクトを返す ID2D1RenderTarget::CreateSolidColorBrush メソッドを呼び出します。 次の図は、黒い色のブラシでストロークされ、0x9ACD32の色の値を持つ純色のブラシで塗りつぶされた四角形を示しています。

単色のブラシで塗られた正方形のイラスト

次のコードは、黒いカラー ブラシと、色の値が 0x9ACD32 のブラシを作成して使用して、この四角形を塗りつぶして描画する方法を示しています。

    ID2D1SolidColorBrush *m_pBlackBrush;
    ID2D1SolidColorBrush *m_pYellowGreenBrush;
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
        &m_pBlackBrush
        );
}

// Create a solid color brush with its rgb value 0x9ACD32.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );
}
m_pRenderTarget->FillRectangle(&rcBrushRect, m_pYellowGreenBrush);
m_pRenderTarget->DrawRectangle(&rcBrushRect, m_pBlackBrush, 1, NULL);

他のブラシとは異なり、 ID2D1SolidColorBrush の作成は比較的安価な操作です。 パフォーマンスにほとんど影響を与えずにレンダリングするたびに 、ID2D1SolidColorBrush オブジェクトを作成できます。 この方法は、グラデーションまたはビットマップ ブラシにはお勧めしません。

線形グラデーション ブラシの使用

ID2D1LinearGradientBrush は、線 (グラデーション軸) に沿って定義された線形グラデーションで領域を塗りつぶします。 ID2D1GradientStop オブジェクトを使用して、グラデーションの色とそのグラデーション軸に沿った位置を指定します。 グラデーション軸を変更することもできます。これにより、水平方向および垂直方向のグラデーションを作成したり、グラデーションの方向を反転させることができます。 線形グラデーション ブラシを作成するには、 ID2D1RenderTarget::CreateLinearGradientBrush メソッドを呼び出します。

次の図は、"Yellow" と "ForestGreen" という 2 つの定義済みの色を持つ ID2D1LinearGradientBrush で塗りつぶされた四角形を示しています。

黄色と森の緑の線形グラデーションブラシで塗られた正方形のイラスト

前の図に示したグラデーションを作成するには、次の手順を実行します。

  1. 2 つの D2D1_GRADIENT_STOP オブジェクトを宣言します。 各グラデーションの位置は、色と位置を指定します。 0.0 の位置はグラデーションの始まりを示し、1.0 の位置はグラデーションの終わりを示します。

    次のコードでは、2 つのD2D1_GRADIENT_STOP オブジェクトの配列 作成します。 最初のストップは位置 0 の色 "Yellow" を指定し、2 番目のストップは位置 1 の色 "ForestGreen" を指定します。

    // Create an array of gradient stops to put in the gradient stop
    // collection that will be used in the gradient brush.
    ID2D1GradientStopCollection *pGradientStops = NULL;

    D2D1_GRADIENT_STOP gradientStops[2];
    gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
    gradientStops[0].position = 0.0f;
    gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
    gradientStops[1].position = 1.0f;
  1. ID2D1GradientStopCollection を作成します。 次の例では CreateGradientStopCollection を呼び出し、 D2D1_GRADIENT_STOP オブジェクトの配列、グラデーションの停止の数 (2)、 補間のD2D1_GAMMA_2_2 、拡張モード のD2D1_EXTEND_MODE_CLAMP を渡します。
    // Create the ID2D1GradientStopCollection from a previously
    // declared array of D2D1_GRADIENT_STOP structs.
    hr = m_pRenderTarget->CreateGradientStopCollection(
        gradientStops,
        2,
        D2D1_GAMMA_2_2,
        D2D1_EXTEND_MODE_CLAMP,
        &pGradientStops
        );
  1. ID2D1LinearGradientBrush を作成します。 次の例では、 CreateLinearGradientBrush メソッドを呼び出し、始点 (0, 0) と終点 (150, 150) を含む線形グラデーション ブラシ プロパティを渡し、前の手順で作成したグラデーションが停止します。
    // The line that determines the direction of the gradient starts at
    // the upper-left corner of the square and ends at the lower-right corner.

    if (SUCCEEDED(hr))
    {
        hr = m_pRenderTarget->CreateLinearGradientBrush(
            D2D1::LinearGradientBrushProperties(
                D2D1::Point2F(0, 0),
                D2D1::Point2F(150, 150)),
            pGradientStops,
            &m_pLinearGradientBrush
            );
    }
  1. ID2D1LinearGradientBrush を使用します。 次のコード例では、ブラシを使用して四角形を塗りつぶします。
    m_pRenderTarget->FillRectangle(&rcBrushRect, m_pLinearGradientBrush);

グラデーションの分岐点の詳細

D2D1_GRADIENT_STOPは、グラデーション ブラシの基本的な構成要素です。 グラデーションの停止点は、グラデーション軸に沿った色と位置を指定します。 グラデーション位置の値は、0.0 ~ 1.0 の範囲です。 0.0 に近いほど、色はグラデーションの始点に近づくようになります。1.0 に近いほど、色はグラデーションの終点に近づいてきます。

次の図は、グラデーションの分岐点を強調表示しています。 円はグラデーションの位置を示し、破線はグラデーション軸を示します。

軸に沿って 4 つの位置を持つ線形グラデーション ブラシの図

最初のグラデーションの停止位置は、0.0 の位置にある黄色の色を指定します。 2 番目のグラデーションの位置は、0.25 の位置に赤い色を指定します。 グラデーション軸に沿って左から右に、これら 2 つの停止間の色は徐々に黄色から赤に変わります。 3 番目のグラデーションの位置は、0.75 の位置に青い色を指定します。 2 番目と 3 番目のグラデーションの間の色は、徐々に赤から青に変わります。 4 番目のグラデーションの位置は、1.0 の位置にライム グリーンを指定します。 3 番目と 4 番目のグラデーションの間の色は、青からライム グリーンに徐々に変化します。

グラデーション軸

前述のように、線形グラデーション ブラシのグラデーション位置は、グラデーション軸の線に沿って配置されます。 直線グラデーション ブラシを作成するときに、D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES構造の startPoint フィールドと endPoint フィールドを使用して、線の向きとサイズを指定できます。 ブラシを作成したら、ブラシの SetStartPoint メソッドと SetEndPoint メソッドを呼び出してグラデーション軸を調整できます。 ブラシの始点と終点を操作することで、水平方向と垂直方向のグラデーションの作成、グラデーションの方向の反転などを行うことができます。

たとえば、次の図では、始点が (0,0) に設定され、終点が (150, 50) に設定されています。これにより、左上隅から始まり、塗りつぶされている領域の右下隅まで伸びる斜めのグラデーションが作成されます。 始点を (0, 25) に設定し、終点を (150, 25) に設定すると、水平方向のグラデーションが作成されます。 同様に、始点を (75, 0) に設定し、終点を (75, 50) に設定すると、垂直方向のグラデーションが作成されます。 始点を (0, 50) に設定し、終点を (150, 0) に設定すると、左下隅から始まり、塗りつぶされている領域の右上隅まで伸びる対角線のグラデーションが作成されます。

同じ四角形の 4 つの異なるグラデーション軸の図

放射状グラデーション ブラシの使用

グラデーション軸に沿って 2 つ以上の色をブレンドする ID2D1LinearGradientBrush とは異なり、 ID2D1RadialGradientBrush は、楕円全体に 2 つ以上の色をブレンドする放射状グラデーションで領域を塗りつぶします。 ID2D1LinearGradientBrush は始点と終点を使用してグラデーション軸を定義しますが、ID2D1RadialGradientBrush では、中心、水平、垂直半径、グラデーションの原点オフセットを指定してグラデーション楕円を定義します。

ID2D1LinearGradientBrush と同様に、ID2D1RadialGradientBrushID2D1GradientStopCollection を使用してグラデーション内の色と位置を指定します。

次の図は、 ID2D1RadialGradientBrush で塗りつぶされた円を示しています。 円には 2 つのグラデーションの分岐点があります。1 つ目は 0.0 の位置に定義済みの色 "Yellow" を指定し、2 つ目は 1.0 の位置に定義済みの色 "ForestGreen" を指定します。 グラデーションの中心は (75、75)、グラデーションの原点オフセット (0、0)、x 半径と y 半径 75 です。

放射状グラデーション ブラシで塗られた円の図

次のコード例は、 ID2D1RadialGradientBrush でこの円を塗りつぶす方法を示しています。0.0 の位置に "Yellow" 、1.0 の位置に "ForestGreen" があります。 ID2D1LinearGradientBrush の作成と同様に、この例では CreateGradientStopCollection を呼び出して、グラデーションストップの配列から ID2D1GradientStopCollection を作成します。

// Create an array of gradient stops to put in the gradient stop
// collection that will be used in the gradient brush.
ID2D1GradientStopCollection *pGradientStops = NULL;

D2D1_GRADIENT_STOP gradientStops[2];
gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
gradientStops[0].position = 0.0f;
gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
gradientStops[1].position = 1.0f;
// Create the ID2D1GradientStopCollection from a previously
// declared array of D2D1_GRADIENT_STOP structs.
hr = m_pRenderTarget->CreateGradientStopCollection(
    gradientStops,
    2,
    D2D1_GAMMA_2_2,
    D2D1_EXTEND_MODE_CLAMP,
    &pGradientStops
    );

ID2D1RadialGradientBrush を作成するには、ID2D1RenderTarget::CreateRadialGradientBrush メソッドを使用します。 CreateRadialGradientBrush は、3 つのパラメーターを受け取ります。 最初のパラメーター である D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES は、グラデーションの中心、グラデーションの原点オフセット、および水平方向と垂直方向の半径を指定します。 2 番目のパラメーターは、グラデーション内の色とその位置を記述する ID2D1GradientStopCollection です。3 番目のパラメーターは、新しい ID2D1RadialGradientBrush 参照を受け取るポインターのアドレスです。 一部のオーバーロードでは、新しいブラシに適用する不透明度の値と変換を指定する D2D1_BRUSH_PROPERTIES 構造体である追加のパラメーターを受け取ります。

次の例では、 CreateRadialGradientBrush を呼び出し、グラデーション位置の配列を渡し、 中心 値が (75,75)、 gradientOriginOffset が (0,0)、 radiusXradiusY の両方を 75 に設定した放射状グラデーション ブラシ プロパティを呼び出します。

// The center of the gradient is in the center of the box.
// The gradient origin offset was set to zero(0, 0) or center in this case.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateRadialGradientBrush(
        D2D1::RadialGradientBrushProperties(
            D2D1::Point2F(75, 75),
            D2D1::Point2F(0, 0),
            75,
            75),
        pGradientStops,
        &m_pRadialGradientBrush
        );
}

最後の例では、ブラシを使用して楕円を塗りつぶします。

m_pRenderTarget->FillEllipse(ellipse, m_pRadialGradientBrush);
m_pRenderTarget->DrawEllipse(ellipse, m_pBlackBrush, 1, NULL);

放射状グラデーションの構成

centergradientOriginOffsetradiusXradiusY の値が異なると、異なるグラデーションが生成されます。 次の図は、グラデーションの原点オフセットが異なるいくつかの放射状グラデーションを示しており、さまざまな角度から円を照らす光の外観を作成しています。

異なる原点オフセットを持つ放射状グラデーション ブラシで塗られた同じ円の図

ビットマップ ブラシの使用

ID2D1BitmapBrush は、ビットマップで領域を描画します (ID2D1Bitmap オブジェクトで表されます)。

次の図は、植物のビットマップで塗りつぶされた正方形を示しています。

植物のビットマップで塗りつぶされた四角形の図

次の例では、この四角形を ID2D1BitmapBrush で塗りつぶす方法を示します。

最初の例では、ブラシで使用するために ID2D1Bitmap を初期化します。 ID2D1Bitmap は、サンプルの他の場所で定義されているヘルパー メソッド LoadResourceBitmap によって提供されます。

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

ビットマップ ブラシを作成するには、 ID2D1RenderTarget::CreateBitmapBrush メソッドを呼び出し、塗りつぶす ID2D1Bitmap を指定します。 メソッドは 、HRESULT オブジェクトと ID2D1BitmapBrush オブジェクトを 返します。 一部 の CreateBitmapBrush オーバーロードを使用すると、 D2D1_BRUSH_PROPERTIESD2D1_BITMAP_BRUSH_PROPERTIES 構造体を受け入れることで、追加のオプションを指定できます。

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

次の例では、ブラシを使用して四角形を塗りつぶします。

m_pRenderTarget->FillRectangle(&rcBrushRect, m_pBitmapBrush);

拡張モードの構成

グラデーション ブラシまたはビットマップ ブラシのビットマップのグラデーションが、塗りつぶされている領域を完全に塗りつぶさない場合があります。

次の図は、 ID2D1BitmapBrush の拡張モードの可能なすべての組み合わせの結果を示しています。 D2D1_EXTEND_MODE_CLAMP (CLAMP)、 D2D1_EXTEND_MODE_WRAP (WRAP)、 D2D1_EXTEND_MIRROR (MIRROR) です。

さまざまな拡張モードからの元のイメージと結果の画像の図

次の例は、ビットマップ ブラシの x および y 拡張モードを D2D1_EXTEND_MIRROR に設定する方法を示しています。 次に、 ID2D1BitmapBrush で四角形を塗りつぶします。

m_pBitmapBrush->SetExtendModeX(D2D1_EXTEND_MODE_MIRROR);
m_pBitmapBrush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);

m_pRenderTarget->FillRectangle(exampleRectangle, m_pBitmapBrush);

次の図に示すように、出力が生成されます。

x 方向と y 方向をミラーリングした後の元のイメージと結果のイメージの図

ブラシの変換

ブラシでペイントすると、レンダー ターゲットの座標空間にペイントされます。 ブラシは、塗りつぶされているオブジェクトに合わせて自動的に配置されません。既定では、レンダー ターゲットの原点 (0,0) で描画が開始されます。

ID2D1LinearGradientBrush によって定義されたグラデーションをターゲット領域に "移動" するには、その始点と終点を設定します。 同様に、 ID2D1RadialGradientBrush で定義されたグラデーションを移動するには、その中心と半径を変更します。

ID2D1BitmapBrush の内容を塗りつぶされている領域に揃えるには、SetTransform メソッドを使用してビットマップを目的の場所に変換します。 この変換はブラシにのみ影響します。レンダー ターゲットによって描画される他のコンテンツには影響しません。

次の図は、 ID2D1BitmapBrush を使用して (100,100) にある四角形を塗りつぶす効果を示しています。 左側の図は、ブラシを変換せずに四角形を塗りつぶした結果を示しています。ビットマップはレンダー ターゲットの原点に描画されます。 その結果、ビットマップの一部のみが四角形に表示されます。 右側の図は、 ID2D1BitmapBrush を変換して、コンテンツが 50 ピクセル右にシフトし、50 ピクセル下にシフトした結果を示しています。 ビットマップが四角形を塗りつぶすようになりました。

ビットマップ ブラシで描画された四角形の図。ブラシを変換せずに、ブラシを変換して

これを実現する方法を次のコードに示します。 まず ID2D1BitmapBrush に平行移動を適用し、ブラシを x 軸に沿って 50 ピクセル、y 軸に沿って 50 ピクセル下に移動します。 次に 、ID2D1BitmapBrush を使用して、左上隅が (100,100) で右下隅が (200, 200) の四角形を塗りつぶします。

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

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

D2D1_RECT_F rcTransformedBrushRect = D2D1::RectF(100, 100, 200, 200);

// Demonstrate the effect of transforming a bitmap brush.
m_pBitmapBrush->SetTransform(
     D2D1::Matrix3x2F::Translation(D2D1::SizeF(50,50))
     );

// To see the content of the rcTransformedBrushRect, comment
// out this statement.
m_pRenderTarget->FillRectangle(
     &rcTransformedBrushRect, 
     m_pBitmapBrush
     );

m_pRenderTarget->DrawRectangle(rcTransformedBrushRect, m_pBlackBrush, 1, NULL);