(とても長いです)基礎的な3Dプログラミングで、例外が発生する
Posted: 2013年7月23日(火) 15:53
基礎的な3Dプログラミングをしています。
そこで、本に書いているとおりソースコードを入れましたが、
今やっているところからは、サンプルがCDに付属されていなくて、コンパイルはできたのですが、
実行すると例外が発生して、なおかつ予測していた、立方体が描画されません。
本に付属していたサンプルでは、この章のひとつまえまでがあり、いまのところはなく、
どこに処理を入れればいいのかが、自分なりにいれました。
どこに入れればいいのか迷っているのは コメントの 8-2 ~ 8-6です。
そこで、この8-2 ~ 8-6を適切な場所に入れてくれると助かります。
上のとおり、2つ質問があります。
ひとつは例外が発生するので、どこがまずいのか。
ふたつめは、8-2 ~ 8-6 をどこの処理に入れればいいのかをアドバイスしてください。
以下、ソースコード全部となり、とてもながいです。
そこで、本に書いているとおりソースコードを入れましたが、
今やっているところからは、サンプルがCDに付属されていなくて、コンパイルはできたのですが、
実行すると例外が発生して、なおかつ予測していた、立方体が描画されません。
本に付属していたサンプルでは、この章のひとつまえまでがあり、いまのところはなく、
どこに処理を入れればいいのかが、自分なりにいれました。
どこに入れればいいのか迷っているのは コメントの 8-2 ~ 8-6です。
そこで、この8-2 ~ 8-6を適切な場所に入れてくれると助かります。
上のとおり、2つ質問があります。
ひとつは例外が発生するので、どこがまずいのか。
ふたつめは、8-2 ~ 8-6 をどこの処理に入れればいいのかをアドバイスしてください。
以下、ソースコード全部となり、とてもながいです。
// [2013 07 16] DirectX 3D.cpp : アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#include "[2013 07 16] DirectX 3D.h"
/*----------------------------------------------------------
DirectX9実践プログラミング
DirectX Graphicsサンプル
DXGSample01.cpp
「基本的なウインドウ・アプリケーション」
(C) 2003 NARITA, Takuro
E-Mail narita@a1.mbn.or.jp
--------------------------------------------------------------*/
#define WIN32_LEAN_AND_MEAN // ヘッダーからあまり使われない関数を省く
#include <windows.h>
#include <tchar.h>
#include <d3dx9.h>
#include <dxerr9.h>
#include "resource.h"
#define RELEASE(x) if(x){x->Release();x=NULL;}
/*-------------------------------------------
グローバル変数(アプリケーション関連)
--------------------------------------------*/
HINSTANCE g_hInstance = NULL; // インスタンス・ハンドル
HWND g_hWindow = NULL; // ウインドウ・ハンドル
HMENU g_hMenu = NULL; // メニュー・ハンドル
TCHAR g_szAppTitle[] = _T("DirectX 9.0 Graphics Sample01");
TCHAR g_szWndClass[] = _T("DX9GS01");
RECT g_rectWindow;
// 起動時の描画領域サイズ
bool g_bWindow = true; // true:ウィンドウモード false:フルスクリーンモード
SIZE g_sizeWindowMode = { 640, 480 }; // ウインドウ・モード
SIZE g_sizeFullMode = { 1024, 768 }; // フルスクリーン・モード
D3DFORMAT g_formatFull = D3DFMT_X8R8G8B8; // ディスプレイ(バック・バッファ)・フォーマット
// デバイス設定の希望値
D3DFORMAT g_fmtDisplay[] = // 希望するディスプレイ・フォーマット
{ D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5 };
D3DFORMAT g_fmtRendTexter[] = // 希望するレンダリング・テクスチャのフォーマット
{ D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5 };
D3DFORMAT g_fmtDepthStencil = D3DFMT_D24S8; // 希望する深度/ステンシルバッファのフォーマット(D3DFMT_UNKNOWNで未使用)
D3DMULTISAMPLE_TYPE g_MultiSampleType[] =
{ D3DMULTISAMPLE_4_SAMPLES, D3DMULTISAMPLE_NONMASKABLE };
// 希望するマルチ・サンプリングのタイプ
UINT g_Interval = D3DPRESENT_INTERVAL_IMMEDIATE; // 希望するPresent処理の実行レート
// アプリケーションの動作フラグ
bool g_bActive = false; // アクティブ状態
/*-------------------------------------------
グローバル変数(DirectX関連)
--------------------------------------------*/
// インターフェイス
LPDIRECT3D9 g_pD3D = NULL; // Direct3Dインターフェイス
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // Direct3DDeviceインターフェイス
D3DPRESENT_PARAMETERS g_D3DPP; // D3DDeviceの設定
D3DPRESENT_PARAMETERS g_D3DPPWindow; // D3DDeviceの設定(ウインドウ・モード用)
D3DPRESENT_PARAMETERS g_D3DPPFull; // D3DDeviceの設定(フルスクリーン・モード用)
D3DFORMAT g_fmtRendTexterWindow; // レンダリング・テクスチャのフォーマット(ウインドウ用)
D3DFORMAT g_fmtRendTexterFull; // レンダリング・テクスチャのフォーマット(フルスクリーン用)
bool g_bDeviceLost = false; // デバイスの消失フラグ
// スプライト機能
LPD3DXSPRITE g_pD3DXSprite = NULL; // スプライト
LPDIRECT3DTEXTURE9 g_pD3DTexture = NULL; // スプライトに使うテクスチャ
TCHAR g_szSpriteFile[] = _T("canvas.png"); // スプライトに使う画像ファイル
// フォント機能
LPD3DXFONT g_pD3DXFont = NULL; // D3DXFontインターフェイス
// マウス・カーソル機能
TCHAR g_szCursorFile[] = _T("Cursor.dds"); // カーソルに使う画像ファイル
// 画面キャプチャ機能
TCHAR g_szFontBufferFile[] = _T("save.bmp"); // キャプチャ画面の画像ファイル
// 8.基本的な3Dグラフィックスのプログラミング
struct XYZBuffer
{
FLOAT x,y,z;
};
struct ColBuffer
{
D3DCOLOR color;
};
D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
D3DDECL_END()
};
LPDIRECT3DVERTEXDECLARATION9 g_pVertexDeclaration;
LPDIRECT3DVERTEXBUFFER9 g_pD3DVBXYZBuffer; // XYZBuffer の頂点バッファ
LPDIRECT3DVERTEXBUFFER9 g_pD3DVBColBuffer; // ColBuffer の頂点バッファ
LPDIRECT3DINDEXBUFFER9 g_pD3DIBuffer;
LPDIRECT3DVERTEXSHADER9 g_pVertexShader; // 頂点シェーダを受け取る変数
LPDIRECT3DPIXELSHADER9 g_pPixelShader; // ピクセルシェーダを受け取る変数
/*-------------------------------------------
関数定義
--------------------------------------------*/
LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam);
/*-------------------------------------------
アプリケーション初期化(最初に一度だけ呼ばれる)
--------------------------------------------*/
HRESULT InitApp(HINSTANCE hInst)
{
// アプリケーションのインスタンス・ハンドルを保存
g_hInstance = hInst;
// IMEを禁止する
// ImmDisableIME(-1);
// ウインドウ・クラスの登録
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = MainWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_hInstance;
wcex.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_MY20130716DIRECTX3D));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY20130716DIRECTX3D);
wcex.lpszClassName = g_szWndClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
if (!RegisterClassEx(&wcex))
return DXTRACE_ERR("InitApp", GetLastError());
// メイン・ウインドウ作成(ウインドウ・モード用)
g_rectWindow.top = 0;
g_rectWindow.left = 0;
g_rectWindow.right = g_sizeWindowMode.cx;
g_rectWindow.bottom = g_sizeWindowMode.cy;
AdjustWindowRect( &g_rectWindow, WS_OVERLAPPEDWINDOW, TRUE);
g_rectWindow.right = g_rectWindow.right - g_rectWindow.left;
g_rectWindow.bottom = g_rectWindow.bottom - g_rectWindow.top;
g_rectWindow.top = 0;
g_rectWindow.left = 0;
RECT rect;
if( g_bWindow )
{
// (ウィンドウモード用)
rect.top = CW_USEDEFAULT;
rect.left = CW_USEDEFAULT;
rect.right = g_rectWindow.right;
rect.bottom = g_rectWindow.bottom;
}
else
{
// (フクスクリーン・モード用)
rect.top = 0;
rect.left = 0;
rect.right = g_sizeFullMode.cx;
rect.bottom = g_sizeFullMode.cy;
g_hMenu = LoadMenu( g_hInstance, MAKEINTRESOURCE(IDR_MENU1) );
}
g_hWindow = CreateWindow(g_szWndClass, g_szAppTitle,
g_bWindow ? WS_OVERLAPPEDWINDOW : WS_POPUP,
rect.left, rect.top, rect.right, rect.bottom,
NULL, NULL, hInst, NULL);
if (g_hWindow == NULL)
return DXTRACE_ERR("InitApp", GetLastError());
// ウインドウ表示
ShowWindow(g_hWindow, SW_SHOWNORMAL);
UpdateWindow(g_hWindow);
return S_OK;
}
/*-------------------------------------------
適切なDirect3DDeviceやフォーマットの選択
--------------------------------------------*/
HRESULT CheckDeviceCaps(D3DCAPS9 *Caps); // デバイス能力のチェック
HRESULT SelectAdapterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode); // ディスプレイとバック・バッファのフォーマットの調査
HRESULT SelectDepthStencilFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode); // 深度/ステンシル・バッファのフォーマットを調べる
HRESULT SelectRenderTexterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode); // レンダリング・テクスチャのフォーマットを調べる
HRESULT SelectMultiSampleType(UINT Adapter, D3DDEVTYPE Device); // フルシーン・アンチエイリアシングを調べる
HRESULT SelectDisplayMode(UINT Adapter); // ディスプレイ・モードを調べる
HRESULT SelectD3DDevice(UINT &Adapter, D3DDEVTYPE &Device)
{
// アダプタの選択
Adapter = D3DADAPTER_DEFAULT; // プライマリ・ディスプレイ・アダプタ
// デバイス能力の取得
D3DCAPS9 Caps; // 能力を受け取るD3DCAPS9構造体
HRESULT hr;
Device = D3DDEVTYPE_HAL; // HALデバイスをチェック
hr = g_pD3D->GetDeviceCaps(Adapter, Device, &Caps);
if (FAILED(hr) || FAILED(CheckDeviceCaps(&Caps)))
{
DXTRACE_ERR("SelectD3DDevice CheckDeviceCaps HAL", E_FAIL);
Device = D3DDEVTYPE_REF; // REFデバイスをチェック
hr = g_pD3D->GetDeviceCaps(Adapter, Device, &Caps);
if (FAILED(hr) || FAILED(CheckDeviceCaps(&Caps)))
return DXTRACE_ERR("SelectD3DDevice CheckDeviceCaps REF", E_FAIL);
}
// 現在のディスプレイのフォーマットなどを取得しておく
D3DDISPLAYMODE dmode;
hr = g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dmode);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice GetAdapterDisplayMode", hr);
// ディスプレイとバック・バッファのフォーマットの調査
hr = SelectAdapterFormat(Adapter, Device, dmode);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice SelectAdapterFormat", hr);
// 深度/ステンシル・バッファのフォーマットの調査
if (g_fmtDepthStencil != D3DFMT_UNKNOWN)
{
hr = SelectDepthStencilFormat(Adapter, Device, dmode);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice SelectDepthStencilFormat", hr);
}
// レンダリング・テクスチャのフォーマットを調べる
hr = SelectRenderTexterFormat(Adapter, Device, dmode);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice SelectRenderTexterFormat", hr);
// その他のフォーマットを調べる(なし)
// フルシーン・アンチエイリアシングを調べる
hr = SelectMultiSampleType(Adapter, Device);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice SelectMultiSampleType", hr);
// ディスプレイ・モードを調べる
hr = SelectDisplayMode(Adapter);
if (FAILED(hr))
return DXTRACE_ERR("SelectD3DDevice SelectDisplayMode", hr);
return S_OK;
}
// デバイス能力のチェック
HRESULT CheckDeviceCaps(D3DCAPS9 *Caps)
{
if (Caps->MaxStreams < 3) // 頂点ストリーム数
return DXTRACE_ERR("CheckDeviceCaps MaxStreams < 3", E_FAIL);
if (Caps->MaxPrimitiveCount < 0xFFFF) // プリミティブ数
return DXTRACE_ERR("CheckDeviceCaps MaxPrimitiveCount < 0xFFFF", E_FAIL);
if (Caps->MaxVertexIndex < 0xFFFF) // インデックス数
return DXTRACE_ERR("CheckDeviceCaps MaxVertexIndex < 0xFFFF", E_FAIL);
// if (Caps->VertexShaderVersion < D3DVS_VERSION(2, 0)) // 頂点シェーダ・バージョン
// return DXTRACE_ERR("CheckDeviceCaps VertexShaderVersion < D3DVS_VERSION(2, 0)", E_FAIL);
// if (Caps->PixelShaderVersion < D3DPS_VERSION(2, 0)) // ピクセル・シェーダ・バージョン
// return DXTRACE_ERR("CheckDeviceCaps PixelShaderVersion < D3DPS_VERSION(2, 0)", E_FAIL);
return S_OK;
}
// ディスプレイとバック・バッファのフォーマットの調査
HRESULT SelectAdapterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode)
{
int i;
HRESULT hr = S_OK;
// ウインドウ・モード
ZeroMemory(&g_D3DPPWindow, sizeof(g_D3DPPWindow));
g_D3DPPWindow.BackBufferCount = 1;
g_D3DPPWindow.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3DPPWindow.hDeviceWindow = g_hWindow;
g_D3DPPWindow.Windowed = TRUE;
g_D3DPPWindow.PresentationInterval = g_Interval;
for (int i=0; i<sizeof(g_fmtDisplay)/sizeof(g_fmtDisplay[0]); i++)
{
hr = g_pD3D->CheckDeviceType(Adapter, Device, dmode.Format, g_fmtDisplay[i], TRUE);
if (SUCCEEDED(hr))
{
g_D3DPPWindow.BackBufferFormat = g_fmtDisplay[i];
break;
}
}
if (FAILED(hr))
return DXTRACE_ERR("SelectAdapterFormat CheckDeviceType Window", hr);
// フルスクリーン・モード
ZeroMemory(&g_D3DPPFull, sizeof(g_D3DPPFull));
g_D3DPPFull.BackBufferCount = 1;
g_D3DPPFull.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3DPPFull.hDeviceWindow = g_hWindow;
g_D3DPPFull.Windowed = FALSE;
g_D3DPPFull.PresentationInterval = g_Interval;
for (/*int */i=0; i<sizeof(g_fmtDisplay)/sizeof(g_fmtDisplay[0]); i++)
{
hr = g_pD3D->CheckDeviceType(Adapter, Device, g_fmtDisplay[i], g_fmtDisplay[i], FALSE);
if (SUCCEEDED(hr))
{
g_D3DPPFull.BackBufferFormat = g_fmtDisplay[i];
break;
}
}
if (FAILED(hr))
return DXTRACE_ERR("SelectAdapterFormat CheckDeviceType Full", hr);
return S_OK;
}
// 深度/ステンシル・バッファのフォーマットを調べる
HRESULT SelectDepthStencilFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode)
{
HRESULT hr;
// ウインドウ・モード
hr = g_pD3D->CheckDeviceFormat(Adapter, Device,
dmode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, g_fmtDepthStencil);
if (FAILED(hr))
return DXTRACE_ERR("SelectDepthStencilFormat CheckDeviceFormat DS Window", hr);
hr = g_pD3D->CheckDepthStencilMatch(Adapter, Device,
dmode.Format, g_D3DPPWindow.BackBufferFormat, g_fmtDepthStencil);
if (FAILED(hr))
return DXTRACE_ERR("SelectDepthStencilFormat CheckDepthStencilMatch DS Window", hr);
g_D3DPPWindow.EnableAutoDepthStencil = TRUE;
g_D3DPPWindow.AutoDepthStencilFormat = g_fmtDepthStencil;
// フルスクリーン・モード
hr = g_pD3D->CheckDeviceFormat(Adapter, Device,
g_D3DPPFull.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, g_fmtDepthStencil);
if (FAILED(hr))
return DXTRACE_ERR("SelectDepthStencilFormat CheckDeviceFormat DS Full", hr);
hr = g_pD3D->CheckDepthStencilMatch(Adapter, Device,
g_D3DPPFull.BackBufferFormat, g_D3DPPFull.BackBufferFormat, g_fmtDepthStencil);
if (FAILED(hr))
return DXTRACE_ERR("SelectDepthStencilFormat CheckDepthStencilMatch DS Full", hr);
g_D3DPPFull.EnableAutoDepthStencil = TRUE;
g_D3DPPFull.AutoDepthStencilFormat = g_fmtDepthStencil;
return S_OK;
}
// レンダリング・テクスチャのフォーマットを調べる
HRESULT SelectRenderTexterFormat(UINT Adapter, D3DDEVTYPE Device, D3DDISPLAYMODE dmode)
{
HRESULT hr = S_OK;
int i;
// ウインドウ・モード
g_fmtRendTexterWindow = D3DFMT_UNKNOWN;
for (int i=0; i<sizeof(g_fmtRendTexter)/sizeof(g_fmtRendTexter[0]); i++)
{
hr = g_pD3D->CheckDeviceFormat(Adapter, Device,
dmode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, g_fmtRendTexter[i]);
if (SUCCEEDED(hr))
{
hr = g_pD3D->CheckDepthStencilMatch(Adapter, Device,
dmode.Format, g_fmtRendTexter[i], g_fmtDepthStencil);
if (SUCCEEDED(hr))
{
g_fmtRendTexterWindow = g_fmtRendTexter[i];
break;
}
}
}
if (FAILED(hr))
return DXTRACE_ERR("SelectRenderTexterFormat Window", hr);
// フルスクリーン・モード
g_fmtRendTexterFull = D3DFMT_UNKNOWN;
for (i=0; i<sizeof(g_fmtRendTexter)/sizeof(g_fmtRendTexter[0]); i++)
{
hr = g_pD3D->CheckDeviceFormat(Adapter, Device,
g_D3DPPFull.BackBufferFormat,
D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, g_fmtRendTexter[i]);
if (SUCCEEDED(hr))
{
hr = g_pD3D->CheckDepthStencilMatch(Adapter, Device,
g_D3DPPFull.BackBufferFormat, g_fmtRendTexter[i], g_fmtDepthStencil);
if (SUCCEEDED(hr))
{
g_fmtRendTexterFull = g_fmtRendTexter[i];
break;
}
}
}
if (FAILED(hr))
return DXTRACE_ERR("SelectRenderTexterFormat Full", hr);
return S_OK;
}
// フルシーン・アンチエイリアシングを調べる
HRESULT SelectMultiSampleType(UINT Adapter, D3DDEVTYPE Device)
{
int i;
int mstCount = sizeof(g_MultiSampleType) / sizeof(g_MultiSampleType[0]);
// ウインドウ・モード
for (int i=0; i<mstCount; i++)
{
if (FAILED(g_pD3D->CheckDeviceMultiSampleType(Adapter, Device,
g_D3DPPWindow.BackBufferFormat, TRUE, g_MultiSampleType[i], NULL)))
continue;
if (g_D3DPPWindow.EnableAutoDepthStencil == TRUE)
if (FAILED(g_pD3D->CheckDeviceMultiSampleType(Adapter, Device,
g_D3DPPWindow.AutoDepthStencilFormat, TRUE, g_MultiSampleType[i], NULL)))
continue;
g_D3DPPWindow.MultiSampleType = g_MultiSampleType[i];
g_D3DPPWindow.MultiSampleQuality = 0;
break;
}
// フルスクリーン・モード
for (/*int */i=0; i<mstCount; i++)
{
if (FAILED(g_pD3D->CheckDeviceMultiSampleType(Adapter, Device,
g_D3DPPFull.BackBufferFormat, FALSE, g_MultiSampleType[i], NULL)))
continue;
if (g_D3DPPWindow.EnableAutoDepthStencil == TRUE)
if (FAILED(g_pD3D->CheckDeviceMultiSampleType(Adapter, Device,
g_D3DPPFull.AutoDepthStencilFormat, FALSE, g_MultiSampleType[i], NULL)))
continue;
g_D3DPPFull.MultiSampleType = g_MultiSampleType[i];
g_D3DPPFull.MultiSampleQuality = 0;
break;
}
return S_OK;
}
// ディスプレイ・モードを調べる
HRESULT SelectDisplayMode(UINT Adapter)
{
// ウインドウ・モード(調べる必要ない)
// フルスクリーン・モード
D3DDISPLAYMODE dmode = { 0, 0, 0, D3DFMT_UNKNOWN };
int level = 1000000;
int num = g_pD3D->GetAdapterModeCount(Adapter, g_D3DPPFull.BackBufferFormat);
for (int i=0; i<num; i++)
{
// ディスプレイ・モードの列挙
D3DDISPLAYMODE dm;
g_pD3D->EnumAdapterModes(Adapter, g_D3DPPFull.BackBufferFormat, i, &dm);
// 希望のモードとの誤差
int l = abs(g_sizeFullMode.cx - (LONG)dm.Width) + abs(g_sizeFullMode.cy - (LONG)dm.Height);
if (l < level)
{
// より適切なモードを選択
dmode = dm;
level = l;
}
}
if (dmode.Format == D3DFMT_UNKNOWN)
return DXTRACE_ERR("SelectDisplayMode EnumAdapterModes", E_FAIL);
g_D3DPPFull.BackBufferWidth = dmode.Width;
g_D3DPPFull.BackBufferHeight = dmode.Height;
return S_OK;
}
/*-------------------------------------------
DirectX Graphics初期化
--------------------------------------------*/
HRESULT InitDXGraphics(void)
{
// Direct3Dオブジェクトの作成
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_pD3D == NULL)
return DXTRACE_ERR("InitDXGraphics Direct3DCreate9", E_FAIL);
// デバイス設定の選択
UINT Adapter;
D3DDEVTYPE Device;
HRESULT hr = SelectD3DDevice(Adapter, Device);
if (FAILED(hr))
return DXTRACE_ERR("InitDXGraphics SelectD3DDevice", hr);
// D3DDeviceオブジェクトの作成
if (g_bWindow)
g_D3DPP = g_D3DPPWindow;
else
g_D3DPP = g_D3DPPFull;
hr = g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWindow,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_D3DPP, &g_pD3DDevice);
if (FAILED(hr))
{
hr = g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, g_hWindow,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_D3DPP, &g_pD3DDevice);
if (FAILED(hr))
return DXTRACE_ERR("InitDXGraphics CreateDevice", hr);
}
// ビューポートの設定
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = g_D3DPP.BackBufferWidth;
vp.Height = g_D3DPP.BackBufferHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
hr = g_pD3DDevice->SetViewport(&vp);
if (FAILED(hr))
return DXTRACE_ERR("InitDXGraphics SetViewport", hr);
// スプライト機能の初期化
hr = D3DXCreateTextureFromFile(g_pD3DDevice, g_szSpriteFile, &g_pD3DTexture);
if (FAILED(hr))
return DXTRACE_ERR("InitDXGraphics D3DXCreateTextureFromFile", hr);
hr = D3DXCreateSprite(g_pD3DDevice, &g_pD3DXSprite);
if (FAILED(hr))
return DXTRACE_ERR("InitDXGraphics D3DXCreateSprite", hr);
// フォントの準備
LOGFONT logfont;
logfont.lfHeight = 16; // 高さ
logfont.lfWidth = 0; // 平均文字幅
logfont.lfEscapement = 0; // X角度
logfont.lfOrientation = 0; // Y角度
logfont.lfWeight = FW_NORMAL; // 太さ
logfont.lfItalic = FALSE; // 斜体
logfont.lfUnderline = FALSE; // 下線
logfont.lfStrikeOut = FALSE; // 打ち消し線
logfont.lfCharSet = SHIFTJIS_CHARSET; // キャラクタ・セット
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; // 出力精度
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; // クリップ精度
logfont.lfQuality = DEFAULT_QUALITY; // 品質
logfont.lfPitchAndFamily = DEFAULT_PITCH || FF_DONTCARE; // ピッチ
lstrcpy(logfont.lfFaceName, _T("")); // フォント名
// hr = D3DXCreateFontIndirect( g_pD3DDevice, &logfont, &g_pD3DXFont);
// if (FAILED(hr))
// return DXTRACE_ERR("InitDXGraphics D3DXCreateFontIndirect", hr);
// 8-2 頂点フォーマットの定義
// ■頂点宣言オブジェクトを作る
hr = g_pD3DDevice->CreateVertexDeclaration( decl, &g_pVertexDeclaration );
if( FAILED(hr) )
return false;
// 8-3 頂点バッファとインデックスバッファの作成
// ■頂点バッファの作成
// [XYZBuffer]を収める頂点バッファ1
hr = g_pD3DDevice->CreateVertexBuffer(
sizeof(XYZBuffer)*8, // バッファ・サイズ(立方体の頂点数)
0, // 使用法
0, // 非FVF頂点バッファ
D3DPOOL_MANAGED, // Direct3Dでメモリを管理
&g_pD3DVBXYZBuffer, // 頂点バッファを受け取る変数
NULL );
if( FAILED(hr) )
return false;
// [ColBuffer]を収める頂点バッファ2
hr = g_pD3DDevice->CreateVertexBuffer(
sizeof(ColBuffer)*8, // バッファ・サイズ
0, // 使用法
0, // 非FVF頂点バッファ
D3DPOOL_MANAGED, // Direct3Dでメモリを管理
&g_pD3DVBColBuffer, // 頂点バッファを受け取る変数
NULL );
if( FAILED(hr) )
return false;
// ■頂点バッファへの書き込み
// XYZBufferを収める頂点バッファ1に書き込む
XYZBuffer *pXYZBuffer;
hr = g_pD3DVBXYZBuffer->Lock(
0, 0, // 全体をロックする
(LPVOID*)&pXYZBuffer, 0 );
if( FAILED(hr) )
DXTRACE_ERR( "エラー", hr );
// 立方体の頂点データを書き込み
pXYZBuffer[0].x = 1.0f; pXYZBuffer[0].y = 1.0f; pXYZBuffer[0].z = 1.0f;
pXYZBuffer[1].x = 1.0f; pXYZBuffer[1].y = 1.0f; pXYZBuffer[1].z = -1.0f;
pXYZBuffer[2].x = 1.0f; pXYZBuffer[2].y = -1.0f; pXYZBuffer[2].z = 1.0f;
pXYZBuffer[3].x = 1.0f; pXYZBuffer[3].y = -1.0f; pXYZBuffer[3].z = -1.0f;
pXYZBuffer[4].x = -1.0f; pXYZBuffer[4].y = 1.0f; pXYZBuffer[4].z = 1.0f;
pXYZBuffer[5].x = -1.0f; pXYZBuffer[5].y = 1.0f; pXYZBuffer[5].z = -1.0f;
pXYZBuffer[6].x = -1.0f; pXYZBuffer[6].y = -1.0f; pXYZBuffer[6].z = 1.0f;
pXYZBuffer[7].x = -1.0f; pXYZBuffer[7].y = -1.0f; pXYZBuffer[7].z = -1.0f;
g_pD3DVBXYZBuffer->Unlock(); // アンロック
// ColBufferを収める頂点バッファ2に書き込む
ColBuffer *pColBuffer;
hr = g_pD3DVBColBuffer->Lock( 0, 0, (LPVOID*)&pColBuffer, 0 );
if( FAILED(hr) )
return false;
// 頂点の色データを書き込む
pColBuffer[0].color = D3DCOLOR_XRGB( 0xff, 0xff, 0xff );
pColBuffer[1].color = D3DCOLOR_XRGB( 0xff, 0xff, 0x00 );
pColBuffer[2].color = D3DCOLOR_XRGB( 0xff, 0x00, 0xff );
pColBuffer[3].color = D3DCOLOR_XRGB( 0xff, 0x00, 0x00 );
pColBuffer[4].color = D3DCOLOR_XRGB( 0x00, 0xff, 0xff );
pColBuffer[5].color = D3DCOLOR_XRGB( 0x00, 0xff, 0x00 );
pColBuffer[6].color = D3DCOLOR_XRGB( 0x00, 0x00, 0xff );
pColBuffer[7].color = D3DCOLOR_XRGB( 0x00, 0x00, 0x00 );
g_pD3DVBColBuffer->Unlock();
// ■インデックス・バッファの作成
hr = g_pD3DDevice->CreateIndexBuffer(
36 * 2, // 36頂点分の16ビット・インデックス・バッファ
0, // 使用法
D3DFMT_INDEX16, // 16ビット・インデックス・バッファ
D3DPOOL_MANAGED,// Direct3Dでメモリを管理する
&g_pD3DIBuffer, // インデックス・バッファを受け取る変数
NULL );
if( FAILED(hr) )
return false;
// ■インデックス・バッファへの書き込み
DWORD *pIndex;
hr = g_pD3DIBuffer->Lock( 0, 0, (LPVOID*)&pIndex, 0 );
if( FAILED(hr) )
return hr;
// インデックスの書き込み
pIndex[0] = 0; pIndex[1] = 3; pIndex[2] = 1;
pIndex[3] = 0; pIndex[4] = 2; pIndex[5] = 3;
pIndex[6] = 0; pIndex[7] = 5; pIndex[8] = 4;
pIndex[9] = 0; pIndex[10] = 1; pIndex[11] = 5;
pIndex[12] = 4; pIndex[13] = 2; pIndex[14] = 0;
pIndex[15] = 4; pIndex[16] = 6; pIndex[17] = 2;
pIndex[18] = 5; pIndex[19] = 6; pIndex[20] = 4;
pIndex[21] = 5; pIndex[22] = 7; pIndex[23] = 6;
pIndex[24] = 3; pIndex[25] = 6; pIndex[26] = 7;
pIndex[27] = 3; pIndex[28] = 2; pIndex[29] = 6;
pIndex[30] = 1; pIndex[31] = 7; pIndex[32] = 5;
pIndex[33] = 1; pIndex[34] = 3; pIndex[35] = 7;
g_pD3DIBuffer->Unlock();
// 8-4 プログラマブル・シェーダの作成
// 頂点シェーダ・プログラムのアセンブル
LPD3DXBUFFER pCode;
hr = D3DXAssembleShaderFromFile( _T("test.vs"), NULL, NULL, 0, &pCode, NULL );
if( FAILED(hr) )
return DXTRACE_ERR("8-4", hr);
// 頂点シェーダを作る
hr = g_pD3DDevice->CreateVertexShader( (DWORD*)pCode->GetBufferPointer(), &g_pVertexShader );
RELEASE( pCode );
if( FAILED(hr) )
return false;
// ■ピクセル・シェーダの作成
// ピクセルシェーダ・プログラムのアセンブル
hr = D3DXAssembleShaderFromFile( _T("test.ps"), NULL, NULL, 0, &pCode, NULL );
if( FAILED(hr) )
return false;
// ピクセルシェーダを作る
hr = g_pD3DDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), &g_pPixelShader );
RELEASE( pCode );
if( FAILED(hr) )
return false;
// 8-5 レンダリング・ステートの設定
// ■シェーディングモードの設定
hr = g_pD3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
if( FAILED(hr) )
return false;
// ■zバッファの設定
hr = g_pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
if( FAILED(hr) )
return false;
// ■背面のカリングの設定
hr = g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
if( FAILED(hr) )
return false;
// ■変換行列の設定
D3DXMATRIX matWorld;
FLOAT ry = 0.0f;
D3DXMatrixRotationY( &matWorld, ry );
// ビュー変換行列
D3DXMATRIX matView;
D3DXVECTOR3 vEye( 0.0f, 5.0f, -5.0f );
D3DXVECTOR3 vAt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUp( 0.0f, 1.0f, 0.0f );
D3DXMatrixLookAtLH( &matView, &vEye, &vAt, &vUp );
// 透視変換行列
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj,
3.1415926535 / 3.0f, // 60度
g_D3DPP.BackBufferWidth / g_D3DPP.BackBufferHeight, // 画面のアスペクト比
3.0f, 15.0f );
D3DXMATRIX mat;
mat = matWorld * matView * matProj;
D3DXMatrixTranspose( &mat, &mat );
g_pD3DDevice->SetVertexShaderConstantF( 0, (float*)&mat, 4 );
return S_OK;
}
/*-------------------------------------------
D3Dに管理されないオブジェクトの初期化
--------------------------------------------*/
HRESULT InitD3DObject(void)
{
HRESULT hr;
// レンダリング・ステートの設定
// Zバッファの設定
g_pD3DDevice->SetRenderState(D3DRS_ZENABLE,
g_D3DPP.EnableAutoDepthStencil ? D3DZB_TRUE : D3DZB_FALSE);
// マルチサンプリングの設定
hr = g_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE );
if( FAILED(hr) )
return DXTRACE_ERR( "error", hr );
// hr = g_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,
// g_D3DPP.MultiSampleType != D3DMULTISAMPLE_NONE ? TRUE : FALSE);
// if( FAILED(hr) )
// return DXTRACE_ERR( "error", hr );
// スプライトの処理
g_pD3DXSprite->OnResetDevice();
// フォントの処理
// g_pD3DXFont->OnResetDevice();
// マウス・カーソルの設定
LPDIRECT3DSURFACE9 pCursorSurface = NULL;
hr = g_pD3DDevice->CreateOffscreenPlainSurface(32, 32,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCursorSurface, NULL);
if (FAILED(hr))
return DXTRACE_ERR("InitD3DObject CreateOffscreenPlainSurface", hr);
hr = D3DXLoadSurfaceFromFile(pCursorSurface, NULL, NULL,
g_szCursorFile, NULL, D3DX_FILTER_NONE, 0, NULL);
if (SUCCEEDED(hr))
hr = g_pD3DDevice->SetCursorProperties(16, 10, pCursorSurface);
RELEASE(pCursorSurface);
if (FAILED(hr))
return DXTRACE_ERR("InitD3DObject SetCursorProperties", hr);
return S_OK;
}
/*--------------------------------------------
画面の描画処理
--------------------------------------------*/
HRESULT Render(void)
{
// シーンのクリア
HRESULT hr;
hr = g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
// シーンの描画開始
// if (SUCCEEDED(g_pD3DDevice->BeginScene()))
hr = g_pD3DDevice->BeginScene();
{
// 8-6 3Dオブジェクトの描画
// 頂点宣言オブジェクトの登録
g_pD3DDevice->SetVertexDeclaration( g_pVertexDeclaration );
// 頂点バッファとインデックスバッファの登録
g_pD3DDevice->SetStreamSource( 0, g_pD3DVBXYZBuffer, 0, sizeof(XYZBuffer) );
g_pD3DDevice->SetStreamSource( 1, g_pD3DVBColBuffer, 0, sizeof(ColBuffer) );
hr = g_pD3DDevice->SetIndices( g_pD3DIBuffer );
if( FAILED(hr) )
return DXTRACE_ERR( "error", hr );
// プログラマブルシェーダの登録
g_pD3DDevice->SetVertexShader( g_pVertexShader );
g_pD3DDevice->SetPixelShader( g_pPixelShader );
hr = g_pD3DDevice->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST,
0,
0,
8,
0,
12 );
if( FAILED(hr) )
DXTRACE_ERR( "str", hr );
/*
// シーンの描画(スプライトの描画)
static int alpha=0;
g_pD3DXSprite->Begin();
g_pD3DXSprite->Draw(g_pD3DTexture, NULL, NULL, NULL, 0.0f, NULL,
D3DCOLOR_ARGB(alpha>255?511-alpha:alpha,255,255,255));
alpha++; alpha &= 0x1FF;
g_pD3DXSprite->End();
// フォントの描画
g_pD3DXFont->Begin();
// 文字列表示
RECT rect1 = { 8, 32, 108, 50 }; //描画領域(8, 32)-(108, 50)
g_pD3DXFont->DrawText(_T("文字列表示①"),
-1, // 文字数(NULL終端まで表示)
&rect1, // 描画領域
DT_LEFT | DT_NOCLIP, // 左揃え&クリップしない
D3DCOLOR_XRGB(255, 255, 0)); // 文字色(R255,G255, B0)
g_pD3DXFont->End();
*/
// シーンの描画終了
hr = g_pD3DDevice->EndScene();
if( FAILED(hr) )
DXTRACE_ERR( "error", hr );
}
// シーンの表示
hr = g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
if( FAILED(hr) )
DXTRACE_ERR( "error", hr );
return hr;
}
/*-------------------------------------------
D3Dに管理されないオブジェクトの終了処理
--------------------------------------------*/
HRESULT CleanupD3DObject(void)
{
// スプライトの処理
if (g_pD3DXSprite)
g_pD3DXSprite->OnLostDevice();
// フォントの処理
if (g_pD3DXFont)
g_pD3DXFont->OnLostDevice();
return S_OK;
}
/*-------------------------------------------
ウインドウ・サイズの変更
--------------------------------------------*/
HRESULT ChangeWindowSize(void)
{
// ウインドウのクライアント領域に合わせる
CleanupD3DObject();
HRESULT hr = g_pD3DDevice->Reset(&g_D3DPP);
if (FAILED(hr))
{
if (hr == D3DERR_DEVICELOST)
g_bDeviceLost = true;
else
DestroyWindow(g_hWindow);
return DXTRACE_ERR("ChangeWindowSize Reset", hr);
}
hr = InitD3DObject();
if (FAILED(hr))
{
DestroyWindow(g_hWindow);
return DXTRACE_ERR("ChangeWindowSize InitD3DObject", hr);
}
// ビューポートの設定
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = g_D3DPP.BackBufferWidth;
vp.Height = g_D3DPP.BackBufferHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
hr = g_pD3DDevice->SetViewport(&vp);
if (FAILED(hr))
{
DXTRACE_ERR("ChangeWindowSize SetViewport", hr);
DestroyWindow(g_hWindow);
}
return hr;
}
/*-------------------------------------------
画面モードの変更
--------------------------------------------*/
void ChangeDisplayMode(void)
{
g_bWindow = !g_bWindow;
CleanupD3DObject();
if (g_bWindow)
{
g_D3DPP = g_D3DPPWindow;
}
else
{
g_D3DPP = g_D3DPPFull;
GetWindowRect(g_hWindow, &g_rectWindow);
}
HRESULT hr = g_pD3DDevice->Reset(&g_D3DPP);
if (FAILED(hr))
{
if (hr == D3DERR_DEVICELOST)
g_bDeviceLost = true;
else
DestroyWindow(g_hWindow);
DXTRACE_ERR("ChangeDisplayMode Reset", hr);
return;
}
hr = InitD3DObject();
if (FAILED(hr))
{
DXTRACE_ERR("ChangeDisplayMode InitD3DObject", hr);
DestroyWindow(g_hWindow);
return;
}
if (g_bWindow)
{
SetWindowLong(g_hWindow, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
if(g_hMenu != NULL)
{
SetMenu(g_hWindow, g_hMenu);
g_hMenu = NULL;
}
SetWindowPos(g_hWindow, HWND_NOTOPMOST,
g_rectWindow.left, g_rectWindow.top,
g_rectWindow.right - g_rectWindow.left,
g_rectWindow.bottom - g_rectWindow.top,
SWP_SHOWWINDOW);
}
else
{
SetWindowLong(g_hWindow, GWL_STYLE, WS_POPUP | WS_VISIBLE);
if(g_hMenu == NULL)
{
g_hMenu = GetMenu(g_hWindow);
SetMenu(g_hWindow, NULL);
}
}
}
/*-------------------------------------------
DirectX Graphicsの終了処理(初期化に失敗したときも呼ばれる)
--------------------------------------------*/
bool CleanupDXGraphics(void)
{
// 取得したオブジェクトの開放
RELEASE(g_pD3DXFont);
RELEASE(g_pD3DXSprite);
RELEASE(g_pD3DTexture);
RELEASE(g_pD3DDevice);
RELEASE(g_pD3D);
return true;
}
/*-------------------------------------------
アプリケーションの終了処理(最後に呼ばれる)
--------------------------------------------*/
bool CleanupApp(void)
{
// メニュー・ハンドルの削除
if( g_hMenu )
DestroyMenu( g_hMenu );
// ウインドウ・クラスの登録解除
UnregisterClass(g_szWndClass, g_hInstance);
return true;
}
/*-------------------------------------------
ウィンドウ処理
--------------------------------------------*/
HRESULT SaveFrontBuffer(void); // 画面キャプチャ
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
HRESULT hr = S_OK;
switch(msg)
{
case WM_ACTIVATE:
g_bActive = (LOWORD(wParam) != 0);
break;
case WM_DESTROY:
// D3Dに管理されないオブジェクトの終了処理
CleanupD3DObject();
// DirectX Graphicsの終了処理
CleanupDXGraphics();
// ウインドウを閉じる
PostQuitMessage(0);
g_hWindow = NULL;
return 0;
// ウインドウ・サイズの変更処理
case WM_SIZE:
if (g_D3DPP.Windowed != TRUE)
break;
if (!g_pD3DDevice || wParam == SIZE_MINIMIZED)
break;
g_D3DPP.BackBufferWidth = LOWORD(lParam);
g_D3DPP.BackBufferHeight = HIWORD(lParam);
if(g_bDeviceLost)
break;
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
ChangeWindowSize();
break;
case WM_SETCURSOR:
if (g_pD3DDevice)
{
if (LOWORD(lParam) == HTCLIENT) // クライアント領域のみ
{
SetCursor(NULL); // ウインドウの標準カーソルを消す
g_pD3DDevice->ShowCursor(TRUE); // DirectX Graphicsのカーソル機能を使う
return TRUE; // 設定を終えたことを通知
}
}
break;
case WM_MOUSEMOVE:
if (g_pD3DDevice)
{
POINT ptCursor;
GetCursorPos(&ptCursor);
g_pD3DDevice->SetCursorPosition(ptCursor.x, ptCursor.y, 0L);
}
break;
case WM_KEYDOWN:
// キー入力の処理
switch(wParam)
{
case VK_ESCAPE: // [ESCAPE]キーでウインドウを閉じる
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
case 'W': // 画面モードの切り替え
ChangeDisplayMode();
break;
case 'S': // 画面キャプチャ
SaveFrontBuffer();
break;
}
break;
case WM_COMMAND:
// 選択されたメニューを実行
switch (LOWORD(wParam))
{
case IDM_EXIT:
DestroyWindow(hWnd);
return 0;
}
break;
}
// デフォルト処理
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// 画面キャプチャ
HRESULT SaveFrontBuffer(void)
{
HRESULT hr;
// 現在のディスプレイのフォーマットなどを取得
D3DDISPLAYMODE dmode;
hr = g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dmode);
if (FAILED(hr))
return DXTRACE_ERR("SaveFrontBuffer GetAdapterDisplayMode", hr);
// キャプチャ用サーフェス作成
LPDIRECT3DSURFACE9 pSurface; // サーフェス
hr = g_pD3DDevice->CreateOffscreenPlainSurface(
dmode.Width,
dmode.Height,
D3DFMT_A8R8G8B8, // この場合、標準的な32ビット・フォーマット
D3DPOOL_SCRATCH, &pSurface, NULL);
if (FAILED(hr))
return DXTRACE_ERR("SaveFrontBuffert CreateOffscreenPlainSurface", hr);
// キャプチャ
hr = g_pD3DDevice->GetFrontBufferData(0, pSurface);
if (FAILED(hr))
{
RELEASE(pSurface);
return DXTRACE_ERR("SaveFrontBuffert GetFrontBufferData", hr);
}
// サーフェスの保存
RECT rect;
if (g_D3DPP.Windowed)
{
POINT p = { 0, 0 };
ClientToScreen(g_hWindow, &p);
rect.left = p.x; rect.top = p.y;
p.x = g_D3DPP.BackBufferWidth;
p.y = g_D3DPP.BackBufferHeight;
ClientToScreen(g_hWindow, &p);
rect.right = p.x; rect.bottom = p.y;
}
hr = D3DXSaveSurfaceToFile(
g_szFontBufferFile, // 保存ファイル名
D3DXIFF_BMP, // BMP形式
pSurface, // 保存するサーフェス
NULL, // パレット
g_D3DPP.Windowed ? &rect : NULL); // 保存領域
RELEASE(pSurface);
if (FAILED(hr))
return DXTRACE_ERR("SaveFrontBuffert D3DXSaveSurfaceToFile", hr);
return S_OK;
}
/*--------------------------------------------
アイドル時の処理
--------------------------------------------*/
bool AppIdle(void)
{
if (!g_pD3D || !g_pD3DDevice)
return false;
if (!g_bActive)
return true;
// 消失したデバイスの復元処理
HRESULT hr;
if (g_bDeviceLost)
{
Sleep(100); // 0.1秒待つ
// デバイス状態のチェック
hr = g_pD3DDevice->TestCooperativeLevel();
if (FAILED(hr))
{
if (hr == D3DERR_DEVICELOST)
return true; // デバイスはまだ失われている
if (hr != D3DERR_DEVICENOTRESET)
return false; // 予期せぬエラー
CleanupD3DObject(); // Direct3Dで管理していないリソースを開放
hr = g_pD3DDevice->Reset(&g_D3DPP); // 復元を試みる
if (FAILED(hr))
{
if (hr == D3DERR_DEVICELOST)
return true; // デバイスはまだ失われている
DXTRACE_ERR("AppIdle Reset", hr);
return false; // デバイスの復元に失敗
}
hr = InitD3DObject(); // 開放したDirect3Dで管理していないリソースを再取得
if (FAILED(hr))
{
DXTRACE_ERR("AppIdle InitD3DObject", hr);
return false;
}
}
// デバイスが復元した
g_bDeviceLost = false;
}
// 画面の更新
hr = Render();
if (hr == D3DERR_DEVICELOST)
g_bDeviceLost = true; // デバイスの消失
else if (FAILED(hr))
return false;
return true;
}
/*--------------------------------------------
メイン
---------------------------------------------*/
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
// アプリケーションに関する初期化
HRESULT hr = InitApp(hInst);
if (FAILED(hr))
{
DXTRACE_ERR("WinMain InitApp", hr);
return 0;
}
// DirectX Graphicsの初期化
hr = InitDXGraphics();
if (FAILED(hr))
DXTRACE_ERR("WinMain InitDXGraphics", hr);
else
{
// D3Dに管理されないオブジェクトの初期化
hr = InitD3DObject();
if (FAILED(hr))
{
DXTRACE_ERR("WinMain InitD3DObject", hr);
DestroyWindow(g_hWindow);
}
}
// メッセージ・ループ
MSG msg;
do
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// アイドル処理
if (!AppIdle())
// エラーがある場合,アプリケーションを終了する
DestroyWindow(g_hWindow);
}
} while (msg.message != WM_QUIT);
// アプリケーションの終了処理
CleanupApp();
return msg.wParam;
}