Direct3D10で深度/ステンシルバッファを作ってみた。

前回の記事では、ライティングが全くされていなかったので目立たなかったけど、
(DXUTCreateTeapotで頂点カラーが設定されていたので)
頂点カラーをちゃんと出すようにしたら、ポリゴンの前後関係が
めちゃくちゃになって見えた(当たり前)ので、
深度/ステンシルバッファを作ってみた。


Direct3D9ではフラグ一つで出来た深度/ステンシルバッファだけど、
Direct3D10は深度/ステンシルバッファに関するオブジェクトを
作ってあげないといけない。実にめんdry


まずは、頂点カラーをちゃんと出すようにしたシェーダから。

//// MyShader.fx

...

// 頂点シェーダの入力パラメータ
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Color : COLOR;
};

...

// 頂点シェーダ
PS_INPUT VS(VS_INPUT vsIn)
{
PS_INPUT psIn;

// 頂点をトランスフォームする
psIn.Pos = mul(vsIn.Pos, mWorld);
psIn.Pos = mul(psIn.Pos, mView);
psIn.Pos = mul(psIn.Pos, mProj);

// 頂点カラーをセットする
//psIn.Color = float4(1.0f, 0.0f, 0.0f, 1.0f); // こっちが前回の赤にするコード。
psIn.Color = vsIn.Color;

return psIn;
}

...


お次はヘッダファイルの方でインタフェース変数の用意。

//// MyApp.h

...

class MyApp
{
...

ID3D10RenderTargetView* _pBackBuf; // バックバッファのビュー(変数名リネームしました)
ID3D10DepthStencilView* _pZBuf; // 深度/ステンシルバッファのビュー

};


深度/ステンシルバッファの作成部分。

//// MyApp.cpp

...

bool MyApp::Initialize()
{
...

//// Direct3D10 初期化

// バックバッファ(描画ターゲット)のビューを作成
ID3D10Texture2D* pBuffer;
hr = _pSwapChain->GetBuffer( // バックバッファを取得する
0,
__uuidof(ID3D10Texture2D),
(LPVOID*)&pBuffer);

...

// 深度/ステンシルバッファを作成
D3D10_TEXTURE2D_DESC td;
td.Width = SCREEN_W;
td.Height = SCREEN_H;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = DXGI_FORMAT_D32_FLOAT; // 32bit float
td.SampleDesc.Count = 1;
td.SampleDesc.Quality = 0;
td.Usage = D3D10_USAGE_DEFAULT;
td.BindFlags = D3D10_BIND_DEPTH_STENCIL; // 深度/ステンシルとして使用
td.CPUAccessFlags = 0;
td.MiscFlags = 0;

hr = _pDevice->CreateTexture2D(&td, NULL, &pBuffer);
if (FAILED(hr)) {
assert(0);
return false;
}

// 深度/ステンシルバッファのビューを作成
D3D10_DEPTH_STENCIL_VIEW_DESC dsd;
dsd.Format = td.Format; // バッファの方と同じフォーマット
dsd.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
dsd.Texture2D.MipSlice = 0;

hr = _pDevice->CreateDepthStencilView(
pBuffer,
&dsd,
&_pZBuf);
if (FAILED(hr)) {
assert(0);
return false;
}

RELEASE(pBuffer); // Getしたry

// バックバッファのビューと深度/ステンシルバッファのビューをデバイスに設定する
_pDevice->OMSetRenderTargets(1, &_pBackBuf, _pZBuf);

...

}

...


void MyApp::Update()
{
// シーンクリア
float color[] = { 0.0f, 0.0f, 0.5f, 1.0f };
_pDevice->ClearRenderTargetView(_pBackBuf, color); // バックバッファのクリア
_pDevice->ClearDepthStencilView(_pZBuf, D3D10_CLEAR_DEPTH, 1.0f, 0);
// 深度/ステンシルバッファのクリア

...

}

pBufferは同じ2Dテクスチャなので再利用してます。
後、バッファのクリアも別々になりました。



結果はこんな感じ。
意外に鮮やかな頂点カラーが設定されてました。


アホな話ですがー、自分Zバッファって3D空間的なモノを想像してました。
そこにZ順でピクセルを並べて行くみたいな・・・ああなんとアホな想像してたんだ・・・。
よく考えれば、普通のソートみたく、現在書き込む予定のピクセルのZを
ひとつ取っておいて、それとこれから処理するピクセルのZを比較すれば
いいだけなので、2Dテクスチャで十分なのだなと。
自分の3Dの知識の無さが露呈してしまった。