サイトアイコン GAMEWORKS LAB

DirectX11の初期化

DirectX11

DirectX11とは主にゲームの開発で使用されるMicrosoftの開発したAPIです。
DirectX9の説明と全く一緒ですねw

こちらも主にゲームの描画関連に使用されています。
ただしDirectX9とは違って大半のヘルパー機能が無くなりました。

算術、入力、サウンド、通信とこの辺りの処理が無くなっています。
※DirectX9でD3DXの機能だった部分

DirectX11ではDirectX9のデバイス(IDirect3DDevice9)で行っていた処理を機能ごとのクラスに分けられています。
そしてより細かな実装や機能の利用ができるようになっています。

他にも利用できるシェーダが増えるなど機能が拡充しています。
その分、覚える知識や使い方の難易度が上がってもいます。

現在のPS4やSwitchといったコンシューマーのAPIはDirectX12準拠になつていますが、
PCゲームの開発では現役で使用されています。

今後はDirectX12が主流になってくるかと思いますが、
DirectX11よりも難度がさらに上がっているので先にDirectX11から勉強していくことをお勧めします。

それでは今回はDirectX11の利用方法~初期化までを書いていこうかと思います。

事前準備

結論から言いますと事前準備はVisualStudioをインストールするだけです!

現在ではDirectX11は既にWindowsSDKに統合されています。
なのでVisualStudioさえあれば特にインストールなどを行う必要はありません!

DirectX9の頃とは大違いですね!
では次のページから早速初期化のコードを書いていきましょう!

 

DirectX11の初期化

Windowの生成などは別の記事で行っているのでその辺りは割愛します。
最後にサンプルもアップしているのでそちらを参考にしてください。

ではここからDirectX11の初期化のプログラムを書いていきます。
先ずはDirectX11.cppとDirectX11.hを作成しましょう。

DirectX11.h

#pragma once

#include "Window.h"
// DirectX11のヘッダーを含める
#include <d3d11.h>

// 解放用テンプレート関数
template<class T>
void SafeRelease(T*& p)
{
	if (p)
	{
		p->Release();
		p = nullptr;
	}
}


// DirectX11クラス
class DirectX11
{
public:
	DirectX11(void);
	~DirectX11(void);

	// 初期化
	bool Initialize(SimpleWindow& window);
	// 終了処理
	void Finalize(void);

public:
	// デバイスの取得
	ID3D11Device* GetDevice(void) { return m_pDevice; }
	// デバイスコンテキストの取得
	ID3D11DeviceContext* GetContext(void) { return m_pDeviceContext; }
	// スワップチェインの取得
	IDXGISwapChain* GetSwapChain(void) { return m_pSwapChain; }

private:
	ID3D11Device* m_pDevice;		// DirectX11のデバイス
	ID3D11DeviceContext* m_pDeviceContext;	// 描画用のデバイスコンテキスト
	IDXGISwapChain* m_pSwapChain;		// 画面出力用のスワップチェイン
};


DirectX9の時と同様にSafeReleaseという解放用の関数を用意しています。
今回はマクロではなくテンプレートで実装しています。

DirectX9と同様にDirectX11のクラスもIUnknownインターフェイスを継承しています。
IUnknownインターフェイスは参照カウンタで生存管理をしています。

なので正しく解放が行っていない場合はDirectXが解放されずに残ってしまいます。
又、Release関数で解放処理を行っているのでdelete等で直接解放してはいけません。

DirectX11.cpp

#include "DirectX11.h"
// DirectX11のライブラリをリンク
#pragma comment(lib, "d3d11.lib")

DirectX11::DirectX11(void)
	: m_pDevice(nullptr)
	, m_pDeviceContext(nullptr)
	, m_pSwapChain(nullptr)
{}

DirectX11::~DirectX11(void)
{}

// 初期化
bool DirectX11::Initialize(SimpleWindow& window)
{
	DXGI_SWAP_CHAIN_DESC desc{};
	// バッファ情報の設定
	desc.BufferCount = 1;
	desc.BufferDesc.Width = window.GetWidth();
	desc.BufferDesc.Height = window.GetHeight();
	desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	desc.BufferDesc.RefreshRate.Numerator = 60;
	desc.BufferDesc.RefreshRate.Denominator = 1;
	desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	// MSAAの設定
	desc.SampleDesc.Count = 1;
	desc.SampleDesc.Quality = 0;
	// ウィンドウ設定
	desc.Windowed = true;
	desc.OutputWindow = window.GetHandle();

	//	機能レベル
	const D3D_FEATURE_LEVEL FeatureLevels[] =
	{
		D3D_FEATURE_LEVEL_11_0,		// DirectX 11.0
		//D3D_FEATURE_LEVEL_10_1,	// DirectX 10.1
		//D3D_FEATURE_LEVEL_10_0,	// DirectX 10.0
	};
	UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);

	D3D_FEATURE_LEVEL level;
	HRESULT hr;
	//	デバイスを作成
	hr = D3D11CreateDeviceAndSwapChain(
		nullptr,
		D3D_DRIVER_TYPE_HARDWARE,
		nullptr,
		0,
		FeatureLevels,
		NumFeatureLevels,
		D3D11_SDK_VERSION,
		&desc,
		&m_pSwapChain,
		&m_pDevice,
		&level,
		&m_pDeviceContext
	);
	if (FAILED(hr))
	{
		return false;
	}

	return true;
}

// 終了処理
void DirectX11::Finalize(void)
{
	SafeRelease(m_pDevice);
	SafeRelease(m_pDeviceContext);
	SafeRelease(m_pSwapChain);
}


DirectX11の初期化に必要な手順は1つだけです。
それはD3D11CreateDeviceAndSwapChainを呼び出すことです!

SwapChainを自分で作成する場合はD3D11CreateDevice方法もありますが、基本的にSwapChainも一緒に作成して問題ありません。

 

初期化で生成されるオブジェクト

D3D11CreateDeviceAndSwapChainでは下記を生成しています。

ID3D11Device DirectX11の機能にアクセスするためのデバイス
このデバイスから描画に必要なオブジェクトの生成などを行います。
ID3D11DeviceContect DirectX11では描画処理がこちらのデバイスコンテキストで行う形になっています。
このオブジェクトで描画コマンドの生成や発行を管理します。又、ImmediateとDeferredの2種類のコンテキストが存在します。
D3D11CreateDeviceAndSwapChainで生成されるのはImmediateです。Immediateではコマンドの生成からGPUへの発行まで行います。Deferredは使用する際に別途作成する必要があります。
遅延という意味ですがコマンドのみを作成してImmediateで作成したコマンドを後から実行することが可能です。これにより複数スレッドで並列して描画コマンドの生成などが可能になります。
IDXGISwapChain レンダリング結果を出力するためのオブジェクトです。
紐づいたビデオアダプタやウィンドウに対してレンダリング結果を出力します。

これらのオブジェクトを生成するところからDirectX11の実装が始まります。
それでは生成する際に使用した情報を見ていきましょう。

 

DXGI_SWAP_CHAIN_DESC
BufferDesc バックバッファの設定です。
バッファのサイズやフォーマット。
そしてリフレッシュレートなどが指定できます。
BufferSampleDesc MSAAを適応するための設定を行います。
ハードウェアに応じて使用できる品質が異なります。
なので使用する場合はデバイスで使用可能な性能を調べてから設定します。
BufferUsage バッファの使用用途を設定します。
今回はシェーダからの出力先として使用するの下記を指定します。
DXGI_USAGE_RENDER_TARGET_OUTPUT
BufferCount バックバッファの数
OutputWindow 出力先のウィンドウハンドル
Windowed ウィンドウモードで初期化するか?
falseにするとフルスクリーンモードとなります。
SwapEffect フロントバッファとバックバッファの入れ替え方法を設定できます。
詳細はDXGI_SWAP_EFFECTを確認してください。
Flags スワップチェインの設定フラグを指定します。
詳細はDXGI_SWAP_CHAIN_FLAGを確認してください。

スワップチェインの生成に使用する設定は以上です。
DirectX9の頃と同じような内容です。
ただリフレッシュレートが細かく設定できるようになっています。

 

D3D11CreateDeviceAndSwapChain
pAdapter 使用するビデオアダプタの設定します。
※nullptrで規定のアダプタを使用
DriverType ドライバタイプの設定します。
基本的にハードウェア(D3D11_DRIVER_TYPE_HARDWEAR)を指定します。
Software D3D_DRIVER_TYPE_SOFTWAREを指定した際に使用するモジュールを設定します。
Flags 使用するフラグの設定します。
詳細はD3D11_CREATE_DEVICEを確認してください。
pFeatureLevels 使用したい機能レベル(D3D_FEATURE_LEVEL)を指定できます。
指定した内容の上から順に初期化できるか実行されます。
nullptrの場合は使用可能な最高レベルが使用されます。
FeatureLevels 上記で指定した機能レベルの要素数
SDKVersion SDKのバージョン指定します。
必ずD3D11_SDK_VERSIONとなります。
pSwapChainDesc 生成するSwapChainの設定です。
ppSwapChain 生成したSwapChainの格納アドレスです。
ppDevice 生成したDeviceの格納アドレスです。
pFeatureLevel 生成に成功した機能レベルです。
ppImmediateContext 生成したDeviceContectの格納アドレスです。

DirectX11を初期化するにはドライバタイプや機能レベルを指定してデバイスを生成します。
DirectX11となっていますが、実際にはDirectX10やDirectX9に制限をかけた状態で生成することもできます。

基本的にDirectX11が動作しない環境のための対処ですが、
最近のPCは基本的にDirectX11で動作するのでそこまで対応する必要があるかは考えものです。

今回についてはDirectX11.0のみでチェックして初期化するようにしています。

 

サンプルプログラム

今回のDirectX11の初期化はここまでです。
最初に記述したように割愛した部分も含めたサンプルコードをアップロードしているので必要に応じて参考にしてください。

Download

モバイルバージョンを終了