次の方法で共有


ブラシの概要

この概要では、ID2D1SolidColorBrush ID2D1LinearGradientBrushID2D1RadialGradientBrush、および ID2D1BitmapBrush オブジェクトを作成して使用して、純色、グラデーション、ビットマップで領域を描画する方法について説明します。 次のセクションが含まれています。

前提 条件

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

ブラシの種類

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

手記

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 constants」セクションを参照してください。

    定義済みの色の図

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

hr = m_pRenderTarget->CreateSolidColorBrush(
    D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
    &m_pBlackBrush
    );
  • ColorF(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 値は常に直線アルファとして解釈されます。

単色ブラシの使用

純色ブラシを作成するには、ID2D1RenderTarget::CreateSolidColorBrush メソッドを呼び出します。このメソッドは、HRESULT と ID2D1SolidColorBrush オブジェクトを返します。 次の図は、黒いカラー ブラシでストロークされ、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と同様に、ID2D1RadialGradientBrush では、ID2D1GradientStopCollection を使用してグラデーション内の色と位置を指定します。

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

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

次のコード例は、0.0 の位置に "Yellow" と 1.0 の位置に "ForestGreen" という 2 つの色の停止がある ID2D1RadialGradientBrush でこの円を描画する方法を示しています。 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)、radiusX radiusY の両方が 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 を指定します。 このメソッドは、HRESULTID2D1BitmapBrush オブジェクトを返します。 一部 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);