ゲームプログラミングTips(5):DirectX Graphics(1)(基幹編)
2012年5月7日……前回の講座より、実に17日ぶりである。
実は毎回の講座を書くのは前の講座から一週間以内なのだが、日記をサボりがちなため連動して更新が遅れがちである。
……ううむ、どうしたらいいものか(´Д`)
1.DirectX Graphicsとは?
DirectX Graphicsとはゲーム処理用API「DirectX」のグラフィックを扱うコンポーネントのことである。
……って、こんなこと別に書かなくても当然知ってるよね?(´Д`)
詳しくはウィキペれ>[DirectX Graphics]
2.DirectX Graphicsのゲームプログラミングにおける活用事例
Windows上で動作するゲームにおいて使わない事例はない、以上。
……いや、まあブラウザゲーとか例外を挙げていけばいくらでもあるんですがね(;´Д`)
一般的なゲームプログラミングにおいては、気にする必要は無いし考えるだけ無駄というものである。
3.具体例(ヘッダ解説)
本項では、俺が作ったDirectX Graphicsラッパークラスを掲載する。
/************************************************* ファイル名:DX9AGraphic.h 作成者 :あびす 役割 :DirectX Graphicsラッパー *************************************************/ /** * @file DX9AGraphic.h * @brief DirectX Graphicsのラッパークラス関係です。 */ #ifndef DX9A_GRAPHICS_DX9AGRAPHIC_H #define DX9A_GRAPHICS_DX9AGRAPHIC_H namespace nsDX9A{ namespace nsGraphics{ namespace nsDX9AGraphic{ //文字列テクスチャ /** * @brief 文字列テクスチャの情報が格納されている構造体です。 < br > * ユーザーが使用する必要はありません。 */ struct StringTexture{ /** * @brief 文字列テクスチャが最後に参照された時間です。 */ DWORD LastRefTime; //最後に参照された時間 /** * @brief 文字列テクスチャのサイズです(単位:バイト) */ unsigned int Size; //テクスチャのサイズ /** * @brief 文字列テクスチャの横幅です。 */ unsigned int Width; //テクスチャの横幅 /** * @brief 文字列テクスチャの縦幅です。 */ unsigned int Height; //テクスチャの縦幅 /** * @brief 文字列テクスチャです( < a href="http://msdn.microsoft.com/ja-jp/library/cc324033.aspx" target="_blank" > IDirect3DTexture9インターフェイス < /a > へのポインタ) */ LPDIRECT3DTEXTURE9 Texture; //テクスチャ }; //DirectX Graphicsラッパー /** * @brief DirectX Graphicsのラッパークラスです。 < br > * 使用前に、必ずInitメソッドを実行してください。 */ class DX9AGraphic{ /** * @brief DX9AGraphicAccessor クラスから本クラスのプライベートメンバにアクセス可能です。 */ friend class DX9AGraphicAccessor; //フレンドクラス(アクセッサ) public: /** * @brief デフォルトコンストラクタです。 */ DX9AGraphic(); //デフォルトコンストラクタ /** * @brief デストラクタです。 */ ~DX9AGraphic(); //デストラクタ //初期化(必ず呼び出すこと) /** * @brief 初期化を行います。 < br > * 使用前に、必ず実行してください。 * @param hInst [in]インスタンスハンドルを指定します。 * @param WindowName [in]ウインドウ名を指定します。 * @param WndProc [in]メッセージ処理用コールバック関数を指定します。 * @param ScreenWidth [in]ウインドウの横幅を指定します。 * @param ScreenHeight [in]ウインドウの縦幅を指定します。 * @param StringTextureMaxSize [in]文字列テクスチャの最大サイズを指定します(単位:バイト) < br > * 自動で拡張される場合があります。 < br > * (例:StringTextureMaxSize = 5 * 1024(5KB)で使用中の文字列テクスチャ(6KB)が存在する場合、 < br > * StringTextureMaxSize = 6 * 1024(6KB)に自動で拡張されます) * @param IsFullScreen [in]フルスクリーンモードかを指定します。 < br > * フルスクリーンモードにする場合はtrueを、ウインドウモードにする場合はfalseを指定します。 * @param UseDepthStencil [in]深度/ステンシルバッファを使用するかを指定します。 < br > * 使用する場合はtrueを、使用しない場合はfalseを指定します。 * @param UseMultiSample [in]フルシーンアンチエイリアシングを使用するかを指定します。 < br > * 使用する場合はtrueを、使用しない場合はfalseを指定します。 * @param hIcon [in]大アイコンを指定します。 * @param hCursor [in]マウスカーソルを指定します。 * @param hIconSm [in]小アイコンを指定します。 * @return 初期化が成功した場合はtrue、失敗した場合はfalseを返します。 */ bool Init(HINSTANCE hInst, LPCTSTR WindowName, WNDPROC WndProc, int ScreenWidth, int ScreenHeight, unsigned int StringTextureMaxSize, bool IsFullScreen = false, bool UseDepthStencil = false, bool UseMultiSample = false, HICON hIcon = NULL, HCURSOR hCursor = NULL, HICON hIconSm = NULL); //アイドル時の処理(必ず実行すること) /** * @brief アイドル時の処理を行います。 < br > * メインループ中で、必ず実行してください。 * @return 処理が成功した場合はtrue、失敗した場合はfalseを返します。 */ bool AppIdle(); //ウインドウプロシージャ(必ず実行すること) /** * @brief ウインドウプロシージャ内での処理を行います。 < br > * ウインドウプロシージャ内で、必ず実行してください。 * @param hWnd [in]ウインドウプロシージャのhWndを指定します。 < br > * @param uMsg [in]ウインドウプロシージャのuMsgを指定します。 * @param wParam [in]ウインドウプロシージャのwParamを指定します。 * @param lParam [in]ウインドウプロシージャのlParamを指定します。 */ void MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //その他(初期化を済ませてから呼び出すこと) /** * @brief アクティブ状態かを取得します。 * @return アクティブ状態かを返します。 < br > * アクティブ状態の場合はtrueを、アクティブ状態でない場合はfalseを返します。 */ bool IsActive() const; //アクティブ状態かを取得 /** * @brief ウインドウハンドルを取得します。 * @return ウインドウハンドルを返します。 */ HWND GetHWND() const; //ウインドウハンドルを取得 /** * @brief ウインドウの横幅を取得します。 * @return ウインドウの横幅を返します。 */ int GetScreenWidth() const; //画面の横幅を取得 /** * @brief ウインドウの縦幅を取得します。 * @return ウインドウの縦幅を返します。 */ int GetScreenHeight() const; //画面の縦幅を取得 /** * @brief フルスクリーンかを取得します。 * @return フルスクリーンかを返します。 < br > * フルスクリーンモードの場合はtrueを、ウインドウモードの場合はfalseを返します。 */ bool GetFullScreen() const; //フルスクリーンモードか否かを取得 /** * @brief フルスクリーンかを設定します。 * @param IsFullScreen [in]フルスクリーンかを指定します。 < br > * フルスクリーンモードにする場合はtrueを、ウインドウモードにする場合はfalseを指定します。 */ bool SetFullScreen(bool IsFullScreen); //フルスクリーンモードか否かを設定 /** * @brief 画面の消去を行います。 * @param Color [in]塗り潰す色を < a href="http://msdn.microsoft.com/ja-jp/library/bb172518(v=vs.85).aspx" target="_blank" > D3DCOLOR < /a > で指定します。 */ void Clear(D3DCOLOR Color); //画面を消去 /** * @brief 画面の更新を行います。 */ void Present(); //画面を更新 /** * @brief 矩形の描画を行います。 * @param Rect [in]矩形を < a href="http://msdn.microsoft.com/ja-jp/library/ms931125.aspx" target="_blank" > RECT < /a > で指定します。 * @param Color [in]塗り潰す色を < a href="http://msdn.microsoft.com/ja-jp/library/bb172518(v=vs.85).aspx" target="_blank" > D3DCOLOR < /a > で指定します。 * @param Degree [in]回転する角度を指定します(単位:度) * @param BlendOp [in]ブレンディング処理を < a href="http://msdn.microsoft.com/ja-jp/library/bb172509(VS.85).aspx" target="_blank" > D3DBLENDOP < /a > で指定します。 * @param SrcBlend [in]転送元のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 * @param DestBlend [in]転送先のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 */ void DrawRect(RECT Rect, D3DCOLOR Color, float Degree = 0.0f, D3DBLENDOP BlendOp = D3DBLENDOP_ADD, D3DBLEND SrcBlend = D3DBLEND_SRCALPHA, D3DBLEND DestBlend = D3DBLEND_INVSRCALPHA); //矩形を描画 /** * @brief 文字列の描画を行います。 * @param Text [in]文字列を指定します。 * @param x [in]文字列の描画先のX座標を指定します。 * @param y [in]文字列の描画先のY座標を指定します。 * @param Color [in]文字列の色を < a href="http://msdn.microsoft.com/ja-jp/library/bb172518(v=vs.85).aspx" target="_blank" > D3DCOLOR < /a > で指定します。 * @param Font [in]文字列のフォントを指定します。 * @param Size [in]文字列のサイズを指定します。 * @param IsBold [in]文字列が太字かを指定します。 < br > * 太字の場合はtrueを、太字でない場合はfalseを指定します。 * @param IsItalic [in]文字列が斜体かを指定します。 < br > * 斜体の場合はtrueを、斜体でない場合はfalseを指定します。 * @param Degree [in]回転する角度を指定します(単位:度) * @param BlendOp [in]ブレンディング処理を < a href="http://msdn.microsoft.com/ja-jp/library/bb172509(VS.85).aspx" target="_blank" > D3DBLENDOP < /a > で指定します。 * @param SrcBlend [in]転送元のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 * @param DestBlend [in]転送先のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 */ void DrawFreeText(const string& Text, int x, int y, D3DCOLOR Color, const string& Font, unsigned int Size, bool IsBold, bool IsItalic, float Degree = 0.0f, D3DBLENDOP BlendOp = D3DBLENDOP_ADD, D3DBLEND SrcBlend = D3DBLEND_SRCALPHA, D3DBLEND DestBlend = D3DBLEND_INVSRCALPHA); //文字列を描画 /** * @brief テクスチャの転送を行います。 * @param Texture [in]対象のテクスチャを指定します。 * @param x [in]テクスチャの描画先のX座標を指定します。 * @param y [in]テクスチャの描画先のY座標を指定します。 * @param Color [in]テクスチャの描画色を < a href="http://msdn.microsoft.com/ja-jp/library/bb172518(v=vs.85).aspx" target="_blank" > D3DCOLOR < /a > で指定します。 * @param SrcRect [in]転送元矩形を < a href="http://msdn.microsoft.com/ja-jp/library/ms931125.aspx" target="_blank" > RECT < /a > で指定します。 * @param BlendOp [in]ブレンディング処理を < a href="http://msdn.microsoft.com/ja-jp/library/bb172509(VS.85).aspx" target="_blank" > D3DBLENDOP < /a > で指定します。 * @param SrcBlend [in]転送元のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 * @param DestBlend [in]転送先のブレンディングモードを < a href="http://msdn.microsoft.com/ja-jp/library/cc324307.aspx" target="_blank" > D3DBLEND < /a > で指定します。 * @param ScalingX [in]拡大倍率(X方向)を指定します。 * @param ScalingY [in]拡大倍率(Y方向)を指定します。 * @param Degree [in]回転する角度を指定します(単位:度) */ void GeneralBlt(LPDIRECT3DTEXTURE9 Texture, int x, int y, D3DCOLOR Color, const RECT* SrcRect, D3DBLENDOP BlendOp, D3DBLEND SrcBlend, D3DBLEND DestBlend, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f); //汎用転送 private: HWND m_hWnd; //ウインドウハンドル HINSTANCE m_hInst; //インスタンスハンドル string m_ClassName; //ウインドウクラスの名前 bool m_IsActive; //アクティブ状態か? bool m_IsBeginScene; //シーンが開始されているか? bool m_IsBeginSprite; //スプライトの描画が開始されているか? bool m_IsDeviceLost; //デバイスが消失しているか? int m_ScreenWidth; //画面の横幅 int m_ScreenHeight; //画面の縦幅 bool m_IsFullScreen; //フルスクリーンモードか? bool m_IsUseDepthStencil; //深度/ステンシルバッファを使用するか? bool m_IsUseMultiSample; //フルシーンアンチエイリアシングを使用するか? RECT m_WindowLastPos; //ウインドウの最後の位置 void BeginScene(); //描画を開始 void EndScene(); //描画を終了 void BeginSprite(); //スプライトの描画を開始 void EndSprite(); //スプライトの描画を終了 bool InitApp(LPCTSTR WindowName, WNDPROC WndProc, HICON hIcon, HCURSOR hCursor, HICON hIconSm); //アプリケーションを初期化 bool InitD3D(); //Direct3Dに管理されているオブジェクトを初期化 bool SelectD3DDevice(UINT& Adapter, D3DDEVTYPE& Device); //デバイスの設定を選択 bool CheckDeviceCaps(D3DCAPS9* Caps); //デバイスの能力をチェック bool SelectAdapterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode); //ディスプレイとバックバッファのフォーマットを調査 bool SelectDepthStencilFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode); //深度/ステンシルバッファのフォーマットを調査 bool SelectRenderTextureFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode); //レンダリングテクスチャのフォーマットを調査 bool SelectMultiSampleType(UINT Adapter, D3DDEVTYPE Device); //フルシーンアンチエイリアシングを調査 bool SelectDisplayMode(UINT Adapter); //ディスプレイモードを調査 bool InitD3DObject(); //Direct3Dに管理されていないオブジェクトを初期化 bool CleanupD3DObject(); //Direct3Dに管理されていないオブジェクトの終了処理 bool CleanupD3D(); //Direct3Dに管理されているオブジェクトの終了処理 bool CleanupApp(); //アプリケーションの終了処理 LPDIRECT3D9 m_pD3D; //Direct3D9オブジェクト LPDIRECT3DDEVICE9 m_pD3DDevice; //Direct3DDevice9オブジェクト D3DPRESENT_PARAMETERS m_D3DParamNow; //D3DPRESENT_PARAMETERS構造体(現在) D3DPRESENT_PARAMETERS m_D3DParamWin; //D3DPRESENT_PARAMETERS構造体(ウインドウモード) D3DPRESENT_PARAMETERS m_D3DParamFull; //D3DPRESENT_PARAMETERS構造体(フルスクリーンモード) D3DFORMAT m_FmtRenderTextureWin; //レンダリングテクスチャのフォーマット(ウインドウモード) D3DFORMAT m_FmtRenderTextureFull; //レンダリングテクスチャのフォーマット(フルスクリーンモード) LPD3DXSPRITE m_pD3DXSprite; //スプライト LPDIRECT3DTEXTURE9 m_pDrawRect; //矩形描画用テクスチャ unsigned int m_StringTextureNowSize; //文字列テクスチャの合計サイズ unsigned int m_StringTextureMaxSize; //文字列テクスチャの最大サイズ map < string, StringTexture > m_StringTexture; //文字列テクスチャ( < "テキスト_フォント_サイズ_その他", 文字列テクスチャ構造体 > ) DX9AGraphic(const DX9AGraphic&); //コピーコンストラクタ(禁止) DX9AGraphic& operator =(const DX9AGraphic&); //代入演算子(禁止) }; //DirectX Graphicsラッパーへのアクセッサ /** * @brief DX9AGraphic クラスへのアクセッサクラスです。 < br > * 使用前に、必ずSetParentメソッドを実行してください。 < br > * また、このクラス経由で DX9AGraphic クラスのプライベートメンバを操作するのは大変危険な行為です。 < br > * それを理解し、十分注意した上で使用するようにしてください。 */ class DX9AGraphicAccessor{ public: /** * @brief デフォルトコンストラクタです。 */ DX9AGraphicAccessor(); //デフォルトコンストラクタ /** * @brief アクセス対象の DX9AGraphic クラスを設定します。 * @param Parent [in]アクセス対象の DX9AGraphic クラスを指定します。 */ void SetParent(DX9AGraphic* Parent); //親エンジンを設定 /** * @brief < a href="http://msdn.microsoft.com/ja-jp/library/cc324302.aspx" target="_blank" > IDirect3D9インターフェイスへのポインタ < /a > を取得します。 * @return < a href="http://msdn.microsoft.com/ja-jp/library/cc324302.aspx" target="_blank" > IDirect3D9インターフェイスへのポインタ < /a > を返します。 */ LPDIRECT3D9 GetD3D9(); //Direct3D9オブジェクトを取得 /** * @brief < a href="http://msdn.microsoft.com/ja-jp/library/cc372361.aspx" target="_blank" > ID3DXSpriteインターフェイスへのポインタ < /a > を取得します。 * @return < a href="http://msdn.microsoft.com/ja-jp/library/cc372361.aspx" target="_blank" > ID3DXSpriteインターフェイスへのポインタ < /a > を返します。 */ LPD3DXSPRITE GetD3DXSprite(); //スプライトオブジェクトを取得 /** * @brief < a href="http://msdn.microsoft.com/ja-jp/library/cc324252.aspx" target="_blank" > IDirect3DDevice9インターフェイスへのポインタ < /a > を取得します。 * @return < a href="http://msdn.microsoft.com/ja-jp/library/cc324252.aspx" target="_blank" > IDirect3DDevice9インターフェイスへのポインタ < /a > を返します。 */ LPDIRECT3DDEVICE9 GetD3D9Device(); //Direct3DDevice9オブジェクトを取得 private: DX9AGraphic* Outer; //親エンジンのアドレス DX9AGraphicAccessor(const DX9AGraphicAccessor&); //コピーコンストラクタ(禁止) DX9AGraphicAccessor& operator =(const DX9AGraphicAccessor&); //代入演算子(禁止) }; //アクセッサを取得 /** * @brief DX9AGraphicAccessor クラスを取得します。 * @param Parent [in]アクセス対象の DX9AGraphic クラスを指定します。 * @return DX9AGraphicAccessor クラスへのポインタを返します。 */ DX9AGraphicAccessor* GetDX9AGraphicAccessor(DX9AGraphic* Parent); } } } #endif |
ヘッダに対する解説では本クラスの使用方法を説明する。
1.DX9AGraphicクラスのインスタンスを生成する
2.Initメソッドを呼び出し、DirectX Graphicsの初期化を行う
3.メッセージループ内でAppIdleメソッドを呼び出し、アイドル処理を行う
(AppIdleメソッドの戻り値がfalseの場合はエラーを表示し終了処理を行う)
4.ウインドウプロシージャ内でMsgProcメソッドを呼び出し、メッセージ処理を行う
具体例 DX9AGraphic g_DXProjectGraphics; LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ g_DXProjectGraphics.MsgProc(hWnd, uMsg, wParam, lParam); switch(uMsg){ case(WM_CLOSE): if(MessageBox(g_DXProjectGraphics.GetHWND(), "終了しますか?", "確認", MB_YESNO)==IDYES){ DestroyWindow(g_DXProjectGraphics.GetHWND()); } return(0); break; case(WM_DESTROY): PostQuitMessage(0); return(0); break; case(WM_SYSKEYDOWN): if(wParam==VK_MENU){ return(0); } break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ //DirectXを初期化 if(!g_DXProjectGraphics.Init(hInstance, "アプリケーション名", MsgProc, 800, 600, 10 * 1024 * 1024, false)){ MessageBox(g_DXProjectGraphics.GetHWND(), "DirectX Graphicsの初期化に失敗しました!", "エラー!", MB_OK | MB_ICONWARNING); return(0); } //メッセージループ MSG msg; do{ if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); } else{ //アイドル処理 if(!g_DXProjectGraphics.AppIdle()){ //エラー:アプリケーションを終了 MessageBox(g_DXProjectGraphics.GetHWND(), "消失したデバイスが復元できません!", "エラー!", MB_OK | MB_ICONWARNING); DestroyWindow(g_DXProjectGraphics.GetHWND()); } } }while(msg.message!=WM_QUIT); return(static_cast < int > (msg.wParam)); } |
……これだけである、というにはいささか複雑か(´Д`)
では、以下にて具体的な説明を行っていく。
ただしそれなりに長いソースであるため、なるべく説明は簡略に行う。
17〜43行目 //文字列テクスチャ /** * @brief 文字列テクスチャの情報が格納されている構造体です。 文字列テクスチャ構造体を定義している。 |
92〜98行目 //アイドル時の処理(必ず実行すること) /** * @brief アイドル時の処理を行います。 AppIdleメソッドを宣言している。 |
100〜109行目 //ウインドウプロシージャ(必ず実行すること) /** * @brief ウインドウプロシージャ内での処理を行います。 MsgProcメソッドを宣言している。 |
159〜203行目 /** * @brief 矩形の描画を行います。 * @param Rect [in]矩形をRECTで指定します。 * @param Color [in]塗り潰す色をD3DCOLORで指定します。 * @param Degree [in]回転する角度を指定します(単位:度) * @param BlendOp [in]ブレンディング処理をD3DBLENDOPで指定します。 * @param SrcBlend [in]転送元のブレンディングモードをD3DBLENDで指定します。 * @param DestBlend [in]転送先のブレンディングモードをD3DBLENDで指定します。 */ void DrawRect(RECT Rect, D3DCOLOR Color, float Degree = 0.0f, D3DBLENDOP BlendOp = D3DBLENDOP_ADD, D3DBLEND SrcBlend = D3DBLEND_SRCALPHA, D3DBLEND DestBlend = D3DBLEND_INVSRCALPHA); //矩形を描画 /** * @brief 文字列の描画を行います。 * @param Text [in]文字列を指定します。 * @param x [in]文字列の描画先のX座標を指定します。 * @param y [in]文字列の描画先のY座標を指定します。 * @param Color [in]文字列の色をD3DCOLORで指定します。 * @param Font [in]文字列のフォントを指定します。 * @param Size [in]文字列のサイズを指定します。 * @param IsBold [in]文字列が太字かを指定します。
DX9AGraphicクラスはDirectX Graphicsのラッパークラスだが、最低限の描画メソッドを実装している。 |
257〜258行目 DX9AGraphic(const DX9AGraphic&); //コピーコンストラクタ(禁止) DX9AGraphic& operator =(const DX9AGraphic&); //代入演算子(禁止)
コピーコンストラクタと代入演算子を「潰している」。 上記のようにヘッダにクラスのコピーコンストラクタと代入演算子の宣言を記述し、 |
261〜309行目 //DirectX Graphicsラッパーへのアクセッサ /** * @brief DX9AGraphic クラスへのアクセッサクラスです。
DX9AGraphicクラスのアクセッサクラス、ならびにアクセッサクラスの取得関数を定義している。 |
ざっと説明はこんなところである。
大分端折ったつもりなのだが、やはり長くなってしまった……(;´Д`)
4.具体例(ソース解説)
次はソース解説である。
#include "stdafx.h" #include "../index.h" #include "DX9AGraphic.h" namespace nsDX9A{ namespace nsGraphics{ namespace nsDX9AGraphic{ //デフォルトコンストラクタ DX9AGraphic::DX9AGraphic(){ m_hWnd = NULL; m_hInst = NULL; m_IsActive = false; m_IsBeginScene = false; m_IsBeginSprite = false; m_IsDeviceLost = false; m_ScreenWidth = 0; m_ScreenHeight = 0; m_IsFullScreen = false; m_IsUseDepthStencil = false; m_IsUseMultiSample = false; ZeroMemory(&m_WindowLastPos, sizeof(m_WindowLastPos)); m_pD3D = NULL; m_pD3DDevice = NULL; ZeroMemory(&m_D3DParamNow, sizeof(m_D3DParamNow)); ZeroMemory(&m_D3DParamWin, sizeof(m_D3DParamWin)); ZeroMemory(&m_D3DParamFull, sizeof(m_D3DParamFull)); m_FmtRenderTextureWin = D3DFMT_UNKNOWN; m_FmtRenderTextureFull = D3DFMT_UNKNOWN; m_pD3DXSprite = NULL; m_pDrawRect = NULL; m_StringTextureNowSize = 0; m_StringTextureMaxSize = 0; } //デストラクタ DX9AGraphic::~DX9AGraphic(){ CleanupApp(); } //初期化(必ず実行すること) bool DX9AGraphic::Init(HINSTANCE hInst, LPCTSTR WindowName, WNDPROC WndProc, int ScreenWidth, int ScreenHeight, unsigned int StringTextureMaxSize, bool IsFullScreen, bool UseDepthStencil, bool UseMultiSample, HICON hIcon, HCURSOR hCursor, HICON hIconSm){ if(m_hInst){ DX9AErrOut("Failed : DX9AGraphic::Init Already Initialized\n"); return(false); } //メンバ変数を初期化 m_hInst = hInst; m_ClassName = WindowName; m_ScreenWidth = ScreenWidth; m_ScreenHeight = ScreenHeight; m_IsFullScreen = IsFullScreen; m_IsUseDepthStencil = UseDepthStencil; m_IsUseMultiSample = UseMultiSample; m_WindowLastPos.top = 0; m_WindowLastPos.left = 0; m_WindowLastPos.right = ScreenWidth; m_WindowLastPos.bottom = ScreenHeight; m_StringTextureMaxSize = StringTextureMaxSize; //アプリケーションを初期化 if(!InitApp(WindowName, WndProc, hIcon, hCursor, hIconSm)){ DX9AErrOut("Failed : DX9AGraphic::Init InitApp\n"); return(false); } //Direct3Dに管理されているオブジェクトを初期化 if(!InitD3D()){ DX9AErrOut("Failed : DX9AGraphic::Init InitD3D\n"); return(false); } return(true); } //アイドル時の処理(必ず実行すること) bool DX9AGraphic::AppIdle(){ if(!m_pD3D || !m_pD3DDevice){ if(m_pD3D){ DX9AErrOut("Failed : DX9AGraphic::AppIdle No D3DDevice\n"); } else{ DX9AErrOut("Failed : DX9AGraphic::AppIdle No D3D\n"); } return(false); } if(!m_IsActive){ return(true); } //文字列テクスチャの管理 DWORD Now = timeGetTime(); map < string, StringTexture > ::iterator it; while(m_StringTextureNowSize > m_StringTextureMaxSize){ it = m_StringTexture.begin(); for(map < string, StringTexture > ::iterator it2=m_StringTexture.begin();it2!=m_StringTexture.end();it2++){ if(Now-it2->second.LastRefTime > Now-it->second.LastRefTime){ it = it2; } if(Now-it2->second.LastRefTime==Now-it->second.LastRefTime){ if(it2->second.Size > it->second.Size){ it = it2; } } } m_StringTextureNowSize -= it->second.Size; SAFE_RELEASE(it->second.Texture); m_StringTexture.erase(it); } //消失したデバイスの復元処理 HRESULT hr; if(m_IsDeviceLost){ //デバイス状態をチェック hr = m_pD3DDevice->TestCooperativeLevel(); if(FAILED(hr)){ if(hr==D3DERR_DEVICELOST){ return(true); //まだ失われている } if(hr!=D3DERR_DEVICENOTRESET){ DX9AErrOut("Failed : DX9AGraphic::AppIdle Unknown Error\n"); return(false); //予期せぬエラー } //Direct3Dに管理されていないオブジェクトを開放 CleanupD3DObject(); //復元を試みる hr = m_pD3DDevice->Reset(&m_D3DParamNow); if(FAILED(hr)){ if(hr==D3DERR_DEVICELOST){ return(true); //まだ失われている } else{ DX9AErrOut("Failed : DX9AGraphic::AppIdle Reset\n"); return(false); //復元に失敗 } } //Direct3Dに管理されていないオブジェクトを再取得 if(!InitD3DObject()){ DX9AErrOut("Failed : DX9AGraphic::AppIdle InitD3DObject\n"); return(false); } } //復元に成功 m_IsDeviceLost = false; } //チェック hr = m_pD3DDevice->TestCooperativeLevel(); if(FAILED(hr)){ if(hr==D3DERR_DEVICELOST){ m_IsDeviceLost = true; } else{ DX9AErrOut("Failed : DX9AGraphic::AppIdle TestCooperativeLevel Failed\n"); return(false); } } return(true); } //ウインドウプロシージャ(必ず呼び出すこと) void DX9AGraphic::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg){ case(WM_ACTIVATE): m_IsActive = (LOWORD(wParam)!=0); break; case(WM_DESTROY): CleanupD3DObject(); CleanupD3D(); break; } UNREFERENCED_PARAMETER(hWnd); UNREFERENCED_PARAMETER(lParam); } //その他(初期化を済ませてから呼び出すこと) //アクティブ状態かを取得 bool DX9AGraphic::IsActive() const{ return(m_IsActive); } //ウインドウハンドルを取得 HWND DX9AGraphic::GetHWND() const{ return(m_hWnd); } //画面の横幅を取得 int DX9AGraphic::GetScreenWidth() const{ return(m_ScreenWidth); } //画面の縦幅を取得 int DX9AGraphic::GetScreenHeight() const{ return(m_ScreenHeight); } //フルスクリーンモードか否かを取得 bool DX9AGraphic::GetFullScreen() const{ return(m_IsFullScreen); } //フルスクリーンモードか否かを設定 bool DX9AGraphic::SetFullScreen(bool IsFullScreen){ if(m_IsFullScreen!=IsFullScreen){ m_IsFullScreen = IsFullScreen; CleanupD3DObject(); if(m_IsFullScreen){ m_D3DParamNow = m_D3DParamFull; GetWindowRect(m_hWnd, &m_WindowLastPos); } else{ m_D3DParamNow = m_D3DParamWin; } HRESULT hr = m_pD3DDevice->Reset(&m_D3DParamNow); if(FAILED(hr)){ if(hr==D3DERR_DEVICELOST){ m_IsDeviceLost = true; } else{ DestroyWindow(m_hWnd); } DX9AErrOut("Failed : DX9AGraphic::SetFullScreen() Reset\n"); return(false); } if(!InitD3DObject()){ DX9AErrOut("Failed : DX9AGraphic::SetFullScreen() InitD3DObject\n"); DestroyWindow(m_hWnd); return(false); } if(m_IsFullScreen){ SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE); } else{ SetWindowLong(m_hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE); SetWindowPos(m_hWnd, HWND_NOTOPMOST, m_WindowLastPos.left, m_WindowLastPos.top, m_WindowLastPos.right - m_WindowLastPos.left, m_WindowLastPos.bottom - m_WindowLastPos.top, SWP_SHOWWINDOW); } } return(true); } //画面を消去 void DX9AGraphic::Clear(D3DCOLOR Color){ m_pD3DDevice->Clear(0, NULL, m_IsUseDepthStencil ? D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL : D3DCLEAR_TARGET, Color, 1.0f, 0); } //画面を更新 void DX9AGraphic::Present(){ EndSprite(); EndScene(); m_pD3DDevice->Present(NULL, NULL, NULL, NULL); } //矩形を描画 void DX9AGraphic::DrawRect(RECT Rect, D3DCOLOR Color, float Degree, D3DBLENDOP BlendOp, D3DBLEND SrcBlend, D3DBLEND DestBlend){ RECT SrcRect = {0, 0, 1, 1}; float ScalingX = static_cast < float > (Rect.right-Rect.left); float ScalingY = static_cast < float > (Rect.bottom-Rect.top); GeneralBlt(m_pDrawRect, Rect.left, Rect.top, Color, &SrcRect, BlendOp, SrcBlend, DestBlend, ScalingX, ScalingY, Degree); } //文字列を描画 void DX9AGraphic::DrawFreeText(const string& Text, int x, int y, D3DCOLOR Color, const string& Font, unsigned int Size, bool IsBold, bool IsItalic, float Degree, D3DBLENDOP BlendOp, D3DBLEND SrcBlend, D3DBLEND DestBlend){ //内部関数用クラス class InnerFunction{ public: //GetGlyphOutline用にエンコード static void EncodeText(const string& Src, wstring& Dest){ Dest.clear(); for(unsigned int i=0;Src[i]!='\0';){ unsigned int ChByte = ((Src[i] >= static_cast < char > (0x81) && Src[i] <= static_cast < char > (0x9F)) || (Src[i] >= static_cast < char > (0xE0) && Src[i] <= static_cast < char > (0xFF))) ? 2 : 1; Dest.push_back(ChByte==2 ? static_cast < BYTE > (Src[i]) * 256 + static_cast < BYTE > (Src[i+1]) : static_cast < BYTE > (Src[i])); i += ChByte; } } //論理和コピー static void* memcpy_or(void* s1, const void* s2, size_t n){ register BYTE* ss1; register const BYTE* ss2; for(ss1=reinterpret_cast < BYTE* > (s1), ss2=reinterpret_cast < const BYTE* > (s2);n!=0;n--){ *ss1++ |= *ss2++; } return(s1); } }; //空文字列の場合 if(Text==""){ return; } //空文字列でない場合 else{ //テキスト(描画時に利用)を生成 char KeyText[1024] = {0}; sprintf(KeyText, "%s_%s_%d_%d", Text.c_str(), Font.c_str(), Size, (IsBold ? 1 : 0)+(IsItalic ? 2 : 0)); //GetGlyphOutline用にエンコード wstring Text2; InnerFunction::EncodeText(Text, Text2); //文字列テクスチャが存在しない場合は作成する if(m_StringTexture.find(KeyText)==m_StringTexture.end()){ //フォントの作成 LOGFONT LF = {Size, 0, 0, 0, (IsBold ? FW_BOLD : 0), (IsItalic ? TRUE : FALSE), 0, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, ""}; strcpy(LF.lfFaceName, Font.c_str()); HFONT hFont; if((hFont = CreateFontIndirect(&LF))==0){ DX9AErrOut("Failed : DX9AGraphic::DrawFreeText() CreateFontIndirect\n"); return; } //デバイスコンテキストを取得 HDC hDC = GetDC(NULL); HFONT OldFont = reinterpret_cast < HFONT > (SelectObject(hDC, hFont)); //テクスチャのサイズを取得→確保 TEXTMETRIC TM; GLYPHMETRICS GM; UINT TexWidth = 0, TexHeight = 0; CONST MAT2 Mat = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; GetTextMetrics(hDC, &TM); TexHeight += TM.tmHeight; for(unsigned int i=0;Text2[i]!=L'\0';i++){ if(Text2[i]==L'\n'){ TexHeight += TM.tmHeight; } else{ GetGlyphOutline(hDC, Text2[i], GGO_METRICS, &GM, 0, NULL, &Mat); TexWidth += GM.gmCellIncX; } } if(IsItalic){ TexWidth += Size / 4; } unsigned int cnt; UINT TmpTexWidth = TexWidth, TmpTexHeight = TexHeight; for(cnt=0;pow(2.0f, static_cast < float > (cnt)) < TexWidth;cnt++); TexWidth = static_cast < UINT > (pow(2.0f, static_cast < float > (cnt))); for(cnt=0;pow(2.0f, static_cast < float > (cnt)) < TexHeight;cnt++); TexHeight = static_cast < UINT > (pow(2.0f, static_cast < float > (cnt))); m_StringTexture.insert(pair < string, StringTexture > (KeyText, StringTexture())); if(FAILED(D3DXCreateTexture(m_pD3DDevice, TexWidth, TexHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &(m_StringTexture.find(KeyText)->second.Texture)))){ DX9AErrOut("Failed : DX9AGraphic::DrawFreeText() D3DXCreateTexture\n"); SelectObject(hDC, OldFont); DeleteObject(hFont); ReleaseDC(NULL, hDC); return; } //フォントビットマップ取得→テクスチャに書き込み DWORD Alpha, Color; D3DLOCKED_RECT LockedRect; BYTE* p = new BYTE[4 * TexWidth * TexHeight]; int Base_X = 0, Base_Y = 0, Bmp_W, Bmp_H, Ofs_X, Ofs_Y; if(FAILED(m_StringTexture.find(KeyText)->second.Texture->LockRect(0, &LockedRect, NULL, D3DLOCK_DISCARD))){ DX9AErrOut("Failed : DX9AGraphic::DrawFreeText() LockRect\n"); SelectObject(hDC, OldFont); DeleteObject(hFont); ReleaseDC(NULL, hDC); SAFE_DELETE_ARRAY(p); return; } FillMemory(LockedRect.pBits , LockedRect.Pitch * TexHeight, 0); for(unsigned int i=0;Text2[i]!=L'\0';i++){ if(Text2[i]==L'\n'){ Base_X = 0; Base_Y += TM.tmHeight; } else{ GetGlyphOutline(hDC, Text2[i], GGO_METRICS, &GM, 0, NULL, &Mat); if(Text2[i]!=32/* 半角スペース */ && Text2[i]!=33088/* 全角スペース */){ GetGlyphOutline(hDC, Text2[i], GGO_GRAY8_BITMAP, &GM, 4 * TexWidth * TexHeight, p, &Mat); Bmp_W = GM.gmBlackBoxX + (4 - (GM.gmBlackBoxX % 4)) % 4; Bmp_H = GM.gmBlackBoxY; Ofs_X = GM.gmptGlyphOrigin.x; Ofs_Y = TM.tmAscent - GM.gmptGlyphOrigin.y; for(int Y=0;Y < static_cast < int > (GM.gmBlackBoxY);Y++){ for(int X=0;X < static_cast < int > (GM.gmBlackBoxX);X++){ Alpha = (255 * p[Bmp_W * Y + X]) / 64; Color = 0x00ffffff | (Alpha << 24); InnerFunction::memcpy_or((BYTE*)LockedRect.pBits+LockedRect.Pitch*(Base_Y+Ofs_Y+Y)+4*(Base_X+Ofs_X+X), &Color, sizeof(Color)); } } } Base_X += GM.gmCellIncX; } } m_StringTexture.find(KeyText)->second.Texture->UnlockRect(0); SAFE_DELETE_ARRAY(p); //文字列テクスチャの情報を設定 m_StringTexture.find(KeyText)->second.Size = 4 * TexWidth * TexHeight; m_StringTexture.find(KeyText)->second.Width = TmpTexWidth; m_StringTexture.find(KeyText)->second.Height = TmpTexHeight; //文字列テクスチャのサイズ > 文字列テクスチャの最大サイズなら、文字列テクスチャの最大サイズを拡張する if(m_StringTexture.find(KeyText)->second.Size > m_StringTextureMaxSize){ m_StringTextureMaxSize = m_StringTexture.find(KeyText)->second.Size; } //文字列テクスチャの合計サイズを増加 m_StringTextureNowSize += m_StringTexture.find(KeyText)->second.Size; //後始末 SelectObject(hDC, OldFont); DeleteObject(hFont); ReleaseDC(NULL, hDC); } //文字列を描画 RECT SrcRect = {0, 0, m_StringTexture.find(KeyText)->second.Width, m_StringTexture.find(KeyText)->second.Height}; GeneralBlt(m_StringTexture.find(KeyText)->second.Texture, x, y, Color, &SrcRect, BlendOp, SrcBlend, DestBlend, 1.0, 1.0, Degree); //文字列テクスチャの最後に参照された時間を更新 m_StringTexture.find(KeyText)->second.LastRefTime = timeGetTime(); } } //汎用転送 void DX9AGraphic::GeneralBlt(LPDIRECT3DTEXTURE9 Texture, int x, int y, D3DCOLOR Color, const RECT* SrcRect, D3DBLENDOP BlendOp, D3DBLEND SrcBlend, D3DBLEND DestBlend, float ScalingX, float ScalingY, float Degree){ if(Texture){ BeginScene(); BeginSprite(); //マトリックスを設定 //変換行列初期化 D3DXMATRIX Mat; D3DXMatrixIdentity(&Mat); //拡大処理 D3DXMATRIX Scaling; D3DXMatrixScaling(&Scaling, ScalingX, ScalingY, 1.0f); //回転処理(中心点:スプライトの中心座標) D3DXMATRIX Rotation, t1, t2; float ox = SrcRect ? static_cast < float > (SrcRect->right - SrcRect->left) * ScalingX / 2.0f : 0.0f; float oy = SrcRect ? static_cast < float > (SrcRect->bottom - SrcRect->top) * ScalingY / 2.0f : 0.0f; D3DXMatrixTranslation(&t1, -ox, -oy, 0.0f); D3DXMatrixRotationZ(&Rotation, D3DXToRadian(Degree)); D3DXMatrixTranslation(&t2, ox, oy, 0.0f); Rotation = t1 * Rotation * t2; //移動処理 D3DXMATRIX Translation; D3DXMatrixTranslation(&Translation, static_cast < float > (x), static_cast < float > (y), 0.0f); //行列を合成 Mat = Scaling * Rotation * Translation; //トランスフォームステートを設定 m_pD3DXSprite->SetTransform(&Mat); //レンダリングステートを設定 m_pD3DDevice->SetRenderState(D3DRS_BLENDOP, BlendOp); m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, SrcBlend); m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, DestBlend); //転送 m_pD3DXSprite->Draw(Texture, SrcRect, NULL, NULL, Color); m_pD3DXSprite->Flush(); } } //描画を開始 void DX9AGraphic::BeginScene(){ if(!m_IsBeginScene){ m_pD3DDevice->BeginScene(); m_IsBeginScene = true; } } //描画を終了 void DX9AGraphic::EndScene(){ if(m_IsBeginScene){ m_pD3DDevice->EndScene(); m_IsBeginScene = false; } } //スプライトの描画を開始 void DX9AGraphic::BeginSprite(){ if(!m_IsBeginSprite){ m_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND); m_IsBeginSprite = true; } } //スプライトの描画を終了 void DX9AGraphic::EndSprite(){ if(m_IsBeginSprite){ m_pD3DXSprite->End(); m_IsBeginSprite = false; } } //アプリケーションを初期化 bool DX9AGraphic::InitApp(LPCTSTR WindowName, WNDPROC WndProc, HICON hIcon, HCURSOR hCursor, HICON hIconSm){ //ウインドウクラスを設定 WNDCLASSEX wc = { sizeof(wc), CS_CLASSDC, WndProc, 0, 0, m_hInst, hIcon, hCursor, NULL, NULL, WindowName, hIconSm}; if(!RegisterClassEx(&wc)){ DX9AErrOut("Failed : DX9AGraphic::InitApp() RegisterClassEx\n"); return(false); } //ウインドウを生成 RECT WindowRect = {0}; RECT DesktopRect = {0}; GetWindowRect(GetDesktopWindow(), &DesktopRect); AdjustWindowRect(&m_WindowLastPos, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, FALSE); m_WindowLastPos.bottom -= m_WindowLastPos.top; m_WindowLastPos.right -= m_WindowLastPos.left; m_WindowLastPos.left = (DesktopRect.right - m_WindowLastPos.right) / 2; m_WindowLastPos.top = (DesktopRect.bottom - m_WindowLastPos.bottom) / 2; m_WindowLastPos.bottom += m_WindowLastPos.top; m_WindowLastPos.right += m_WindowLastPos.left; if(m_IsFullScreen){ //フルスクリーンモード WindowRect.top = 0; WindowRect.left = 0; WindowRect.right = m_ScreenWidth; WindowRect.bottom = m_ScreenHeight; } else{ //ウインドウモード WindowRect.top = m_WindowLastPos.top; WindowRect.left = m_WindowLastPos.left; WindowRect.right = m_WindowLastPos.right - m_WindowLastPos.left; WindowRect.bottom = m_WindowLastPos.bottom - m_WindowLastPos.top; } m_hWnd = CreateWindow(WindowName, WindowName, m_IsFullScreen ? WS_POPUP : WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, WindowRect.left, WindowRect.top, WindowRect.right, WindowRect.bottom, NULL, NULL, m_hInst, NULL); if(!m_hWnd){ DX9AErrOut("Failed : DX9AGraphic::InitApp() CreateWindow\n"); return(false); } ShowWindow(m_hWnd, SW_SHOW); UpdateWindow(m_hWnd); return(true); } //Direct3Dに管理されているオブジェクトを初期化 bool DX9AGraphic::InitD3D(){ //Direct3D9オブジェクトを初期化 m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(!m_pD3D){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() Direct3DCreate9\n"); return(false); } //デバイスの設定を選択 UINT Adapter; D3DDEVTYPE Device; if(!SelectD3DDevice(Adapter, Device)){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() SelectD3DDevice\n"); return(false); } //Direct3DDevice9オブジェクトを初期化 if(m_IsFullScreen){ m_D3DParamNow = m_D3DParamFull; } else{ m_D3DParamNow = m_D3DParamWin; } /* ↓CheckDeviceCapsメソッドの変更に伴いこちらも変更 if(FAILED(m_pD3D->CreateDevice(Adapter, Device, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(Adapter, Device, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() CreateDevice\n"); return(false); } } */ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_MIXED_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() CreateDevice\n"); return(false); } } } } /* ↑CheckDeviceCapsメソッドの変更に伴いこちらも変更 */ //ビューポートを設定 D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = m_D3DParamNow.BackBufferWidth; vp.Height = m_D3DParamNow.BackBufferHeight; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; if(FAILED(m_pD3DDevice->SetViewport(&vp))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() SetViewport\n"); return(false); } //テクスチャを初期化 if(FAILED(D3DXCreateTexture(m_pD3DDevice, 2, 2, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pDrawRect))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() D3DXCreateTexture\n"); return(false); } else{ D3DLOCKED_RECT LockedRect; if(FAILED(m_pDrawRect->LockRect(0, &LockedRect, NULL, D3DLOCK_DISCARD))){ if(FAILED(m_pDrawRect->LockRect(0, &LockedRect, NULL, 0))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() LockRect\n"); return(false); } } D3DCOLOR RectColor = D3DCOLOR_ARGB(255, 255, 255, 255); for(int y=0;y < 2;y++){ for(int x=0;x < 2;x++){ memcpy(reinterpret_cast < BYTE* > (LockedRect.pBits)+LockedRect.Pitch*y+4*x, &RectColor, sizeof(RectColor)); } } m_pDrawRect->UnlockRect(0); } //スプライトを初期化 if(FAILED(D3DXCreateSprite(m_pD3DDevice, &m_pD3DXSprite))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() D3DXCreateSprite\n"); return(false); } return(true); } //デバイスの設定を選択 bool DX9AGraphic::SelectD3DDevice(UINT& Adapter, D3DDEVTYPE& Device){ HRESULT hr; //アダプタを選択 Adapter = D3DADAPTER_DEFAULT; //デバイスの能力を取得 D3DCAPS9 Caps; //HALデバイスをチェック Device = D3DDEVTYPE_HAL; hr = m_pD3D->GetDeviceCaps(Adapter, Device, &Caps); if(FAILED(hr) || !CheckDeviceCaps(&Caps)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() GetDeviceCaps HAL\n"); //REFデバイスをチェック Device = D3DDEVTYPE_REF; hr = m_pD3D->GetDeviceCaps(Adapter, Device, &Caps); if(FAILED(hr) || !CheckDeviceCaps(&Caps)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() GetDeviceCaps REF\n"); return(false); } } //現在のディスプレイのフォーマットなどを取得 D3DDISPLAYMODE DMode; if(FAILED(m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DMode))){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() GetAdapterDisplayMode\n"); return(false); } //ディスプレイとバックバッファのフォーマットを調査 if(!SelectAdapterFormat(Adapter, Device, DMode)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() SelectAdapterFormat\n"); return(false); } //深度/ステンシルバッファのフォーマットを調査 if(m_IsUseDepthStencil){ if(!SelectDepthStencilFormat(Adapter, Device, DMode)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() SelectDepthStencilFormat\n"); return(false); } } //レンダリングテクスチャのフォーマットを調査 if(!SelectRenderTextureFormat(Adapter, Device, DMode)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() SelectRenderTextureFormat\n"); return(false); } //フルシーンアンチエイリアシングを調査 if(m_IsUseMultiSample){ if(!SelectMultiSampleType(Adapter, Device)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() SelectMultiSampleType\n"); return(false); } } //ディスプレイモードを調査 if(!SelectDisplayMode(Adapter)){ DX9AErrOut("Failed : DX9AGraphic::SelectD3DDevice() SelectDisplayMode\n"); return(false); } return(true); } //デバイスの能力をチェック bool DX9AGraphic::CheckDeviceCaps(D3DCAPS9* Caps){ /* ↓EeePC等の低スペックPCで無意味にREFに切り替えられてしまう原因、とりあえずはコメントアウトで対応! //プリミティブ数 if(Caps->MaxPrimitiveCount < 0xFFFF){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() MaxPrimitiveCount < 0xFFFF\n"); return(false); } //インデックス数 if(Caps->MaxVertexIndex < 0xFFFF){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() MaxVertexIndex < 0xFFFF\n"); return(false); } //頂点シェーダバージョン if(Caps->VertexShaderVersion < D3DVS_VERSION(1, 1)){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() VertexShaderVersion < D3DVS_VERSION(1, 1)\n"); return(false); } //ピクセルシェーダバージョン if(Caps->PixelShaderVersion < D3DVS_VERSION(1, 1)){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() PixelShaderVersion < D3DVS_VERSION(1, 1)\n"); return(false); } ↑EeePC等の低スペックPCで無意味にREFに切り替えられてしまう原因、とりあえずはコメントアウトで対応! */ UNREFERENCED_PARAMETER(Caps); return(true); } //ディスプレイとバックバッファのフォーマットを調査 bool DX9AGraphic::SelectAdapterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode){ HRESULT hr = S_OK; //希望するフォーマット D3DFORMAT FmtDisplay[] = FMT_DISPLAY; //ウインドウモード m_D3DParamWin.BackBufferCount = 1; m_D3DParamWin.SwapEffect = D3DSWAPEFFECT_DISCARD; m_D3DParamWin.hDeviceWindow = m_hWnd; m_D3DParamWin.Windowed = TRUE; m_D3DParamWin.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; m_D3DParamWin.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; for(int i=0;i < sizeof(FmtDisplay)/sizeof(FmtDisplay[0]);i++){ hr = m_pD3D->CheckDeviceType(Adapter, Device, DMode.Format, FmtDisplay[i], TRUE); if(SUCCEEDED(hr)){ m_D3DParamWin.BackBufferFormat = FmtDisplay[i]; break; } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectAdapterFormat() CheckDeviceType Window\n"); return(false); } //フルスクリーンモード m_D3DParamFull.BackBufferCount = 1; m_D3DParamFull.SwapEffect = D3DSWAPEFFECT_DISCARD; m_D3DParamFull.hDeviceWindow = m_hWnd; m_D3DParamFull.Windowed = FALSE; m_D3DParamFull.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; m_D3DParamFull.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; for(int i=0;i < sizeof(FmtDisplay)/sizeof(FmtDisplay[0]);i++){ hr = m_pD3D->CheckDeviceType(Adapter, Device, FmtDisplay[i], FmtDisplay[i], FALSE); if(SUCCEEDED(hr)){ m_D3DParamFull.BackBufferFormat = FmtDisplay[i]; break; } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectAdapterFormat() CheckDeviceType FullScreen\n"); return(false); } return(true); } //深度/ステンシルバッファのフォーマットを調査 bool DX9AGraphic::SelectDepthStencilFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode){ HRESULT hr = S_OK; //希望するフォーマット D3DFORMAT FmtDepthStencil[] = FMT_DEPTHSTENCIL; //ウインドウモード for(int i=0;i < sizeof(FmtDepthStencil)/sizeof(FmtDepthStencil[0]);i++){ hr = m_pD3D->CheckDeviceFormat(Adapter, Device, DMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, FmtDepthStencil[i]); if(SUCCEEDED(hr)){ hr = m_pD3D->CheckDepthStencilMatch(Adapter, Device, DMode.Format, m_D3DParamWin.BackBufferFormat, FmtDepthStencil[i]); if(SUCCEEDED(hr)){ m_D3DParamWin.EnableAutoDepthStencil = TRUE; m_D3DParamWin.AutoDepthStencilFormat = FmtDepthStencil[i]; break; } } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectDepthStencilFormat() Window\n"); return(false); } //フルスクリーンモード for(int i=0;i < sizeof(FmtDepthStencil)/sizeof(FmtDepthStencil[0]);i++){ hr = m_pD3D->CheckDeviceFormat(Adapter, Device, m_D3DParamFull.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, FmtDepthStencil[i]); if(SUCCEEDED(hr)){ hr = m_pD3D->CheckDepthStencilMatch(Adapter, Device, m_D3DParamFull.BackBufferFormat, m_D3DParamFull.BackBufferFormat, FmtDepthStencil[i]); if(SUCCEEDED(hr)){ m_D3DParamFull.EnableAutoDepthStencil = TRUE; m_D3DParamFull.AutoDepthStencilFormat = FmtDepthStencil[i]; break; } } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectDepthStencilFormat() FullScreen\n"); return(false); } return(true); } //レンダリングテクスチャのフォーマットを調査 bool DX9AGraphic::SelectRenderTextureFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE DMode){ HRESULT hr = S_OK; //希望するフォーマット D3DFORMAT FmtRenderTexture[] = FMT_RENDERTEXTURE; //ウインドウモード m_FmtRenderTextureWin = D3DFMT_UNKNOWN; for(int i=0;i < sizeof(FmtRenderTexture)/sizeof(FmtRenderTexture[0]);i++){ hr = m_pD3D->CheckDeviceFormat(Adapter, Device, DMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, FmtRenderTexture[i]); if(SUCCEEDED(hr)){ if(m_D3DParamWin.EnableAutoDepthStencil==TRUE){ hr = m_pD3D->CheckDepthStencilMatch(Adapter, Device, DMode.Format, FmtRenderTexture[i], m_D3DParamWin.AutoDepthStencilFormat); if(SUCCEEDED(hr)){ m_FmtRenderTextureWin = FmtRenderTexture[i]; break; } } else{ m_FmtRenderTextureWin = FmtRenderTexture[i]; break; } } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectRenderTextureFormat() Window\n"); return(false); } //フルスクリーンモード m_FmtRenderTextureFull = D3DFMT_UNKNOWN; for(int i=0;i < sizeof(FmtRenderTexture)/sizeof(FmtRenderTexture[0]);i++){ hr = m_pD3D->CheckDeviceFormat(Adapter, Device, m_D3DParamFull.BackBufferFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, FmtRenderTexture[i]); if(SUCCEEDED(hr)){ if(m_D3DParamFull.EnableAutoDepthStencil==TRUE){ hr = m_pD3D->CheckDepthStencilMatch(Adapter, Device, m_D3DParamFull.BackBufferFormat, FmtRenderTexture[i], m_D3DParamFull.AutoDepthStencilFormat); if(SUCCEEDED(hr)){ m_FmtRenderTextureFull = FmtRenderTexture[i]; break; } } else{ m_FmtRenderTextureFull = FmtRenderTexture[i]; break; } } } if(FAILED(hr)){ DX9AErrOut("Failed : DX9AGraphic::SelectRenderTextureFormat() FullScreen\n"); return(false); } return(true); } //フルシーンアンチエイリアシングを調査 bool DX9AGraphic::SelectMultiSampleType(UINT Adapter, D3DDEVTYPE Device){ //希望するフォーマット D3DMULTISAMPLE_TYPE MST[] = TYPE_MULTISAMPLE; //ウインドウモード for(int i=0;i < sizeof(MST)/sizeof(MST[0]);i++){ if(FAILED(m_pD3D->CheckDeviceMultiSampleType(Adapter, Device, m_D3DParamWin.BackBufferFormat, TRUE, MST[i], NULL))){ continue; } if(m_D3DParamWin.EnableAutoDepthStencil==TRUE){ if(FAILED(m_pD3D->CheckDeviceMultiSampleType(Adapter, Device, m_D3DParamWin.AutoDepthStencilFormat, TRUE, MST[i], NULL))){ continue; } } m_D3DParamWin.MultiSampleType = MST[i]; m_D3DParamWin.MultiSampleQuality = 0; break; } //フルスクリーンモード for(int i=0;i < sizeof(MST)/sizeof(MST[0]);i++){ if(FAILED(m_pD3D->CheckDeviceMultiSampleType(Adapter, Device, m_D3DParamFull.BackBufferFormat, FALSE, MST[i], NULL))){ continue; } if(m_D3DParamFull.EnableAutoDepthStencil==TRUE){ if(FAILED(m_pD3D->CheckDeviceMultiSampleType(Adapter, Device, m_D3DParamFull.AutoDepthStencilFormat, FALSE, MST[i], NULL))){ continue; } } m_D3DParamFull.MultiSampleType = MST[i]; m_D3DParamFull.MultiSampleQuality = 0; break; } return(true); } //ディスプレイモードを調査 bool DX9AGraphic::SelectDisplayMode(UINT Adapter){ //ウインドウモード(調査不要) //フルスクリーンモード int level = INT_MAX; D3DDISPLAYMODE DMode = {0, 0, 0, D3DFMT_UNKNOWN}; int Num = m_pD3D->GetAdapterModeCount(Adapter, m_D3DParamFull.BackBufferFormat); for(int i=0;i < Num;i++){ //ディスプレイモードの列挙 D3DDISPLAYMODE DM; m_pD3D->EnumAdapterModes(Adapter, m_D3DParamFull.BackBufferFormat, i, &DM); int l = abs(m_ScreenWidth - static_cast < int > (DM.Width)) + abs(m_ScreenHeight - static_cast < int > (DM.Height)); if(l < level){ //より適切なモードを選択 DMode = DM; level = l; } } if(DMode.Format==D3DFMT_UNKNOWN){ DX9AErrOut("Failed : DX9AGraphic::SelectDisplayMode()\n"); return(false); } m_D3DParamFull.BackBufferWidth = DMode.Width; m_D3DParamFull.BackBufferHeight = DMode.Height; return(true); } //Direct3Dに管理されていないオブジェクトを初期化 bool DX9AGraphic::InitD3DObject(){ //スプライトの管理 if(m_pD3DXSprite){ m_pD3DXSprite->OnResetDevice(); } //レンダリングステートを設定 //Zバッファ m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, m_D3DParamNow.EnableAutoDepthStencil ? D3DZB_TRUE : D3DZB_FALSE); //マルチサンプリング m_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, m_D3DParamNow.MultiSampleType!=D3DMULTISAMPLE_NONE ? TRUE : FALSE); return(true); } //Direct3Dに管理されていないオブジェクトの終了処理 bool DX9AGraphic::CleanupD3DObject(){ if(m_pD3DXSprite){ m_pD3DXSprite->OnLostDevice(); } return(true); } //Direct3Dに管理されているオブジェクトの終了処理 bool DX9AGraphic::CleanupD3D(){ for(map < string, StringTexture > ::iterator it=m_StringTexture.begin();it!=m_StringTexture.end();it++){ SAFE_RELEASE(it->second.Texture); } SAFE_RELEASE(m_pDrawRect); SAFE_RELEASE(m_pD3DXSprite); SAFE_RELEASE(m_pD3DDevice); SAFE_RELEASE(m_pD3D); return(true); } //アプリケーションの終了処理 bool DX9AGraphic::CleanupApp(){ UnregisterClass(m_ClassName.c_str(), m_hInst); return(true); } //デフォルトコンストラクタ DX9AGraphicAccessor::DX9AGraphicAccessor(){ Outer = NULL; } //親エンジンを設定 void DX9AGraphicAccessor::SetParent(DX9AGraphic* Parent){ Outer = Parent; } //Direct3D9オブジェクトを取得 LPDIRECT3D9 DX9AGraphicAccessor::GetD3D9(){ return(Outer->m_pD3D); } //スプライトオブジェクトを取得 LPD3DXSPRITE DX9AGraphicAccessor::GetD3DXSprite(){ return(Outer->m_pD3DXSprite); } //Direct3DDevice9オブジェクトを取得 LPDIRECT3DDEVICE9 DX9AGraphicAccessor::GetD3D9Device(){ return(Outer->m_pD3DDevice); } //アクセッサ static DX9AGraphicAccessor DX9ASingletonDX9AGraphicAccessor; //アクセッサを取得 DX9AGraphicAccessor* GetDX9AGraphicAccessor(DX9AGraphic* Parent){ DX9ASingletonDX9AGraphicAccessor.SetParent(Parent); return(&DX9ASingletonDX9AGraphicAccessor); } } } } |
コメントも付けているしググれば大体分かると思うが、一応いくつか補足しておく。
98〜116行目 //文字列テクスチャの管理 DWORD Now = timeGetTime(); map < string, StringTexture > ::iterator it; while(m_StringTextureNowSize > m_StringTextureMaxSize){ it = m_StringTexture.begin(); for(map < string, StringTexture > ::iterator it2=m_StringTexture.begin();it2!=m_StringTexture.end();it2++){ if(Now-it2->second.LastRefTime > Now-it->second.LastRefTime){ it = it2; } if(Now-it2->second.LastRefTime==Now-it->second.LastRefTime){ if(it2->second.Size > it->second.Size){ it = it2; } } } m_StringTextureNowSize -= it->second.Size; SAFE_RELEASE(it->second.Texture); m_StringTexture.erase(it); } アイドル時に文字列テクスチャの管理を行っている。 |
284〜306行目 //内部関数用クラス class InnerFunction{ public: //GetGlyphOutline用にエンコード static void EncodeText(const string& Src, wstring& Dest){ Dest.clear(); for(unsigned int i=0;Src[i]!='\0';){ unsigned int ChByte = ((Src[i] >= static_cast < char > (0x81) && Src[i] <= static_cast < char > (0x9F)) || (Src[i] >= static_cast < char > (0xE0) && Src[i] <= static_cast < char > (0xFF))) ? 2 : 1; Dest.push_back(ChByte==2 ? static_cast < BYTE > (Src[i]) * 256 + static_cast < BYTE > (Src[i+1]) : static_cast < BYTE > (Src[i])); i += ChByte; } } //論理和コピー static void* memcpy_or(void* s1, const void* s2, size_t n){ register BYTE* ss1; register const BYTE* ss2; for(ss1=reinterpret_cast < BYTE* > (s1), ss2=reinterpret_cast < const BYTE* > (s2);n!=0;n--){ *ss1++ |= *ss2++; } return(s1); } }; DrawFreeTextメソッド内でローカル関数を定義している。 |
582〜600行目 /* ↓CheckDeviceCapsメソッドの変更に伴いこちらも変更 if(FAILED(m_pD3D->CreateDevice(Adapter, Device, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(Adapter, Device, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() CreateDevice\n"); return(false); } } */ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_MIXED_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, m_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_D3DParamNow, &m_pD3DDevice))){ DX9AErrOut("Failed : DX9AGraphic::InitD3D() CreateDevice\n"); return(false); } } } } /* ↑CheckDeviceCapsメソッドの変更に伴いこちらも変更 */ 本来はコメントアウトの内容通り、ハードウェアアクセラレーションでのデバイス作成→ソフトウェアアクセラレーションでのデバイス作成を試みていた。 |
714〜740行目 //デバイスの能力をチェック bool DX9AGraphic::CheckDeviceCaps(D3DCAPS9* Caps){ /* ↓EeePC等の低スペックPCで無意味にREFに切り替えられてしまう原因、とりあえずはコメントアウトで対応! //プリミティブ数 if(Caps->MaxPrimitiveCount<0xFFFF){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() MaxPrimitiveCount<0xFFFF\n"); return(false); } //インデックス数 if(Caps->MaxVertexIndex<0xFFFF){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() MaxVertexIndex<0xFFFF\n"); return(false); } //頂点シェーダバージョン if(Caps->VertexShaderVersion < D3DVS_VERSION(1, 1)){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() VertexShaderVersion < D3DVS_VERSION(1, 1)\n"); return(false); } //ピクセルシェーダバージョン if(Caps->PixelShaderVersion < D3DVS_VERSION(1, 1)){ DX9AErrOut("Failed : DX9AGraphic::CheckDeviceCaps() PixelShaderVersion < D3DVS_VERSION(1, 1)\n"); return(false); } /* ↑EeePC等の低スペックPCで無意味にREFに切り替えられてしまう原因、とりあえずはコメントアウトで対応! */ UNREFERENCED_PARAMETER(Caps); return(true); } コメントアウトの理由は582〜600行目と同じ、本来は定数化なりマクロ化なりで対応してコメントアウトで誤魔化すべきではない。 |
746〜747、796〜797行目 //希望するフォーマット D3DFORMAT FmtDisplay[] = FMT_DISPLAY; //希望するフォーマット D3DFORMAT FmtDepthStencil[] = FMT_DEPTHSTENCIL; //希望するフォーマット D3DFORMAT FmtRenderTexture[] = FMT_RENDERTEXTURE; //希望するフォーマット D3DMULTISAMPLE_TYPE MST[] = TYPE_MULTISAMPLE; 上記ソースコードにおける定数は、別のヘッダファイルにて以下のように定義されている。 //DirectX Graphics //希望するフォーマット(必ず希望順で並べること) /** * @brief ディスプレイならびにバックバッファの希望です。 * * 必ず希望順で並べてください。 */ #define FMT_DISPLAY {D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5} /** * @brief 深度/ステンシルバッファの希望です。 * * 必ず希望順で並べてください。 */ #define FMT_DEPTHSTENCIL {D3DFMT_D24S8} /** * @brief レンダリングテクスチャの希望です。 * * 必ず希望順で並べてください。 */ #define FMT_RENDERTEXTURE {D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5} /** * @brief フルシーンアンチエイリアシングの希望です。 * * 必ず希望順で並べてください。 */ #define TYPE_MULTISAMPLE {D3DMULTISAMPLE_4_SAMPLES, D3DMULTISAMPLE_3_SAMPLES, D3DMULTISAMPLE_2_SAMPLES, D3DMULTISAMPLE_NONMASKABLE} 見れば分かるとおり、定数の配列を定義している。 |
とりあえずざっとした説明を行ってみた、APIなどの説明は省略(ググれば分かるさ!)
個人的にプログラミングのTipsを語る上で重要なのは、APIの解説よりは「何故そんな形で実装しているのか?」だと思う。
前者はMSDNなりAPIの解説を行っているページに行けば簡単に分かることだが、後者は当人が説明しない限り絶対に分からない。
なので、今後もこういった書き方をしていく予定である。1行1行に解説を加えるようなことをするのは、めんどいしね!(それが本音か)
……以上で本項は終了である、お疲れ様でした(´Д`)
次回はちょっと浮気をしてファイルIO周りの解説を行う予定、でもって再びDirectX Graphicsに戻る予定である。