DDSWithoutD3DX サンプル
このサンプルでは、D3DX ヘルパー関数を使用しないで DDS ファイルをテクスチャーにロードする方法を示します。この方法は、D3DX に依存したくないアプリケーションにとって有用です。
Path
ソース : | SDK ルート\Samples\C++\Direct3D10\DDSWithoutD3DX |
実行可能ファイル : | SDK ルート\Samples\C++\Direct3D10\Bin\プラットフォーム\DDSWithoutD3DX.exe |
サンプルが動作するしくみ
このサンプルで興味深いコードは、DDSTextureLoader.cpp の中にあります。オーバーロードされる CreateDDSTextureFromFile 関数は 2 つあり、その一方は Direct3D 9 用、他方は Direct3D 10 用です。 これらのいずれもディスクから DDS データをロードした後、使用される Direct3D バージョンに固有のテクスチャーを作成します。
DDS ファイルのロード
LoadTextureDataFromFile 関数は、ディスクから DDS をロードし、メモリー内の特定の DDS 構造体に格納します。DDS ファイルは、3 つの主要な部分から構成されています。まず、該当ファイルを DDS ファイルとして識別するためのマジック ナンバーがあります。次に、DDSURFACEDESC2 構造体があります。最後に、DDSURFACEDESC2 構造体によって規定されたフォーマットで格納される実際のイメージ データがあります。
// DDS files always start with the same magic number
DWORD dwMagicNumber = *(DWORD*)(*ppHeapData);
if( dwMagicNumber != 0x20534444 )
return FALSE;
// setup the pointers in the process request
*ppSurfDesc = (DDSURFACEDESC2_32BIT*)( *ppHeapData + sizeof(DWORD) );
*ppBitData = *ppHeapData + sizeof(DWORD) + sizeof(DDSURFACEDESC2_32BIT);
*pBitSize = FileSize.LowPart - sizeof(DWORD) - sizeof(DDSURFACEDESC2_32BIT);
ただし、このサンプルでは DDSURFACEDESC2 構造体を使用せず、独自の内部 DDSURFACEDESC2_32BIT 構造体を使用します。DDSURFACEDESC2 構造体に含まれるポインターのサイズが、32 ビット システムと 64 ビット システムで異なるためです。DDS ファイルはこのポインターが 32 ビット幅であることを前提にすべて格納されるので、このサンプルではネイティブ システムのポインター サイズとは無関係に、32 ビットサイズのポインターを持つ構造体を使用します。この処理は、このポインターがアプリケーションによって使用されないので、安全です。
Direct3D 9 テクスチャーの作成
このサンプルは、ディスクからロードされたデータを使用して、デバイス テクスチャーを作成します。Direct3D 9 版の CreateTextureFromDDS の場合、このサンプルでは DDSURFACEDESC2 構造体の ddpfPixelFormat メンバーから Direct3D 9 に固有なテクスチャー フォーマットが取得されます。GetD3D9Format ヘルパー関数には、一部のもっと一般的なテクスチャー フォーマットのための変換が含まれています。
DDSURFACEDESC のフォーマットと高さ、幅、およびミップマップ情報を使用して、このサンプルでは 2 つの Direct3D 9 テクスチャーが作成されます。その一方はステージング テクスチャーであり、他方は実際に使用されるテクスチャーです。標準の DEFAULT_POOL テクスチャーをロックすることができないので、データを DEFAULT_POOL テクスチャーに格納するにはステージング テクスチャーを使用する必要があります。ステージング テクスチャーの各ミップマップが満たされた後、UpdateTexture を使用してステージング テクスチャー全体が DEFAULT_POOL テクスチャーにコピーされます。
Direct3D 10 テクスチャーの作成
Direct3D 10 テクスチャーの作成は、Direct3D 9 テクスチャーの作成に類似しています。GetD3D9Format を使用して、DDSURFACEDESC2 構造体の ddpfPixelFormat メンバーから D3DFMT を作成します。その後、ConvertToDXGI_FORMAT により、D3DFMT を最も近い互換性のある DXGI_FORMAT に変換します。一部の Direct3D 9 フォーマットは、Direct3D 10 と互換性がない場合もあります。 D3DFMT_X8R8G8B8 や D3DFMT_A8R8G8B8 のようなフォーマットは、一部の成分の再編成が必要な DXGI_FORMAT_R8G8B8A8_UNORM に変換する必要があります。
// swizzle if it's a format that may not be completely compatible with D3D10
if( D3DFMT_X8R8G8B8 == fmt ||
D3DFMT_A8R8G8B8 == fmt )
{
for( UINT i=0; i<BitSize; i+=4 )
{
BYTE a = pBitData[i];
pBitData[i] = pBitData[i+2];
pBitData[i+2] = a;
}
}
Direct3D 10 のテクスチャーを作成する場合、このサンプルではステージング テクスチャーの作成が不要です。その代わり、テクスチャー内のミップマップごとに D3D10_SUBRESOURCE_DATA 構造体が作成されます。この構造体の pSysMem メンバーは該当するミップマップのデータの先頭に設定され、SysMemPitch メンバーは該当するミップマップ データのストライド (バイト数) に設定されます。テクスチャーの作成時、D3D10_SUBRESOURCE_DATA 構造体の配列は第 2 パラメーターとして渡され、テクスチャーはこのデータを使用して自動的に初期化されます。該当する関数は、テクスチャーをシェーダーで使用するのに必要なリソース ビューを作成します。