DirectGraphics -DirectX9-

■DirectGraphics概要

DirectGraphicsはDirectXの描画関連を扱うAPIです。
3Dの描画がメインですが、2Dの描画も行うことが可能です。
DirectX9からプログラマシェーダを使用することができ、
10、11とバージョンがあがるごとに使用できるシェーダの種類も増えています。

■DirectGraphicsの構成

DirectGraphicsは大きく二つのCOMインターフェースにより構成されています。
一つはDirectGraphicsの大元となるIDirect3D**(**はバージョン)、
もう一つは描画を行うための関数を持っているIDirect3DDevice**(**はバージョン)です。
※インターフェースがわからない方はインターフェースの部分をクラスに置き換えて下さい。
 DirectXを使用するだけならその認識で問題ないと思います。

●IDirect3D**(**はバージョン)
	上でも記述していますが、IDirect3D**はDirectGraphicsを使用するにあたり、
	大元となるインターフェースです。
	IDirect3DDevice**を作成するための関数やDirectXを使用するPCが
	どこまで機能を使いこなせるかをチェックする関数を持ちます。

●IDirect3DDevice**(**はバージョン)
	IDirect3DDevice**は描画関連のデバイス(GPUやディスプレイ)を管理するインターフェースです。
	このインターフェースにウィンドウに描画をするための関数があるので、
	ゲーム中は主にこのインターフェースを使用することになります。

directx_008

■DirectGraphicsの初期化の流れ

1.IDirect3D9の作成

2.D3DPRESENT_PARAMETERS構造体の設定

3.IDirect3DDevice9の作成

■1.IDirect3D9の作成

DirectGraphicsを使用する場合、最初にIDirect3D9を作成します。
IDirect3D9はDirectX9におけるDirectGraphicsの大元になりますが
この後に作成するIDirect3DDevice9を作成した後はほとんど使用しなくなります。

●IDirect3D9取得関数:
	IDirect3D9* Direct3DCreate9(UINT SDKVersion);
		内容:
			IDirect3D9の作成

		返り値:
			IDirect3D9* IDirect3D9のポインタ

		引数:
			UINT SDKVersion DirectXのSDKバージョン

●IDirect3D9取得関数使用例:
	LPDIRECT3D9 direct3d9 = Direct3DCreate9(D3D_SDK_VERSION);

	if (direct3d9 == NULL)
	{
		// 作成失敗
	}

■D3DPRESENT_PARAMETERS構造体の設定

次に作成するIDirect3DDevice9インターフェースの取得時に
D3DPRESENT_PARAMETERS構造体の設定を行う必要があります。
この構造体でバックバッファの設定などを行います。

●D3DPRESENT_PARAMETERS構造体のメンバ変数
	・UINT BackBufferWidth
		バックバッファの横幅
	
	・UINT BackBufferHeight
		バックバッファの縦幅
	
	・D3DFORMAT BackBufferFormat
		バックバッファの画面フォーマット情報
	
	・UINT BackBufferCount
		バックバッファの数
		
	・MultiSampleType
		マルチサンプルの数
		
	・MultiSampleQuality
		マルチサンプルの品質レベル
		
	・SwapEffect
		フロントバッファとバックバッファの切り替え方法
	
	・hDeviceWindow
		画面を描画するウィンドウハンドル
	
	・Windowed
		スクリーンモード
	
	・EnableAutoDepthStencil
		深度ステンシルバッファの有無
	
	・AutoDepthStencilFormat
		ステンシルバッファのフォーマット

	・Flags
		バックバッファからフロントバッファへ転送時のオプション
		
	・FullScreenRefreshRateInHZ
		フルスクリーンでのリフレッシュレート

	・PresentationInterval
		スワップエフェクトの書き換えタイミング

●最低限必要な設定項目(ウィンドウモード)
	D3DPRESENT_PARAMETERSは全て設定する必要はありませんし、
	最低限必要な設定であっても基本的な値は決まっています。

		・バックバッファのフォーマット => 自動設定
			BackBufferFormat => D3DFMT_UNKNOWN
		
		・バックバッファの数 => 一つ
			BackBufferCount => 1
		
		・ウィンドウモード => true(ウィンドウ)、false(フルスクリーン)
			Windowed => true
		
		・スワップエフェクトの種類 => 自動設定
			SwapEffect => D3DSWAPEFFECT_DISCARD

		※他のメンバ変数に無効な値が設定されないように
		 ZeroMemoryやmemsetなどの関数を使用してD3DPRESENT_PARAMETERS構造体の
		 0クリアは必ず行ってください。

■IDirect3DDeviceの作成

IDirect3Dの作成をしたら次はIDirect3DDeviceの作成をします。
IDirect3DDeviceはグラフィック関連のデバイス(グラフィックカード等の装置)を管理しており、
画面への描画もこのIDirect3DDeviceの関数を使用して行います。

●IDirect3DDevice作成関数
	HRESULT CreateDevice(
			UINT,
			D3DDEVTYPE,
			HWND,
			DWORD,
			D3DPRESENT_PARAMETERS,
			IDirect3DDevice9* );

		内容:
			IDirectDevieceを作成する

		戻り値:
			成功:D3D_OK
			失敗:D3D_OK以外

		引数:
			UINT Adapter:
				ディスプレイアダプタの種類
				D3DADAPTER_DEFAULTを指定

			D3DDEVTYPE DeviceType:
				デバイスの種類を設定
					・D3DDEVTYPE_HAL
						HALデバイスを使用して効率の良い描画処理を行う
	
					・D3DDEVTYPE_REF
						ソフトウェアで描画処理を行う
						D3DDEVTYPE_HALに比べると処理が遅い
	
			HWND hFocusWindow:
				このデバイスが割り当てられるウィンドウハンドル
	
			DWORD BehaviorFlags:
				デバイス制御の組み合わせ
				基本的にはD3DCREATE_HARDWARE_VERTEXPROCESSINGか
				D3DCREATE_SOFTWARE_VERTEXPROCESSINGを使用する
		
			D3DPRESENT_PARAMETERS *pPresentationParameters:
				デバイスを設定するためのD3DPRESENT_PARAMETERS構造体
	
			IDirect3DDevice9** ppReturnedDeviceInterface:
				作成されたIDirect3DDevice9を格納する
				IDirect3DDevice9のポインタのアドレス

●失敗した場合
	CreateDevice関数の失敗の原因としてよくあるのが、
	デバイスの種類と制御設定の部分でハードウェアの設定をしている場合です。
	これはPCのデバイスがDirectXに対応していないことが原因です。
	このエラーの場合は以下の設定を試します。

	1.HAL * ハードウェア処理
		D3DDEVTYPE_HAL、D3DCREATE_HARDWARE_VERTEXPROCESSING
	
	2.HAL * ソフトウェア処理
		D3DDEVTYPE_HAL、D3DCREATE_SOFTWARE_VERTEXPROCESSING
	
	3.REF * ハードウェア処理
		D3DDEVTYPE_REF、D3DCREATE_HARDWARE_VERTEXPROCESSING
	
	4.REF * ソフトウェア処理
		D3DDEVTYPE_REF、D3DCREATE_SOFTWARE_VERTEXPROCESSING

	この設定で問題が発生するようならPC自体がDirectXに対応していない可能性があります。

■ViewPort(ビューポート)

バッファの内容をウィンドウに描画するためには
前もって描画領域を決めておく必要があり、
その描画領域の設定はViewPort(ビューポート)で設定行います。

●D3DVIEWPORT9構造体
	ViewPortの設定はD3DVIEWPORT9構造体を使用します。
		X
			描画開始位置:X座標
		
		Y
			描画開始位置:Y座標
		
		Width
			描画範囲:幅
		
		Height
			描画範囲:高さ
			
		MinZ
			Z深度:最小
		
		MaxZ
			Z深度:最大

●構造体設定
	マルチプレイを行う場合などの特殊な場合以外では以下の設定が基本です。

		X = 0
		Y = 0
		Width = ウィンドウの幅
		Height = ウィンドウの高さ
		MinZ = 0.0f
		MaxZ = 1.0f

●範囲設定の注意点
	directx_007
	上の図にあるように描画開始位置を(0, 0)でない場合は描画開始位置が変更されますが、
	その位置からバッファの内容が描画されるということではない点に注意してください。

●ViewPort設定関数
	ViewPortを設定する関数はIDirectDevice9のメンバ関数であるSetViewportを使用します。
		
	HRESULT SetViewPort(D3DVIEWPORT9のポインタ)

		内容:
			D3DVIEWPORT9の内容を反映する
		
		戻り値:
			D3D_OK:成功
			D3D_OK以外:失敗
			
		引数:
			D3DVIEWPORT9のポインタ

■DirectGraphicsの描画

DirectGraphicsの描画は描画開始と終了を関数を使用して宣言して、
その間に描画処理を行うことでバックバッファに描き込みが行われます。
ただし、そのままでは描画はされず、最後にバックバッファの内容を
フロントバッファに送ることで完了します。
※DirectXではこの描画範囲のことをScene(シーン)と呼んでいます。

●描画手順
	以下は描画を行う手順になりますが、この手順は毎フレーム行います。

	1.シーンのクリア
		描画を行う前にまずはバックバッファの内容をクリアします。
		クリアを行わないと前に描き込まれた内容に上書きすることになるので
		そのフレームのみの描画結果にはなりません。

		使用関数:
			HRESULT Clear(DWORD, const D3DRECT*, DWORD, D3DCOLOR, float, DWORD)

			内容:
				ビューポートの範囲を指定した内容でクリアする

			戻り値:
				成功:D3D_OK
				失敗:D3D_OK以外

			引数:
				DWORD
					第二引数のconst D3DRECT*の矩形の数
	
				const D3DRECT*
					D3DRECTの配列
					クリアする矩形の範囲を変更したい場合に使用
						NULLならビューポート全体をクリア
	
				DWORD
					クリアフラグ
						D3DCLEAR_STENCIL
							ステンシルバッファをクリア
	
						D3DCLEAR_TARGET
							レンダリングターゲットをクリア
	
						D3DCLEAR_ZBUFFER
							深度バッファをクリア
		
						※2Dの場合はD3DCLEAR_TARGETだけでも問題なし
	
				D3DCOLOR
					クリアする色情報
	
				float
					深度バッファで使用する値
					未使用なら0.0f

				DWORD
					ステンシルバッファで使用する値
					未使用なら0
					
	2.シーン描画開始
		バッファをクリアしたら描画開始の宣言をします。

		使用関数:
			HRESULT BeginScene(void)

			内容:
				シーン描画を開始する
	
			戻り値:
				成功:D3D_OK
				失敗:D3D_OK以外

	3.シーン描画終了
		1フレーム内で行う処理がすべて完了したらシーン描画を終了します。

		使用関数:
			HRESULT EndScene(void);

			内容:
				シーン描画を終了する
				※先にBeginSceneを呼び出しておく必要がある

			戻り値:
				成功:D3D_OK
				失敗:D3D_OK以外

	4.バッファ転送
		シーン描画が終了したらシーンの内容をフロントバッファへ転送します。

		使用関数:
			HRESULT Present(const RECT *, const RECT *, HWND, const RGNDATA*)

			内容:
				バッファの内容を転送する

			戻り値:
				成功:D3D_OK
				失敗:D3D_OK以外

			引数:
				const RECT *
					転送元矩形
					※SWAP_EFFECTの種類がD3DSWAPEFFECT_COPYの場合の有効
					 D3DSWAPEFFECT_COPY以外はNULL

				const RECT *
					転送先矩形
					※SWAP_EFFECTの種類がD3DSWAPEFFECT_COPYの場合の有効
					 D3DSWAPEFFECT_COPY以外はNULL
			
				HWND
					ウィンドウハンドル
					※NULLを設定したらD3DPRESENT_PARAMETERSで設定した
					 ウィンドウハンドルが使用される
			
				const RGNDATA*
					基本NULL

	例:
		// IDirect3DDevice9 => pD3D9Device

		// 1.シーンクリア
		pD3D9Device->Clear(0, NULL, D3DCOLOR_XRGB(0, 0, 0), 0.0f, 0);

		// 2.シーン描画開始
		if (D3D_OK == pD3D9Device->BeginScene())
		{
			// 3.シーン描画終了
			pD3D9Device->EndScene();
			// 4.バッファ転送
			pD3D9Device->Present(NULL, NULL, NULL, NULL);
		}

■DirectGraphicsの終了

DirectGraphicsの使用を終了する場合は取得した
COMインターフェースを解放する必要があります。
インターフェース解放はRelease関数が用意してあるのでそれを使います。

●解放の順番
	DirectGraphicsを使用した場合最低でもIDirect3D**(**はバージョン)と
	IDirect3DDevice**(**はバージョン)の二つを使用しますが、
	特別な理由がなければ作成した時と逆の順番で解放します。

	例:
		// IDirect3D9 => pD3D9
		// IDirect3DDevice9 => pD3D9Device

		pD3D9Device->Release();
		pD3D9->Release();