SUU-Lab

プログラムに関するメモとかが多いです。

Direct3D11初期化&画面クリア 続き

間が空いてしまいましたが、前回の続きを書いていきたいと思います。

画面クリア

画面クリアの手順を見ていきましょう。
 

1.バックバッファのリサイズ処理

IDXGISwapChain::ResizeBuffers 関数でクライアント領域に合わせて、
バックバッファのリサイズを行っています。

// SampleApp::CreateBackBuffer(const Size2D& newSize)
    // バッファのサイズを変更
    HRESULT hr = m_SwapChain->ResizeBuffers(
        m_BufferCount,
        static_cast<UINT>(newSize.width),
        static_cast<UINT>(newSize.height),
        m_BufferFormat,
        DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
    );
    if (FAILED(hr))
    {
        return false;
    }

 

IDXGISwapChain::ResizeBuffers 関数

HRESULT ResizeBuffers(
UINT BufferCount,
UINT Width,
UINT Height,
DXGI_FORMAT NewFormat,
UINT SwapChainFlags
);

BufferCount
 スワップチェインのバッファ数です。

 作成した時と同じ値を指定しておけば問題ないでしょう。

Width
 バック バッファーの新しい幅です。

 0 が指定された場合、ターゲット ウィンドウのクライアント領域の幅が使用されます。

Height
 バック バッファーの新しい高さです。

 0 が指定された場合、ターゲット ウィンドウのクライアント領域の高さが使用されます。

NewFormat
 バック バッファーの新しいフォーマットです。

 DXGI_FORMAT の値を指定できます。

 変更しない場合は作成時と同じ値を指定します。

SwapChainFlags
 スワップチェインの動作オプションです。

 DXGI_SWAP_CHAIN_FLAG の値を指定できます。

 変更しない場合は作成時と同じ値を指定します。
 

2.バックバッファを取得

IDXGISwapChain::GetBuffer 関数でバックバッファを取得します。

// SampleApp::CreateBackBuffer(const Size2D& newSize)
    ComPtr<ID3D11Texture2D> backBuffer;

    hr= m_SwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
    if (FAILED(hr))
    {
        return false;
    }

 

IDXGISwapChain::GetBuffer 関数

HRESULT GetBuffer(
UINT Buffer,
REFIID riid,
void **ppSurface
);

Buffer
 取得したいバッファーのインデックスです。

 レンダーターゲットを作成する場合は 0 で問題ないでしょう。

riid
 バッファーの操作に使用するインターフェイスの種類です。

ppSurface
 バック バッファー インターフェイスへのポインターです。
 
※引数の指定の仕方について
IID_PPV_ARGS マクロを使用すると簡潔に記述できます。

m_SwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));

 

3.レンダーターゲットを作成

ID3D11Device::CreateRenderTargetView 関数でレンダーターゲットを作成します。

// SampleApp::CreateBackBuffer(const Size2D& newSize)
    hr = m_Device->CreateRenderTargetView(
        backBuffer.Get(),
        nullptr,
        &m_RenderTargetView
    );
    if (FAILED(hr))
    {
        return false;
    }

 

ID3D11Device::CreateRenderTargetView 関数

HRESULT CreateRenderTargetView(
ID3D11Resource *pResource,
const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
ID3D11RenderTargetView **ppRTView
);

pResource
 レンダー ターゲットを表す ID3D11Resource へのポインターです。

 このリソースは、D3D11_BIND_RENDER_TARGET フラグを使用してあらかじめ作成しておく必要があります。

 ここでは、IDXGISwapChain::GetBuffer 関数で取得した値を指定しています。

pDesc
 レンダー ターゲット ビューの記述を表す D3D11_RENDER_TARGET_VIEW_DESC へのポインターです。

 バックバッファのレンダーターゲットの場合 NULL を指定できます。

ppRTView
 作成されたレンダーターゲットを表す ID3D11RenderTargetView へのポインターのアドレスです。
 

4.レンダーターゲットを設定

ID3D11DeviceContext::OMSetRenderTargets 関数を使用して設定します。

// SampleApp::CreateBackBuffer(const Size2D& newSize)
    ID3D11RenderTargetView* pRenderTargetViews[] = {
        m_RenderTargetView.Get()
    };
    m_Context->OMSetRenderTargets(
        _countof(pRenderTargetViews),
        pRenderTargetViews,
        nullptr
    );

 

ID3D11DeviceContext::OMSetRenderTargets 関数

void OMSetRenderTargets(
UINT NumViews,
ID3D11RenderTargetView *const *ppRenderTargetViews,
ID3D11DepthStencilView *pDepthStencilView
);

NumViews
 バインドするレンダー ターゲットの数です (範囲は 0 ~ D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT)。

 ppRenderTargetViews の要素数です。

ppRenderTargetViews
 デバイスにバインドするレンダー ターゲットの配列へのポインターです。

 このパラメーターが NULL の場合、レンダー ターゲットはバインドされません。

pDepthStencilView
 デバイスにバインドする深度ステンシル ビューへのポインターです。

 このパラメーターが NULL の場合、深度ステンシル ステートはバインドされません。
 

5.ビューポートの設定

D3D11_VIEWPORT 構造体で設定を記述し、
ID3D11DeviceContext::RSSetViewports 関数で設定します。

// SampleApp::CreateBackBuffer(const Size2D& newSize)
    D3D11_VIEWPORT viewport;
    viewport.Width = static_cast<FLOAT>(newSize.width);
    viewport.Height = static_cast<FLOAT>(newSize.height);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;
    m_Context->RSSetViewports(1, &viewport);

 

6.画面クリア

ID3D11DeviceContext::ClearRenderTargetView 関数を使用して画面をクリアします。

// SampleApp::Render()
    // 指定色でクリア
    FLOAT clearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
    m_Context->ClearRenderTargetView(m_RenderTargetView.Get(), clearColor);

 

7.バックバッファを画面に反映

IDXGISwapChain::Present 関数でバックバッファを画面に反映します。

// SampleApp::Render()
    // 結果をウインドウに反映
    HRESULT hr = m_SwapChain->Present(0, 0);
    if (FAILED(hr))
        // Error!
    }

 
最後の方が説明不足な気がしますが、これで画面クリアができました。
長かったです。

f:id:n-suudai:20180505135844p:plain
画面クリア