以前掲載した D3D10 のサンプルプログラム ss00 を少々解説します。
ss00.cpp 以外にライブラリやら DXUT も使わず、できるだけ
Direct3D 10 の API だけで済むようコードを減らしていったものです。
それでも初期化は思ったより長い関数になりました。
・Direct3D 10 シェーダー4.0サンプルプログラム
あらためてゼロから書いてみると結構手間がかかりますね。
それでも DirectX3~6 あたりまでと比べると、シェーダーが必須になった
だけで、初期化自体は簡単になっているはずです。
ソースはこちらからどうぞ
・HYPERでんち
動作には Vista + DirectX10 対応 GPU が必要です。
ss00.cpp
●初期化 InitDevice()
InitDevice() は初期化を行います。
Direct3D10 で最初に必要なインターフェースは次の2つです。
この2つは名称が異なるものの、D3D10CreateDeviceAndSwapChain()
関数一発で簡単に作ることができます。
・D3D10CreateDeviceAndSwapChain()
DirectX9 以前のように、Device の前に IDirect3D を作る必要がなくなりました。
IDirect3D が行っていた Display 周りの選択や制御が DXGI に移行した形と
なっています。
D3DX10CreateDeviceAndSwapChain() 作成時に与えるパラメータは、
Direct3D9 の D3DPRESENT_PARAMETERS とほとんど同じです。
・D3DPRESENT_PARAMETERS
ここは Direct3D9 のコードを基にしていても比較的容易に対応できる
部分でしょう。
フレームバッファのサイズ、リフレッシュレート、フレームバッファのフォーマット、
フロントバッファへ反映させるときのエフェクトやタイミング、フルスクリーン
かどうか、などを与えています。
DXGI_SWAP_CHAIN_DESC swapdesc= {
{
width, height, // フレームバッファサイズ
{ 60, 1, }, // リフレッシュレート
DXGI_FORMAT_R8G8B8A8_UNORM, // フォーマット
DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
DXGI_MODE_SCALING_UNSPECIFIED,
},
{ 1, 0, }, // sample
DXGI_USAGE_RENDER_TARGET_OUTPUT,
1,
hwnd, // Window ハンドル
winmode, // WindowMode か FullScreen か
DXGI_SWAP_EFFECT_DISCARD,
0
};
D3D10CreateDeviceAndSwapChain(
NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
D3D10_CREATE_DEVICE_DEBUG,
D3D10_SDK_VERSION,
&swapdesc,
&g_iSwapChain, // IDXGISwapChain
&g_iDevice // ID3D10Device
);
ID3D10Device と IDXGISwapChain ができたら View を作ります。
この View は Direct3D10 になって登場した新しい概念です。
メモリ上のテクスチャ空間に対して、実際にどのような手段で Shader が
アクセスするのか決定します。
リソースの自由度が上がった分、具体的にどのような使い方をするのか
ひと手間必要になったわけですね。
IDXGISwapChain から BackBuffer を取り出し、Direct3D からアクセスするための
ID3D10RenderTargetView を作成します。
ID3D10Texture2D* iBackBuffer= NULL;
g_iSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ),
reinterpret_cast
g_iDevice->CreateRenderTargetView( iBackBuffer, NULL, &g_iRenderTargetView );
ZRELEASE( iBackBuffer );
次に Depth Buffer を作成しています。
ここでは何も考えずに Stencil のない D3D10 新フォーマットと思われる
D32_FLOAT を使っています。
ID3D10Texture2D* iTexture= NULL;
D3D10_TEXTURE2D_DESC tex2ddesc= {
width, height, 1, 1, // width, height, mip, array
DXGI_FORMAT_D32_FLOAT, // format
{ 1, 0, }, // sample
D3D10_USAGE_DEFAULT,
D3D10_BIND_DEPTH_STENCIL,
0, // cpu flags
0 // misc flags
};
g_iDevice->CreateTexture2D( &tex2ddesc, NULL, &iTexture );
D3D10_DEPTH_STENCIL_VIEW_DESC vdesc= {
DXGI_FORMAT_D32_FLOAT,
D3D10_DSV_DIMENSION_TEXTURE2D
};
g_iDevice->CreateDepthStencilView( iTexture, &vdesc, &g_iDepthStencilView );
ZRELEASE( iTexture );
初期化はこれでおしまいです。
ここからは実際にレンダリングに必要な設定を行います。
今回は非常に単純な描画なので、特に毎フレーム実行しなくても良い処理を
初期化の部分に書いてしまっています。
シェーダーの生成以外の部分、パラメータ設定関連は、必要であれば1フレーム
の描画中に何回か書き換えることになるでしょう。
// レンダーターゲットの設定
g_iDevice->OMSetRenderTargets( 1,
&g_iRenderTargetView, g_iDepthStencilView );
// ビューポートの設定
D3D10_VIEWPORT viewport= {
0, 0, width, height, 0.0f, 1.0f
};
g_iDevice->RSSetViewports( 1, &viewport );
これら関数はどちらも一度に複数個登録できます。今回は1つだけなので
定数 1 を最初に渡しています。
// shader の作成
ID3D10Blob* iblob= NULL;
if( FAILED( D3DX10CreateEffectFromFile(
TEXT(“cube.fx”),
NULL, NULL, “fx_4_0”, 0, 0, g_iDevice,
NULL, NULL, &g_iEffect, &iblob, NULL ) ) ){
OutputDebugStringA( reinterpret_cast
iblob->GetBufferPointer() ) ); // エラーが発生したら表示
ZRELEASE( iblob );
}
ここでは fx ファイルから Shader を作成しています。
今回のサンプルでは ID3D10Effect をそのまま使っています。
HLSL のコンパイル時にはエラーが発生することがあるので、
コンパイラのエラーメッセージをそのまま表示出力しています。
最後に Effect の変数を初期化しています。
// projection の設定
D3DXMATRIX projection;
D3DXMatrixPerspectiveFovLH( &projection, 3.141592f/3.0f,
WINDOW_SIZE_WIDTH/(float)WINDOW_SIZE_HEIGHT, 1.0f, 10000.0f );
g_iEffect->GetVariableByName( “Projection” )->AsMatrix()->SetMatrix( (float*)&projection );
次回は残りの処理と描画です。