はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング ジオメトリインスタンシング⑧

あいさつ

どうも、はかせです。
今回はついにジオメトリインスタンシングっぽいことができたので
それについてです。

実行結果

くだくだ言う前にまずは実行結果です。
f:id:hakase0274:20190611223901p:plain
上に白いやつが、下に灰色のやつがありますね。
これDrawメソッドは1フレームに一回しか呼んでいません。

実装

今回はシェーダーの定数レジスタを使って実装してみました。
やり方は簡単で、

cbuffer global
{
    matrix gWVP[10];
};

こんな感じで定数バッファの領域に配列置いて

// GPU(シェーダ側)へ送る数値をまとめた構造体
struct CONSTANT_BUFFER 
{
	DirectX::XMMATRIX mWVPs[10];
};

CONSTANT_BUFFER cb;
cb.mWVPs[0] = (XMMatrixTranspose(XMMatrixRotationY(90) * XMMatrixTranslation(0, 0, 0) * View * Proj));
cb.mWVPs[1] = (XMMatrixTranspose(XMMatrixRotationY(0) * XMMatrixTranslation(0, 1, 0) * View * Proj));

こんな感じで値をセットして

mDeviceContext->DrawIndexedInstanced(mDrawNum, 2, 0,0,0);

Draw実行です。

渡された値の何番目を使うかはインスタンスIDを用いて決めています。

struct VS_IN
{
    float4 pos : POSITION;
    uint instanceID : SV_InstanceID;
};

output.pos = mul(input.pos, gWVP[input.instanceID]);

ちなみに今回試してわかったことなんですが、
SV_InstanceIDはDrawInstanced系のメソッドを使わないと
値があてがわれないっぽいです。
(普通のDrawメソッドじゃ何も出なかった)

あとがき

今回はようやっとジオメトリインスタンシングっぽいことができた話でした。

調べたところ今回の私の実装みたいな定数レジスタに直接値をセットするのは、
シェーダーインスタンシングと呼ばれているようです。

ただこの実装だと同時に描画できる個数が縛られるのと
定数レジスタに配列を置くということであまりメモリ効率がよくなさそうです。

何にしてもようやく1ドローコールで複数描画できるようになったのはいいことです。
今後も勉強を進め、もうちょい良い実装を見つけたいと思います。

それでは今回はこの辺でノシ
今回作ったものはgithubに上げました
github.com