補遺2: BMP形式以外からテクスチャを作成する。


【ステップ1】

 プロジェクトを改造して行く。 以下の指令に従うべし。

【ステップ1−1 ファイルのダウンロード】
解説
まず、左のリストのファイルを、
mission1 プロジェクトのあるディレクトリに
ダウンロードして下さい。
ダウンロード


【ステップ1−2 リソースの挿入 Part1】
解説
ワークスペースのResourceView タブを
クリックした後、mission1フォルダを右クリックします。
すると、左の図1のようなメニューが
表示されますので、「インポート」を
選んでクリックします。
図1 ワークスペース


【ステップ1−3 リソースの挿入 Part2】
解説
すると図2のようなダイアログが開きます。

まず、「ファイルの種類(T)」に「すべてのファイル(*.*)」を選択

次いで、「用途(A)」として「カスタム」を選択

それから、 先ほどダウンロードしたファイル「sample.tga」を選択して、
「OK」ボタンをクリック。

図2 ファイルの選択


【ステップ1−4 リソースのインポート】
解説
すると図3のようなダイアログが開き、
リソースのタイプを問い合わせてきます。

ここでは「TGA」と記入しておいて下さい。

「OK」ボタンをクリックしましょう。
図3 カスタムリソースタイプ指定


【ステップ1−5 画像データの表示】
解説
すると画面は、図4のようになったはずです。
これで sample.tga がインポートできました。

図4 リソースエディタ







【ステップ2 プログラム改造】

Direct3Dでこのテクスチャーを読み込むルーチンを作ります。

【ステップ3−1 テクスチャー読み込みルーチン】
解説

ワークスペース(左図の部分)から、
d3dmain.cpp をダブルクリックして開きます。

すると画面は、図6の様になったはずです。
図5 ワークスペース


図6 d3dmain.cpp



次に、図6のようにして編集メニューから検索コマンドを選びます。

すると、図7のようなダイアログウィンドウが出てきます、

ここでは、RestoreDeviceObjects というキーワードで検索を実行。

この操作を何度か繰り返すと、リスト1aのプログラムが出てくるはずです。
図7 検索ウィンドウ
図6 検索コマンド


改造前
HRESULT	RestoreDeviceObjects()
{
    LPDIRECT3DSURFACE8 pBackBuffer;
    g_lpD3DDEV->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
    pBackBuffer->GetDesc( &g_d3dsdBackBuffer );
    pBackBuffer->Release();
    return    S_OK;
}
リスト1a

解説
関数 RestoreDeviceObjects は、3D描画環境(IDirect3DDevice8)
を初期化もしくは再初期化した際に呼び出されるようになっています。
3D描画環境が再初期化されるとテクスチャも破棄される為、
テクスチャの読み込みはここで行うのが良い事になります。

テクスチャの読み込みの為に、以下の様に変更して下さい。

改造後
HRESULT RestoreDeviceObjects() { LPDIRECT3DSURFACE8 pBackBuffer; g_lpD3DDEV->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); pBackBuffer->GetDesc( &g_d3dsdBackBuffer ); pBackBuffer->Release();
D3DSURFACE_DESC d3dsDesc; DWORD tw,th; D3DXIMAGE_INFO srcImgInfo; HRESULT hr; HMODULE hMod = GetModuleHandle(NULL); HRSRC hRes = FindResource(hMod,MAKEINTRESOURCE(IDR_TGA1),_T("TGA")); HGLOBAL hObj = LoadResource(hMod,hRes); DWORD sz = SizeofResource(hMod,hRes); LPVOID p = LockResource(hObj); hr = D3DXCreateTextureFromFileInMemoryEx( g_lpD3DDEV, p,sz, 0,0,1,0, D3DFMT_A1R5G5B5,D3DPOOL_MANAGED, D3DX_FILTER_NONE,D3DX_FILTER_NONE, 0, &srcImgInfo,NULL,&g_pTexture ); g_fTexImageWidth=1.0f; g_fTexImageHeight=1.0f; if (g_pTexture){ if (S_OK == g_pTexture->GetLevelDesc(0,&d3dsDesc)){ tw = srcImgInfo.Width; th = srcImgInfo.Height; g_fTexImageWidth = (float)tw; g_fTexImageWidth /= (float)d3dsDesc.Width; g_fTexImageHeight = (float)th; g_fTexImageHeight /= (float)d3dsDesc.Height; } }
return S_OK; }
リスト1b

解説
実際に入力するのは、リスト1bの白バックの部分です。
CreateTextureFromFileInMemoryEx はDirectX 関数で、メモリ上の
ファイルからテクスチャを生成します。詳しくは、Microsoft のドキュメントを
参照してください。

Color key は設定していません。グラフィックのアルファデータで、
透過させます。

g_pTexture はテクスチャを保存する為のグローバル変数、
g_fTexImageWidth および g_fTexImageHeight は、テクスチャの
サイズを保持するグローバル変数で、
d3dmain.cpp の最初の方で宣言しています。

g_fTexImageWidth、g_fTexImageHeight の 1.0 はテクスチャ全体を
意味しています。

※このプログラムではデバイスとテクスチャフォーマットの互換性チェックが不十分です。
リスト1cを参照してください。




※補遺(2003/01/10)
HRESULT RestoreDeviceObjects() { LPDIRECT3DSURFACE8 pBackBuffer; g_lpD3DDEV->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); pBackBuffer->GetDesc( &g_d3dsdBackBuffer ); pBackBuffer->Release(); D3DSURFACE_DESC d3dsDesc; DWORD tw,th;
D3DXIMAGE_INFO srcImgInfo; HRESULT hr; D3DFORMAT TextureFormat[] = {D3DFMT_A1R5G5B5,D3DFMT_A4R4G4B4,D3DFMT_A8R8G8B8}; int i; D3DAdapterInfo* pAdapterInfo = &g_Adapters[g_dwAdapter]; D3DDeviceInfo* pDeviceInfo = &pAdapterInfo->devices[pAdapterInfo->dwCurrentDevice]; D3DDEVTYPE dt = pDeviceInfo->DeviceType;// 現在のデバイスのタイプ for (i = 0; i < (sizeof(TextureFormat)/sizeof(D3DFORMAT)); ++i){ hr = g_lpD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, dt, g_d3dsdBackBuffer.Format, 0, D3DRTYPE_TEXTURE, TextureFormat[i]); if (SUCCEEDED(hr)) break; }
HMODULE hMod = GetModuleHandle(NULL); HRSRC hRes = FindResource(hMod,MAKEINTRESOURCE(IDR_TGA1),_T("TGA")); HGLOBAL hObj = LoadResource(hMod,hRes); DWORD sz = SizeofResource(hMod,hRes); LPVOID p = LockResource(hObj); hr = D3DXCreateTextureFromFileInMemoryEx( g_lpD3DDEV, p,sz, 0,0,1,0, TextureFormat[i],D3DPOOL_MANAGED, D3DX_FILTER_NONE,D3DX_FILTER_NONE, 0, &srcImgInfo,NULL,&g_pTexture ); g_fTexImageWidth=1.0f; g_fTexImageHeight=1.0f; if (g_pTexture){ if (S_OK == g_pTexture->GetLevelDesc(0,&d3dsDesc)){ tw = srcImgInfo.Width; th = srcImgInfo.Height; g_fTexImageWidth = (float)tw; g_fTexImageWidth /= (float)d3dsDesc.Width; g_fTexImageHeight = (float)th; g_fTexImageHeight /= (float)d3dsDesc.Height; } } return S_OK; }
リスト1c

解説
さらにリスト1cのように現在使用中のデバイスのサーフェイスフォーマットと
これから作成しようとするテクスチャのフォーマットに互換性があるか
チェックして互換性のあるフォーマットで読み込む方が無難です。
(すべて互換性無し・・・の診断であった場合の処理も考えておく必要がある。)



【ステップ3−2 テクスチャーの破棄】
解説

再度、図8のようにして編集メニューから検索コマンドを選びます。

すると、図9のようなダイアログウィンドウが出てきます、

こんどは、InvalidateDeviceObjects というキーワードで検索を実行。

そうすると、リスト2aのプログラムが表示されるはずです。
図9 検索ウィンドウ
図8 検索コマンド


改造前
HRESULT    InvalidateDeviceObjects()
{
    return    S_OK;
}
リスト2a

解説
関数 InvalidateDeviceObjects は、3D描画環境(IDirect3DDevice8)
を破棄もしくは再初期化する直前に呼び出されるようになっています。
3D描画環境が再初期化されるとテクスチャも強制的に破棄される為、
その直前にテクスチャを明示的に破棄しておくのが無難です。
その為に、以下の様に変更して下さい。

改造後
HRESULT InvalidateDeviceObjects() {
if (g_pTexture != NULL){ g_pTexture->Release(); g_pTexture = NULL; }
return S_OK; }
リスト1b
これで、TGA 形式のテクスチャーを作れるようになります。

戻る