次の方法で共有


Direct2D デバイス コンテキストを使用してレンダリングする方法

このトピックでは、Windows 8での Direct2Dデバイス コンテキストの作成について説明します。 この情報は、Direct2D を使用して Windows ストア アプリまたはデスクトップ アプリを開発する場合に適用されます。 このトピックでは、Direct2D デバイス コンテキスト オブジェクトの目的、そのオブジェクトの作成方法、および Direct2D プリミティブとイメージのレンダリングと表示に関するステップ バイ ステップ ガイドについて説明します。 また、レンダー ターゲットの切り替えと、アプリへの効果の追加についても学習します。

Direct2D デバイスとは

Direct2D デバイス コンテキストを作成するには、Direct2D デバイスと Direct3D デバイスが必要です。 Direct2D デバイス (ID2D1Device インターフェイス ポインターを公開) は、ディスプレイ アダプターを表します。 Direct3D デバイス ( ID3D11Device インターフェイス ポインターを公開) は、Direct2D デバイスに関連付けられています。 各アプリには 1 つの Direct2D デバイスが必要ですが、複数の デバイスを持つことができます。

Direct2D デバイス コンテキストとは

Direct2Dデバイス コンテキスト (ID2D1DeviceContext インターフェイス ポインターを公開) は、ターゲットにレンダリングするために使用する一連の状態バッファーとコマンド バッファーを表します。 デバイス コンテキストでメソッドを呼び出してパイプラインの状態を設定し、デバイスが所有するリソースを使用してレンダリング コマンドを生成できます。

Windows 8での Direct2D を使用したレンダリング

Windows 7 以前では、 ID2D1HwndRenderTarget または別のレンダー ターゲット インターフェイスを使用してウィンドウまたはサーフェスにレンダリングします。 Windows 8以降、WINDOWS ストア アプリでは動作しないため、ID2D1HwndRenderTarget などのインターフェイスに依存するメソッドを使用してレンダリングすることはお勧めしません。 デスクトップ アプリを作成し、 デバイス コンテキスト の追加機能を引き続き利用する場合は、 デバイス コンテキスト を使用して Hwnd にレンダリングできます。 ただし、Direct2D を使用して Windows ストア アプリでコンテンツをレンダリングするには、デバイス コンテキストが必要です。

デバイス コンテキストを使用してレンダリングする理由

レンダリング用の Direct2D デバイス コンテキストを作成する方法

このコードでは、Direct3D11 デバイスを作成し、関連付けられている DXGI デバイスを取得し、 Direct2D デバイスを作成し、最後にレンダリング用の Direct2D デバイス コンテキスト を作成する方法を示します。

メソッド呼び出しと、このコードで使用されるインターフェイスの図を次に示します。

direct2d および direct3d デバイスとデバイス コンテキストの図。

注意

このコードでは、 ID2D1Factory1 オブジェクトが既に存在することを前提としています。詳細については、「 ID2D1Factory リファレンス ページ」を参照してください。

 

    // This flag adds support for surfaces with a different color channel ordering than the API default.
    // You need it for compatibility with Direct2D.
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
    
    // This array defines the set of DirectX hardware feature levels this app  supports.
    // The ordering is important and you should  preserve it.
    // Don't forget to declare your app's minimum required feature level in its
    // description.  All apps are assumed to support 9.1 unless otherwise stated.
    D3D_FEATURE_LEVEL featureLevels[] = 
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    // Create the DX11 API device object, and get a corresponding context.
    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;

    DX::ThrowIfFailed(
        D3D11CreateDevice(
            nullptr,                    // specify null to use the default adapter
            D3D_DRIVER_TYPE_HARDWARE,
            0,                          
            creationFlags,              // optionally set debug and Direct2D compatibility flags
            featureLevels,              // list of feature levels this app can support
            ARRAYSIZE(featureLevels),   // number of possible feature levels
            D3D11_SDK_VERSION,          
            &device,                    // returns the Direct3D device created
            &m_featureLevel,            // returns feature level of device created
            &context                    // returns the device immediate context
            )
        );

    ComPtr<IDXGIDevice> dxgiDevice;
    // Obtain the underlying DXGI device of the Direct3D11 device.
    DX::ThrowIfFailed(
        device.As(&dxgiDevice)
        );

    // Obtain the Direct2D device for 2-D rendering.
    DX::ThrowIfFailed(
        m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
        );

    // Get Direct2D device's corresponding device context object.
    DX::ThrowIfFailed(
        m_d2dDevice->CreateDeviceContext(
            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            &m_d2dContext
            )
        );

前のコード サンプルの手順を見てみましょう。

  1. デバイス コンテキストを作成するために必要な ID3D11Device インターフェイス ポインターを取得します。

    • 作成フラグを宣言して、BGRA サポート用の Direct3D デバイスを設定します。 Direct2D には BGRA の色順が必要です。

    • アプリでサポート される機能 レベルのセットを表すD3D_FEATURE_LEVELエントリの配列を宣言します。

      注意

      Direct3D は 、ホスト システムでサポートされている機能レベルが見つかるまでリストを検索します。

       

    • D3D11CreateDevice 関数を使用して ID3D11Device オブジェクトを作成します。この関数は ID3D11DeviceContext オブジェクトも返しますが、この例ではそのオブジェクトは必要ありません。

  2. Direct3D 11 デバイスDXGI デバイス インターフェイスのクエリを実行します。

  3. ID2D1Factory::CreateDevice メソッドを呼び出し、IDXGIDevice オブジェクトを渡して、ID2D1Device オブジェクトを作成します。

  4. ID2D1Device::CreateDeviceContext メソッドを使用して、ID2D1DeviceContext ポインターを作成します。

ターゲットの選択

このコードでは、ウィンドウ バック バッファーの 2 次元 Direct3D テクスチャ を取得し、 Direct2D デバイス コンテキスト がレンダリングするこのテクスチャにリンクするビットマップ ターゲットを作成する方法を示します。

        // Allocate a descriptor.
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
        swapChainDesc.Width = 0;                           // use automatic sizing
        swapChainDesc.Height = 0;
        swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
        swapChainDesc.Stereo = false; 
        swapChainDesc.SampleDesc.Count = 1;                // don't use multi-sampling
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.BufferCount = 2;                     // use double buffering to enable flip
        swapChainDesc.Scaling = DXGI_SCALING_NONE;
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
        swapChainDesc.Flags = 0;

        // Identify the physical adapter (GPU or card) this device is runs on.
        ComPtr<IDXGIAdapter> dxgiAdapter;
        DX::ThrowIfFailed(
            dxgiDevice->GetAdapter(&dxgiAdapter)
            );

        // Get the factory object that created the DXGI device.
        ComPtr<IDXGIFactory2> dxgiFactory;
        DX::ThrowIfFailed(
            dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
            );

        // Get the final swap chain for this window from the DXGI factory.
        DX::ThrowIfFailed(
            dxgiFactory->CreateSwapChainForCoreWindow(
                device.Get(),
                reinterpret_cast<IUnknown*>(m_window),
                &swapChainDesc,
                nullptr,    // allow on all displays
                &m_swapChain
                )
            );

        // Ensure that DXGI doesn't queue more than one frame at a time.
        DX::ThrowIfFailed(
            dxgiDevice->SetMaximumFrameLatency(1)
            );

    // Get the backbuffer for this window which is be the final 3D render target.
    ComPtr<ID3D11Texture2D> backBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
        );

    // Now we set up the Direct2D render target bitmap linked to the swapchain. 
    // Whenever we render to this bitmap, it is directly rendered to the 
    // swap chain associated with the window.
    D2D1_BITMAP_PROPERTIES1 bitmapProperties = 
        BitmapProperties1(
            D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
            m_dpi,
            m_dpi
            );

    // Direct2D needs the dxgi version of the backbuffer surface pointer.
    ComPtr<IDXGISurface> dxgiBackBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
        );

    // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
    DX::ThrowIfFailed(
        m_d2dContext->CreateBitmapFromDxgiSurface(
            dxgiBackBuffer.Get(),
            &bitmapProperties,
            &m_d2dTargetBitmap
            )
        );

    // Now we can set the Direct2D render target.
    m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());

前のコード例の手順を見てみましょう。

  1. DXGI_SWAP_CHAIN_DESC1構造体を割り当て、スワップ チェーンの設定を定義します。

    これらの設定は、Windows ストア アプリで使用できるスワップ チェーンを作成する方法の例を示しています。

  2. Direct3D デバイスDXGI デバイスが実行されているアダプターを取得し、それらに関連付けられている IDXGIFactory オブジェクトを取得します。 この DXGI ファクトリ を使用して、 スワップ チェーン が同じアダプターに作成されるようにする必要があります。

  3. IDXGIFactory2::CreateSwapChainForCoreWindow メソッドを呼び出して、スワップ チェーンを作成します。 Windows ストア アプリのメイン ウィンドウには、Windows::UI::CoreWindow クラスを使用します。

    電力消費量を最小限に抑えるには、フレームの最大待機時間を 1 に設定してください。

    Windows ストア アプリで Direct2D コンテンツをレンダリングする場合は、 CreateSwapChainForComposition メソッドを参照してください。

  4. スワップ チェーンからバック バッファーを取得します。 バック バッファーは、スワップ チェーンによって割り当てられた ID3D11Texture2D インターフェイスを公開します

  5. D2D1_BITMAP_PROPERTIES1構造体を宣言し、プロパティ値を設定します。 Direct3D デバイスDXGI デバイスで使用される形式であるため、ピクセル形式を BGRA に設定します。

  6. Direct2D に渡す IDXGISurface としてバック バッファーを取得します。 Direct2D では 、ID3D11Texture2D は 直接受け入れられません。

    ID2D1DeviceContext::CreateBitmapFromDxgiSurface メソッドを使用して、バック バッファーから ID2D1Bitmap オブジェクトを作成します。

  7. Direct2D ビットマップがバック バッファーにリンクされるようになりました。 Direct2D デバイス コンテキストのターゲットをビットマップに設定します。

レンダリングと表示の方法

ターゲット ビットマップが作成されたので、 Direct2D デバイス コンテキストを使用してプリミティブ、イメージ、イメージ効果、テキストを描画できます。 次のコードは、四角形を描画する方法を示しています。

ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
   m_d2dContext->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        )
);

m_d2dContext->BeginDraw();

m_d2dContext->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

DX::ThrowIfFailed(
    m_d2dContext->EndDraw()
);

DX::ThrowIfFailed(
    m_swapChain->Present1(1, 0, &parameters);
);

前のコード例の手順を見てみましょう。

  1. CreateSolidColorBrush を呼び出して、四角形を塗りつぶすブラシを作成します。
  2. 描画コマンドを発行する前に BeginDraw メソッドを呼び出します。
  3. 描画する四角形とブラシを DrawRectangle メソッドを呼び出します。
  4. 描画コマンドの発行が完了したら、 EndDraw メソッドを呼び出します。
  5. IDXGISwapChain::P resent メソッドを呼び出して結果を表示します。

Direct2D デバイス コンテキストを使用して、プリミティブ、画像、画像効果、テキストを画面に描画できるようになりました。