■今回のプログラムの流れ
*準備段階
第1回のものに加え、以下の準備を行います。
- 頂点バッファの準備
- シェーダーの準備
- 頂点入力レイアウトオブジェクトを作成
*メッセージループ
画面クリア処理の後、以下の設定を行います。
- バッファのセット
- 頂点バッファのセット
- 入力頂点の情報オブジェクトをセット
- シェーダーのセット
- 描画命令を発行
■頂点バッファの作成
頂点バッファを指定サイズで作成し、
ある初期値をコピーするようにして初期化まで行います。
[cpp]
// 頂点バッファの準備
D3D11_BUFFER_DESC descVB;
ZeroMemory( &descVB, sizeof(descVB) );
descVB.Usage = D3D11_USAGE_DEFAULT;
descVB.ByteWidth = sizeof(Vertex) * 3;
descVB.BindFlags = D3D11_BIND_VERTEX_BUFFER;
ID3D11Buffer* pVertexBuffer = 0;
/// 頂点”元”データ.
Vertex vbdata[] = {
XMFLOAT3( 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF,
XMFLOAT3( 1.0f, 0.0f, 0.0f ), 0xFFFF0000,
XMFLOAT3( 0.0f,-1.0f, 0.0f ), 0xFF00FF00,
};
D3D11_SUBRESOURCE_DATA subresData;
ZeroMemory( &subresData, sizeof(subresData) );
subresData.pSysMem = vbdata;
// 頂点バッファを作成し、サブリソースで設定した初期値に設定.
hr = pd3dDevice->CreateBuffer( &descVB, &subresData, &pVertexBuffer );
[/cpp]
■シェーダーの準備
ピクセルシェーダーもほぼ同様なのでここでは頂点シェーダーだけの説明にします。
まずHLSLで記述したファイルから読み込みコンパイルを行います。
その後、コンパイル後のバイトデータ列からシェーダーを作成します。
なお、頂点シェーダーのバイトデータ列はこの後の処理でも使うので、
即座に解放することは出来ません。
[cpp]
// シェーダーの準備
ID3D10Blob* pBlobVS = 0; // DXSDK2010Juneだと ID3DBlob になる.
ID3D10Blob* pErrMsg = 0;
// まずはコンパイル(VS)
D3DX11CompileFromFile( L”shader.vs”, NULL, NULL, “mainVS”, “vs_4_0”,
D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR,
0,
NULL,
&pBlobVS, &pErrMsg, NULL );
if( pErrMsg ) {
OutputDebugStringA( (const char*) pErrMsg->GetBufferPointer() );
OutputDebugStringA( “\n” );
pErrMsg->Release();
pErrMsg = 0;
}
// シェーダーを作成(VS)
ID3D11VertexShader* pVertexShader = 0;
hr = pd3dDevice->CreateVertexShader(
pBlobVS->GetBufferPointer(),
pBlobVS->GetBufferSize(),
NULL,
&pVertexShader );
[/cpp]
また、DirectX SDK 2009Augustのものでは、
D3D10Blobを使うようになっていました。
DirectX SDK 2010June版では、D3DBlobを使うようです。
新しいバージョンのSDKでは、どうやらD3D[10,11]の部分の番号が取れていく傾向にありそうです。
特に機能拡張のないデータに関してはそのようになるっぽいです。
シェーダーのコンパイルのフラグもD3D10となっていますが、新しいSDKではバージョン番号が取れている物を使用することが出来るので、
DirectX11なのにDirectX10の設定を使うことに関する違和感は軽減されるかと思います。
手元が2009Augのため、DirectX11RTM版のSDKでは~という話です。
こんな変更もあるし、開発に使用するSDKのバージョンも再検討したほうが良さそうです。
自分がDirectX SDK 2009Augなのは、Windows7環境でDirectX9が正しく動作する最低バージョンだからです。
■頂点入力レイアウトの作成
従来でいう頂点宣言になります。
頂点データがどのような構造で入力されていくかを示すオブジェクトになります。
この情報を作成するのに、頂点シェーダーのバイトデータ列が必要になっています。
このあたりはDirectX10と変更は特にありません。
[cpp]
// 頂点入力の設定.
D3D11_INPUT_ELEMENT_DESC layout[] = {
“POSITION”, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
“COLOR”, 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0,
};
// 頂点入力レイアウト情報オブジェクトの作成.
// 頂点シェーダーのバイトコードも必要になるのがポイント.
ID3D11InputLayout* pInputLayout = 0;
pd3dDevice->CreateInputLayout( layout, 2, pBlobVS->GetBufferPointer(), pBlobVS->GetBufferSize(), &pInputLayout );
// この時点でシェーダー用バイトコードは解放して良い.
if( pBlobVS ) { pBlobVS->Release(); pBlobVS=0; }
if( pBlobPS ) { pBlobPS->Release(); pBlobPS=0; }
[/cpp]
■描画処理
画面のクリア後には、今まで作成したオブジェクトをセットしていきます。
[cpp]
// バッファのセット.
UINT strides[] = sizeof(Vertex);
UINT offsets[] = 0;
pImmediateContext->IASetInputLayout( pInputLayout );
pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
pImmediateContext->IASetVertexBuffers( 0, 1, &pVertexBuffer, strides, offsets );
// シェーダーのセット.
pImmediateContext->VSSetShader( pVertexShader, NULL, 0 );
pImmediateContext->PSSetShader( pPixelShader, NULL, 0 );
// 描画
pImmediateContext->Draw( 3, 0 );
[/cpp]
この部分も例によって、ID3D11ImmediateContextに対して設定し、描画コールを行います。
デバイスのオブジェクトではなく、コンテキストに対する描画発行となっています。
また、シェーダーのセットでも若干引数が増えました。
今回は使用していないので、ゼロが設定してあります。
■シェーダーコード
現在のシェーダーコードはこんな感じです。
*頂点シェーダー
struct VS_INPUT { float3 Pos : POSITION; float4 Col : COLOR0; }; struct VS_OUTPUT { float4 Pos : SV_POSITION; float4 Col : COLOR; }; VS_OUTPUT mainVS( VS_INPUT _In ) { VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = float4( _In.Pos, 1 ); Out.Col = _In.Col; return Out; }
*ピクセルシェーダー
[cpp]
struct VS_OUTPUT {
float4 Pos : SV_POSITION;
float4 Col : COLOR;
};
float4 mainPS( VS_OUTPUT _In ) : SV_TARGET
{
return _In.Col;
}
[/cpp]
■感想
DirectX SDK 2009Augを使用しており、これはDirectX11 SDK RTM版といえます。
そのため、シェーダー部分を筆頭に、D3D10, D3D11と入り乱れた感じで初期化になっています。
新しいSDKならこのあたりは解消されているらしいので、プログラムの見やすさは良くなると思います。
あと、算術関連がD3DXではなくxnamath.hに入るようになっていました。
この部分は大きな変更と言えそうです。
“XNA Math”だからプレフィックスは XM*** ということっぽい(XMFLOAT3 とか)。