Direct3D10でライティングやってみた。

これまたDirect3D9なら、カンターンに出来た事なんだけど・・・
Direct3D10からは、ライティングやマテリアル周りの構造体は廃止されて、
全部シェーダにゆだねられるようになっちまいました。
という事でライトを当てるだけでも一苦労・・・。


//// MyShader.fx

...

// ライティング情報
float3 vLightDir; // ライトの向き
float4 vLightColor; // ライトの色

// メッシュのディフューズ
float4 vDiffuse;

// 頂点シェーダ入力パラメータ
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Color : COLOR;
float4 Normal : NORMAL; // 法線ベクトル
};

...

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

// 頂点をトランスフォームする
...

// ライティング(ディフューズのみ)
//psIn.Color = vsIn.Color * vLightColor * saturate(dot(vsIn.Normal, vLightDir)); // 頂点カラー自体にライティングをするなら、こっちのコード。
psIn.Color = vDiffuse * vLightColor * saturate(dot(vsIn.Normal, vLightDir));

return psIn;
}

...

今回は、頂点カラーにライティングを施すコード。
実質グーローシェーディングになるのかな。
他にも、ピクセル単位でライティングを施すとかもあるようで。


で、シェーダのコードの方は、グローバル変数に、
ライトの情報と、マテリアル(ディフューズ)の情報を用意して、
プログラム側から流し込んで計算という感じになる。
頂点シェーダの入力データにも法線ベクトルが増えました。


//// MyApp.cpp

...

void MyApp::Update()
{
// シーンクリア
...

// ライト情報
D3DXVECTOR3 vLight(2.0f, 0.0f, 0.0f);
D3DXVECTOR4 vLightColor(1.0f, 1.0f, 1.0f, 1.0f);

// マテリアル(とりあえずディフューズのみ)
D3DXVECTOR4 vDiffuse(1.0f, 0.0f, 0.0f, 1.0f);

// シーン描画
{
// ライトをぐるぐる回す
D3DXMATRIX m;
D3DXMatrixRotationY(&m, D3DXToRadian(_timer.GetTime()*20));
D3DXVec3TransformCoord(&vLight, &vLight, &m);

// シェーダにトランスフォームのパラメータを設定する
...

// シェーダにライティング、ディフューズ情報を設定する
_pEffect->GetVariableByName("vLightDir")->AsVector()->SetFloatVector((float*)&vLight);
_pEffect->GetVariableByName("vLightColor")->AsVector()->SetFloatVector((float*)&vLightColor);
_pEffect->GetVariableByName("vDiffuse")->AsVector()->SetFloatVector((float*)&vDiffuse);

// テクニックを取得する
...
for (UINT i = 0; i < desc.Passes; ++i) {
pTechnique->GetPassByIndex(i)->Apply(0);

// メッシュ描画
_pMesh->DrawSubset(0);
}
}

...
}

実はSetFloatVectorでfloat4とか3とかに値を設定していいのか微妙。
一応流れているみたいだけど・・・配列サイズを渡してないからどうなっているのか怪しい・・・。


とりあえずコレで、こんな感じのになります。

まだちょっとライティング処理が不完全っぽい。
9でやったグーローシェーディングの結果とは明らかに違う感じ。
でもとりあえず大体のライティングは出来た。
後は、ちゃんとマテリアル情報として、アンビエントとかスペキュラも
持たせて計算してやれば、もっとリアルなシェーディングが
出来るんではなかろうか。


ここまで来ると、大分色々とカスタマイズ出来る様になってきて楽しい。
というかシェーダ楽しい。
今まで自分は3Dグラフィックスと言えば空間に関する事
(ベクトルや行列等)しか興味が無くて、色に関する事は暗黙のうちに
スルーしていたんだけど、こうしてシェーダに触れてみると、
かなり重要な要素なんだなって事がわかった。


てな感じで、ようやく楽しくなりかけてきたDirect3D10なんですが、
この辺りで一旦おしまい。
シェーダ周りはDirect3D9でも出来るので、
また折を見てそっちで勉強したいなーと思います。


所感としては、Direct3D10をやると、Direct3Dの仕組みや、
3Dグラフィックスについての理解はすごく深まると思います。
理解が深まれば、当然コードを組むのも楽しくなります・・・
んが、やっぱりちょっと難解で、初心者には厳しい感じになっちゃったなと。
固定機能パイプラインを廃止したなら、デフォルトの
シェーダを用意するとかして欲しかったなあと思う次第。
カンタン3Dプログラミングがしたいなら、10よりも9のがオススメ。


最後に、Direct3D10の書籍なんぞをご紹介。
なんと、現状では二冊しかないようです。

DirectX10 3Dプログラミング―「Direct3D 10」の基礎知識と使い方 (I・O BOOKS)

DirectX10 3Dプログラミング―「Direct3D 10」の基礎知識と使い方 (I・O BOOKS)

現在唯一の日本語Direct3D10本。
入門本なので、アーキテクチャの解説や初期化・基本的な処理等は網羅されてます。
これからやりたいっちゅー人は是非。


Beginning DirectX 10 Game Programming

Beginning DirectX 10 Game Programming

こちらは洋書のDirectX10入門本。洋書だから英語が読めないとなんだけど、
サンプルコードはわかりやすい。そのまま引っ張れる。
それだけでもオススメ。3D以外のコンポーネントも載ってます。


Direct3D9の本なのだけど、シェーダや効果的なエフェクト処理の
やり方がたくさん載ってます。
HLSLが4.0ではないとはいえ、考え方は十分4.0でも使えるのでオススメ。
本のデザインもなんだか箱○風でCOOL!