ジオメトリシェーダでライン描画
DirectXには一応、線を描画する機能がある。
プリミティブ型にラインリストやラインストリップを指定すれば、頂点バッファの頂点を線として描画してくれる。
ただし、その線には太さという概念がない。線を描くならできればそれなりの太さが欲しい。
太さのもった線を描画するのには、やはり三角形を使って描画するしかないのだが、ここでジオメトリシェーダが役に立つ。
グラフィックパイプラインにおけるジオメトリステージとは、頂点シェーダのあと、ピクセルシェーダの前に走るシェーダステージのことだ。
頂点シェーダが頂点ごと、ピクセルシェーダがラスタライズ後のピクセルごとに処理が走るのに対し、ジオメトリシェーダは「プリミティブ単位」で処理が走る。つまり、プリミティブ型に三角形を指定していれば、ジオメトリシェーダの入力は3頂点というわけだ。そして、ジオメトリシェーダは複数のプリミティブを出力することができる。
このジオメトリシェーダは今回のようなケースで非常に役に立つ。
「ラインリスト」のプリミティブを受け取り、「三角形リスト」を出力する、という処理を書くことができる。線を受け取り、それを三角形二つで構成された四角形を出力するジオメトリシェーダを作れば、太さのある線を描くことができる。
struct VSOutput { float4 pos : SV_POSITION; float4 col : COLOR; float thickness : THICKNESS; }; struct GSOutput { float4 pos : SV_POSITION; float4 col : COLOR; }; [maxvertexcount(6)] void main( line VSOutput input[2], inout TriangleStream< GSOutput > output ) { for (int i = 0; i < 2; i++) { float offset = input[i].thickness / 2.0f; { GSOutput element; element.pos = input[i].pos + float4(offset, 0.0f, 0.0f, 0.0f); element.col = input[i].col; output.Append(element); } { GSOutput element; element.pos = input[i].pos + float4(-offset, 0.0f, 0.0f, 0.0f); element.col = input[i].col; output.Append(element); } { GSOutput element; element.pos = input[(i + 1) % 2].pos + float4(offset * sign(i - 1), 0.0f, 0.0f, 0.0f); element.col = input[(i + 1) % 2].col; output.Append(element); } output.RestartStrip(); } }
今回は頂点情報に線の太さ情報を追加した。これはコンスタントバッファーで与えてもいいだろう。
さて、これを使って現在はレイトレース及びそのビジュアライザを実装している。
レイの挙動を視覚的に確認することができるので、デバッグに大いに役立っている。
近いウチにレイトレースのブログ記事も投稿する予定だ。