Direct3D11初期化&画面クリア
Direct3D11 を使用して初期化&画面クリアするアプリケーションを作成しました。
サンプルアプリケーションクラス
初期化&画面クリアに必要な最小クラスです。
// SampleApp.hpp #pragma once #include "IApp.hpp" #include <dxgi.h> #include <d3d11.h> #include <wrl.h> template<class T> using ComPtr = Microsoft::WRL::ComPtr<T>; class SampleApp { public: SampleApp(IApp* pApp); ~SampleApp(); // 初期化 bool Init(); // 描画処理 void Render(); // リサイズ void OnResize(const Size2D& newSize); private: // バックバッファを作成 bool CreateBackBuffer(const Size2D& newSize); private: IApp * m_pApp; UINT m_BufferCount; DXGI_FORMAT m_BufferFormat; D3D_FEATURE_LEVEL m_FeatureLevel; ComPtr<IDXGIFactory> m_Factory; ComPtr<IDXGISwapChain> m_SwapChain; ComPtr<ID3D11Device> m_Device; ComPtr<ID3D11DeviceContext> m_Context; ComPtr<ID3D11RenderTargetView> m_RenderTargetView; };
Direct3D11 初期化
初期化の手順を見ていきましょう。
1.ライブラリのリンク
Direct3D11 を利用するのに必要なライブラリをリンクしています。
// SampleApp.cpp // DXGI & D3D11 のライブラリをリンク #pragma comment(lib, "dxgi.lib") #pragma comment(lib, "d3d11.lib")
2.IDXGIFactory の作成
IDXGISwapChain を作成するのに必要なので、あらかじめ作成しておきます。
CreateDXGIFactory 関数で作成します。
// SampleApp::Init() HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(&m_Factory)); if(FAILED(hr)) { return false; }
3.ID3D11Device & ID3D11DeviceContext の作成
D3D11CreateDevice 関数で作成しています。
IDXGISwapChain と同時に作成も可能なのですが、今回は別々に作成しています。
// SampleApp::Init() #if defined(DEBUG) || defined(_DEBUG) createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, }; // デバイス&コンテキストを生成 hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE, // ハードウェア ドライバー を使用 nullptr, createDeviceFlags, featureLevels, _countof(featureLevels), D3D11_SDK_VERSION, &m_Device, &m_FeatureLevel, &m_Context ); if (FAILED(hr)) { return false; }
D3D11CreateDevice 関数
HRESULT D3D11CreateDevice(
IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
CONST D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
ID3D11Device **ppDevice,
D3D_FEATURE_LEVEL *pFeatureLevel,
ID3D11DeviceContext **ppImmediateContext
);
pAdapter
デバイスの作成時に使用するビデオ アダプターへのポインターです。
通常は既定のアダプターで良いので、NULL で問題ないです。
DriverType
作成するデバイスの種類です。
D3D_DRIVER_TYPE のいずれかを指定します。
pAdapter に NULL 以外の値を指定する場合は、 D3D_DRIVER_TYPE_UNKNOWN を指定する必要があります。
通常は D3D_DRIVER_TYPE_HARDWARE 問題ないでしょう。
Software
ソフトウェア ラスタライザーを実装する DLL のハンドルです。
DriverType に D3D_DRIVER_TYPE_SOFTWARE を指定した場合、NULL に設定することはできません。
D3D_DRIVER_TYPE_SOFTWARE を指定することはほぼないので、NULL で問題ないでしょう。
Flags
有効にするランタイム レイヤーです。
D3D11_CREATE_DEVICE_FLAG の値を OR 演算で指定できます。
デバッグレイヤーを有効にするには、D3D11_CREATE_DEVICE_DEBUG を指定します。
デフォルトで良い場合は 0 で構いません。
pFeatureLevels
作成を試みる機能レベルの順序を指定する配列へのポインターです。
機能レベルが高いものから順に並べておくと、最大の機能レベルを取得できます。
FeatureLevels
pFeatureLevels の要素数です。
SDKVersion
SDK のバージョンです。D3D11_SDK_VERSION を指定します。
ppDevice
作成されたデバイスを表す ID3D11Device オブジェクトへのポインターのアドレスを返します。
pFeatureLevel
成功した場合は、成功した pFeatureLevels 配列の最初の D3D_FEATURE_LEVEL を返します。
失敗した場合は 0 を返します。
ppImmediateContext
デバイス コンテキストを表す ID3D11DeviceContext オブジェクトへのポインターのアドレスを返します。
4.MSAA (Multi-Sample Anti-Aliasing) の設定
今回は画面クリアまでなので必要ないかもしれませんが、一応設定だけしておきます。
MSAA については、ここでは説明を省きます。
スワップチェインの作成時に MSAA を有効化できるのですが、その設定に利用する値を調べます。
ID3D11::CheckMultisampleQualityLevels 関数を使って、利用可能なサンプリングカウントと品質の最大値を調べます。
// SampleApp::Init() // 使用可能なMSAAを取得 DXGI_SAMPLE_DESC sampleDesc; ZeroMemory(&sampleDesc, sizeof(sampleDesc)); for (int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i <<= 1) { UINT Quality; if (SUCCEEDED(m_Device->CheckMultisampleQualityLevels(DXGI_FORMAT_D24_UNORM_S8_UINT, i, &Quality))) { if (0 < Quality) { sampleDesc.Count = i; sampleDesc.Quality = Quality - 1; } } }
5.DXGI_SWAP_CHAIN_DESC の設定
スワップチェイン作成に必要な設定をします。
下のような感じです。
// SampleApp::Init() // DXGI_SWAP_CHAIN_DESC の設定 DXGI_SWAP_CHAIN_DESC swapChainDesc; ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferDesc.Width = static_cast<UINT>(clientSize.width); swapChainDesc.BufferDesc.Height = static_cast<UINT>(clientSize.height); swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; swapChainDesc.BufferDesc.Format = m_BufferFormat; swapChainDesc.SampleDesc = sampleDesc; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; swapChainDesc.BufferCount = m_BufferCount; swapChainDesc.Windowed = TRUE; swapChainDesc.OutputWindow = hWnd; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
DXGI_SWAP_CHAIN_DESC 構造体
typedef struct DXGI_SWAP_CHAIN_DESC {
DXGI_MODE_DESC BufferDesc;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
HWND OutputWindow;
BOOL Windowed;
DXGI_SWAP_EFFECT SwapEffect;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC;
BufferDesc.Width
バッファの横幅です。
BufferDesc.Height
バッファの縦幅です。
BufferDesc.RefreshRate.Numerator
リフレッシュレートの分子です。
BufferDesc.RefreshRate.Denominator
リフレッシュレートの分母です。
BufferDesc.ScanlineOrdering
スキャンラインの方法です。
バックバッファをフリップした時にハードウェアがパソコンのモニターに点をどう描くかを指定します。
プログレッシブやインターレスなどが選択可能ですが、
特段理由が無ければデフォルト値(DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED)でOKです。
BufferDesc.Scaling
バッファのスケーリングの設定です。
ウィンドウのサイズに応じてスケーリングするかどうかの設定を行えます。
スケーリングする場合は DXGI_MODE_SCALING_STRETCHED 、
スケーリングしない場合は DXGI_MODE_SCALING_CENTERED を指定します。
BufferDesc.Format
バッファのフォーマットです。
フォーマットの設定についてはかなりの種類があるので MSDN を参考にしてください。
SampleDesc
MSAA の設定です。
「4.MSAA (Multi-Sample Anti-Aliasing) の設定」で取得した値を設定します。
何も指定しなかった場合は MSAA が無効になります。
BufferUsage
バッファの使用方法です。
レンダーターゲットとして使用する場合は DXGI_USAGE_RENDER_TARGET_OUTPUT 、
シェーダー入力用(レンダリングテクスチャ)として使用する場合は DXGI_USAGE_SHADER_INPUT を指定します。
BufferCount
バッファの数です。
2ならダブルバッファ、3ならトリプルバッファとなります。
特別こだわりがなければ2で問題ないと思います。
Windowed
ウィンドウモードで作成するかどうかです。
TRUE ならウィンドウモード、FALSE ならフルスクリーンモードです。
OutputWindow
出力ウィンドウです。ウィンドウハンドルを指定します。
Flags
スワップチェインの動作オプションです。
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH を指定した場合、
フルスクリーンモードとウィンドウモードの切り替えが可能になります。
6.IDXGISwapChain の作成
やっとスワップチェインの作成です。
IDXGIFactory::CreateSwapChain 関数で作成します。
// SampleApp::Init() // スワップチェインの生成 hr = m_Factory->CreateSwapChain( m_Device.Get(), &swapChainDesc, &m_SwapChain ); if (FAILED(hr)) { return false; }
IDXGIFactory::CreateSwapChain 関数
HRESULT CreateSwapChain(
IUnknown *pDevice,
DXGI_SWAP_CHAIN_DESC *pDesc,
IDXGISwapChain **ppSwapChain
);
pDevice
スワップ チェーンに 2D イメージを書き込むデバイスへのポインター。
D3D11CreateDevice で作成したデバイスを指定します。
pDesc
DXGI_SWAP_CHAIN_DESC へのポインターです。
NULL は指定できません。
ppSwapChain
作成されたスワップ チェーンへのポインターです。
ここまで記事を書いてきたのですが、
長くなったので続きは次回にしようと思います。
次回はレンダーターゲットの作成と画面クリアの処理についてです。