情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

Direct2D と Direct3D の相互運用性の概要

ハードウェア アクセラレータされた 2-D グラフィックスおよび 3-D グラフィックスは、ゲーム以外のアプリケーションにも次々と組み込まれており、ほとんどのゲーム アプリケーションではメニューやヘッドアップ ディスプレイ (HUD) の形式で 2-D グラフィックスを使用しています。従来の 2-D レンダリングを Direct3D レンダリングと効率的に組み合わせることができるようにすることで、付加価値が高くなります。

ここでは、Direct2D と Direct3D を使用して、2-D グラフィックスと 3-D グラフィックスを統合する方法について説明します。

このトピックは次のセクションで構成されます。

前提条件

この概要では、Direct2D の基本的な描画操作の知識があることを前提としています。チュートリアルについては、「Direct2D クイックスタート」を参照してください。また、Direct3D 10.1 を使用してプログラミングできることも前提としています。

サポートされている Direct3D のバージョン

Direct2D では、Direct3D 10.1 との相互運用性がサポートされています。

DXGI による相互運用性

Direct3D 10 以降、Direct3D ランタイムではリソース管理に DXGI を使用しています。DXGI ランタイム レイヤーはビデオ メモリ サーフェイスをプロセス間で共有できるようにし、他のビデオ メモリ ベースのランタイム プラットフォームの基盤として機能します。Direct2D では DXGI を使用して Direct3D と相互運用します。

Direct2D と Direct3D を組み合わせて使用するには、主に 2 つの方法があります。

  • IDXGISurface を取得し、CreateDxgiSurfaceRenderTarget と共に使用して ID2D1RenderTarget を作成することで、Direct2D コンテンツを Direct3D サーフェイスに書き込むことができます。その後、レンダー ターゲットを使用して 2 次元のインターフェイスまたは背景を 3 次元のグラフィックスに追加するか、Direct2D 描画を 3 次元オブジェクトのテクスチャとして使用することができます。
  • CreateSharedBitmap を使用して IDXGISurface から ID2D1Bitmap を作成することで、Direct3D シーンをビットマップに書き込み、Direct2D を使用してレンダリングできます。

DXGI サーフェイス レンダー ターゲットを使用した Direct3D サーフェイスへの書き込み

Direct3D サーフェイスに書き込むには、IDXGISurface を取得して CreateDxgiSurfaceRenderTarget メソッドに渡し、DXGI サーフェイス レンダー ターゲットを作成します。その後、DXGI サーフェイス レンダー ターゲットを使用して DXGI サーフェイスに 2-D コンテンツを描画できます。

DXGI サーフェイス レンダー ターゲットは ID2D1RenderTarget の 1 つです。他の Direct2D レンダー ターゲットと同様に、DXGI サーフェイス レンダー ターゲットはリソースの作成および描画コマンドの発行に使用できます。

DXGI サーフェイス レンダー ターゲットと DXGI サーフェイスは、同じ DXGI 形式を使用する必要があります。レンダー ターゲットの作成時に DXGI_FORMAT_UNKOWN 形式を指定した場合、サーフェイスの形式が自動的に使用されます。

DXGI サーフェイス レンダー ターゲットでは DXGI サーフェイス同期は実行されません。

DXGI サーフェイスの作成

Direct3D 10 では、DXGI サーフェイスを取得する方法がいくつかあります。デバイスの IDXGISwapChain を作成し、スワップ チェーンの GetBuffer メソッドを使用して DXGI サーフェイスを取得できます。また、デバイスを使用してテクスチャを作成し、そのテクスチャを DXGI サーフェイスとして使用することもできます。

DXGI サーフェイスを作成する方法に関係なく、サーフェイスは DXGI サーフェイス レンダー ターゲットでサポートされている DXGI 形式の 1 つを使用する必要があります。一覧については、「サポートされているピクセル形式とアルファ モード」を参照してください。

また、DXGI サーフェイスを Direct2D で機能させるには、このサーフェイスに関連付けられた ID3D10Device1 で BGRA DXGI 形式がサポートされている必要があります。このサポートを有効にするには、D3D10CreateDevice1 メソッドを呼び出してデバイスを作成するときに D3D10_CREATE_DEVICE_BGRA_SUPPORT フラグを使用します。

次のコードでは、ID3D10Device1 を作成するメソッドを定義します。このコードは、使用できる最適な機能レベルを選択し、ハードウェア レンダリングが使用できない場合は Windows Advanced Rasterization Platform (WARP) に戻ります。

HRESULT DXGISampleApp::CreateD3DDevice(
    IDXGIAdapter *pAdapter,
    D3D10_DRIVER_TYPE driverType,
    UINT flags,
    ID3D10Device1 **ppDevice
    )
{
    HRESULT hr = S_OK;

    static const D3D10_FEATURE_LEVEL1 levelAttempts[] =
    {
        D3D10_FEATURE_LEVEL_10_0,
        D3D10_FEATURE_LEVEL_9_3,
        D3D10_FEATURE_LEVEL_9_2,
        D3D10_FEATURE_LEVEL_9_1,
    };

    for (UINT level = 0; level < ARRAYSIZE(levelAttempts); level++)
    {
        ID3D10Device1 *pDevice = NULL;
        hr = D3D10CreateDevice1(
            pAdapter,
            driverType,
            NULL,
            flags,
            levelAttempts[level],
            D3D10_1_SDK_VERSION,
            &pDevice
            );

        if (SUCCEEDED(hr))
        {
            // transfer reference
            *ppDevice = pDevice;
            pDevice = NULL;
            break;
        }

    }

    return hr;
}

次のコード例では、前の例に示した CreateD3DDevice メソッドを使用して、Direct2D 用に DXGI サーフェイスを作成できる Direct 3D デバイスを作成します。

// Create device
hr = CreateD3DDevice(
    NULL,
    D3D10_DRIVER_TYPE_HARDWARE,
    nDeviceFlags,
    &pDevice
    );

if (FAILED(hr))
{
    hr = CreateD3DDevice(
        NULL,
        D3D10_DRIVER_TYPE_WARP,
        nDeviceFlags,
        &pDevice
        );
}

スワップ チェーン バッファーへの Direct2D コンテンツの書き込み

Direct2D コンテンツを Direct3D シーンに追加する最も簡単な方法は、IDXGISwapChainGetBuffer メソッドを使用して DXGI サーフェイスを取得した後、そのサーフェイスを CreateDxgiSurfaceRenderTarget メソッドで使用して、2-D コンテンツの描画に使用する ID2D1RenderTarget を作成することです。

この方法では、コンテンツは 3 次元ではレンダリングされません。つまり、奥行や深さはありません。ただし、この方法は、次のような一般的なタスクを実行する場合に役立ちます。

  • 3-D シーンの 2-D 背景を作成する。
  • 3-D シーンの前面に 2-D インターフェイスを作成する。
  • Direct2D コンテンツをレンダリングする際に Direct3D マルチサンプリングを使用する。

次のセクションでは、3-D シーンの 2-D 背景を作成する方法を示します。

例: 2-D 背景を描画する

次の手順では、DXGI サーフェイス レンダー ターゲットを作成し、それを使用してグラデーション背景を描画する方法を説明しています。

  1. CreateSwapChain メソッドを使用して、ID3D10Device1 (m_pDevice 変数) のスワップ チェーンを作成します。スワップ チェーンでは DXGI_FORMAT_B8G8R8A8_UNORM DXGI 形式 (Direct2D でサポートされている DXGI 形式の 1 つ) を使用する点に注意してください。

    if (SUCCEEDED(hr))
    {
        hr = pDevice->QueryInterface(&m_pDevice);
    }
    if (SUCCEEDED(hr))
    {
        hr = pDevice->QueryInterface(&pDXGIDevice);
    }
    if (SUCCEEDED(hr))
    {
        hr = pDXGIDevice->GetAdapter(&pAdapter);
    }
    if (SUCCEEDED(hr))
    {
        hr = pAdapter->GetParent(IID_PPV_ARGS(&pDXGIFactory));
    }
    if (SUCCEEDED(hr))
    {
        DXGI_SWAP_CHAIN_DESC swapDesc;
        ::ZeroMemory(&swapDesc, sizeof(swapDesc));
    
        swapDesc.BufferDesc.Width = nWidth;
        swapDesc.BufferDesc.Height = nHeight;
        swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
        swapDesc.BufferDesc.RefreshRate.Numerator = 60;
        swapDesc.BufferDesc.RefreshRate.Denominator = 1;
        swapDesc.SampleDesc.Count = 1;
        swapDesc.SampleDesc.Quality = 0;
        swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapDesc.BufferCount = 1;
        swapDesc.OutputWindow = m_hwnd;
        swapDesc.Windowed = TRUE;
    
        hr = pDXGIFactory->CreateSwapChain(m_pDevice, &swapDesc, &m_pSwapChain);
    }
    
    
  2. スワップ チェーンの GetBuffer メソッドを使用して、DXGI サーフェイスを取得します。

    // Get a surface in the swap chain
    hr = m_pSwapChain->GetBuffer(
        0,
        IID_PPV_ARGS(&pBackBuffer)
        );
    
    
  3. DXGI サーフェイスを使用して、DXGI レンダー ターゲットを作成します。
    // Create the DXGI Surface Render Target.
    FLOAT dpiX;
    FLOAT dpiY;
    m_pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);
    
    D2D1_RENDER_TARGET_PROPERTIES props =
        D2D1::RenderTargetProperties(
            D2D1_RENDER_TARGET_TYPE_DEFAULT,
            D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
            dpiX,
            dpiY
            );
    
    // Create a Direct2D render target which can draw into the surface in the swap chain
    hr = m_pD2DFactory->CreateDxgiSurfaceRenderTarget(
        pBackBuffer,
        &props,
        &m_pBackBufferRT
        );
    
    
    
  4. レンダー ターゲットを使用して、グラデーション背景を描画します。

    // Swap chain will tell us how big the back buffer is
    DXGI_SWAP_CHAIN_DESC swapDesc;
    hr = m_pSwapChain->GetDesc(&swapDesc);
    
    if (SUCCEEDED(hr))
    {
    
    // Draw a gradient background.
    if (m_pBackBufferRT)
    {
        D2D1_SIZE_F targetSize = m_pBackBufferRT->GetSize();
    
        m_pBackBufferRT->BeginDraw();
    
        m_pBackBufferGradientBrush->SetTransform(
            D2D1::Matrix3x2F::Scale(targetSize)
            );
    
        D2D1_RECT_F rect = D2D1::RectF(
            0.0f,
            0.0f,
            targetSize.width,
            targetSize.height
            );
    
        m_pBackBufferRT->FillRectangle(&rect, m_pBackBufferGradientBrush);
    
        hr = m_pBackBufferRT->EndDraw();
    }
    
    

このサンプルでは、コードが省略されています。完全なコードについては、「Direct3D 相互運用機能のサンプル」を参照してください。

Direct2D コンテンツのテクスチャとしての使用

Direct3D で Direct2D コンテンツを使用するもう 1 つの方法では、Direct2D を使用して 2-D テクスチャを生成し、そのテクスチャを 3-D モデルに適用します。これを行うには、ID3D10Texture2D を作成し、テクスチャから DXGI サーフェイスを取得した後、そのサーフェイスを使用して DXGI サーフェイス レンダー ターゲットを作成します。ID3D10Texture2D サーフェイスでは、D3D10_BIND_RENDER_TARGET バインド フラグを使用し、DXGI サーフェイス レンダー ターゲットでサポートされている DXGI 形式を使用する必要があります。サポートされている DXGI 形式の一覧については、「サポートされているピクセル形式とアルファ モード」を参照してください。

例: Direct2D コンテンツをテクスチャとして使用する

次の例は、(ID3D10Texture2D で表される) 2-D テクスチャにレンダリングする DXGI サーフェイス レンダー ターゲットを作成する方法を示しています。

  1. まず、Direct3D デバイスを使用して 2-D テクスチャを作成します。テクスチャは D3D10_BIND_RENDER_TARGET バインド フラグと D3D10_BIND_SHADER_RESOURCE バインド フラグを使用し、DXGI_FORMAT_B8G8R8A8_UNORM DXGI 形式 (Direct2D でサポートされている DXGI 形式の 1 つ) を使用する点に注意してください。

    // Allocate a offscreen D3D surface for D2D to render our 2D content into
    D3D10_TEXTURE2D_DESC texDesc;
    texDesc.ArraySize = 1;
    texDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
    texDesc.CPUAccessFlags = 0;
    texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    texDesc.Height = 512;
    texDesc.Width = 512;
    texDesc.MipLevels = 1;
    texDesc.MiscFlags = 0;
    texDesc.SampleDesc.Count = 1;
    texDesc.SampleDesc.Quality = 0;
    texDesc.Usage = D3D10_USAGE_DEFAULT;
    
    hr = m_pDevice->CreateTexture2D(&texDesc, NULL, &m_pOffscreenTexture);
    
    
  2. テクスチャを使用して、DXGI サーフェイスを取得します。

    IDXGISurface *pDxgiSurface = NULL;
    hr = m_pOffscreenTexture->QueryInterface(&pDxgiSurface);
    
    
  3. CreateDxgiSurfaceRenderTarget メソッドでサーフェイスを使用して、Direct2D レンダー ターゲットを取得します。

    if (SUCCEEDED(hr))
    {
        // Create a D2D render target which can draw into our offscreen D3D
        // surface. Given that we use a constant size for the texture, we
        // fix the DPI at 96.
        D2D1_RENDER_TARGET_PROPERTIES props =
            D2D1::RenderTargetProperties(
                D2D1_RENDER_TARGET_TYPE_DEFAULT,
                D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
                96,
                96
                );
        hr = m_pD2DFactory->CreateDxgiSurfaceRenderTarget(
            pDxgiSurface,
            &props,
            &m_pRenderTarget
            );
    }
    
    

これで、Direct2D レンダー ターゲットを取得して Direct3D テクスチャに関連付けたので、このレンダー ターゲットを使用して Direct2D コンテンツをそのテクスチャに描画し、そのテクスチャを Direct3D プリミティブに適用できます。

このサンプルでは、コードが省略されています。完全なコードについては、「Direct3D 相互運用機能のサンプル」を参照してください。

DXGI サーフェイス レンダー ターゲットのサイズ変更

DXGI サーフェイス レンダー ターゲットでは、ID2D1RenderTarget::Resize メソッドはサポートされていません。DXGI サーフェイス レンダー ターゲットのサイズを変更するには、アプリケーションでこのレンダー ターゲットを解放して作成し直す必要があります。

この操作により、パフォーマンスの問題が発生する可能性があります。レンダー ターゲットは、ID3D10Device1 への参照をレンダー ターゲットの DXGI サーフェイスに関連付けておく最新のアクティブな Direct2D リソースである可能性があります。レンダー ターゲットが解放され、ID3D10Device1 の参照が破棄された場合は、新しいレンダー ターゲットを再度作成する必要があります。

このようにコストのかかる可能性がある操作を回避するには、レンダー ターゲットを再作成するときに、そのレンダー ターゲットによって作成された少なくとも 1 つの Direct2D リソースを保持するようにします。この方法で機能する Direct2D リソースの一部を次に示します。

この方法に対応するには、サイズ変更メソッドで Direct3D デバイスが使用できるかどうかを確認する必要があります。使用できる場合は、DXGI サーフェイス レンダー ターゲットを解放して再作成しますが、以前に作成されたすべてのリソースを保持して再利用します。これが可能なのは、「リソースの概要」で説明されているように、2 つのレンダー ターゲットが同一の Direct3D デバイスに関連付けられている場合、両方のレンダー ターゲットによって作成されたリソースに互換性があるためです。

この方法を実装する方法を示す例については、「Direct3D 相互運用機能のサンプル」を参照してください。

参照

Direct3D 相互運用機能のサンプル
サポートされているピクセル形式とアルファ モード
CreateDxgiSurfaceRenderTarget

 

 

コミュニティの追加

表示:
© 2015 Microsoft