描画するプリミティブの形状は通常 IASetPrimitiveTopology() で
指定します。D3D10/DX10 では次の 9種類が定義されています。
D3D10_PRIMITIVE_TOPOLOGY_POINTLIST // 点 D3D10_PRIMITIVE_TOPOLOGY_LINELIST // 線 D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP // 連続線 D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST // 三角形 D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP // 連続三角形 D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ
ところがジオメトリシェーダーを使っている場合、
IASetPrimitiveTopology() の設定値は実際に描画する
プリミティブ形状と連動していません。
というのは、GeometryShader の出力プリミティブの種類はシェーダー
側で再定義されるからです。
PointSprite がその良い例で、入力 Topology は PointList でも
実際に描画される形状は TriangleStrip の板ポリゴンになっています。
つまりジオメトリシェーダーを使う場合の IASetPrimitiveTopology()
の設定値は、
・頂点ストリームを一度に読み進める量
・GeometryShader へ同時に入力されるパラメータ数
の決定にだけ使われると考えられます。
そこでジオメトリシェーダーへの入力頂点数にだけ注目してまとめると
次のようになります。
同時 1 頂点 POINTLIST
同時 2 頂点 LINELIST
同時 3 頂点 TRIANGLELIST
同時 4 頂点 LINELIST_ADJ
同時 6 頂点 TRIANGLELIST_ADJ
同時 5頂点が無いのが残念ですが、ほぼ 1~6 頂点までの汎用的な入力
頂点数として流用することが可能です。この考え方を使って
4頂点プリミティブや 6頂点プリミティブを定義することができます。
実際に 4角ポリゴン でモデルを作って描画してみました。
いわゆる QUADLIST 相当です。(D3DPT_QUADLIST ?)
いつものように、実行ファイル、ソース、シェーダー込みでダウンロード
できます。
モデルデータ側は四角形のあつまりなので、index list は 4つで
1ポリゴンとなります。
// torus.inc static unsigned short _Index[]= { 0, 1, 2, 3, // 四角ポリゴン1 4, 0, 3, 5, // 四角ポリゴン2 6, 4, 5, 7, // 四角ポリゴン3 8, 6, 7, 9, // 四角ポリゴン4 :
描画命令の発行は 同時4頂点入力の LINELIST_ADJ を使います。
// 描画 (ss07.cpp) iDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ ); iDevice->IASetInputLayout( iInputLayout ); UINT vsize= sizeof(VertexType); UINT voffset= 0; iDevice->IASetVertexBuffers( 0, 1, &iVertexBuffer, &vsize, &voffset ); iDevice->IASetIndexBuffer( iIndexBuffer, DXGI_FORMAT_R16_UINT, 0 ); iEffectModel->GetTechniqueByName( "Main" )->GetPassByIndex( 0 )->Apply( 0 ); iDevice->DrawIndexedInstanced( IndexCount, 16, 0, 0, 0 );
無駄に凝ったことをしているので DrawIndexedInstance() になってますが、
LINELIST_ADJ 以外はごく普通の描画コードです。
DrawIndexed~() に渡す値もそのまま頂点数 (Index) の個数になっています。
もし1枚だけ描くなら 4頂点です。
// 1枚だけ描く場合 iDevice->DrawIndexed( 4, 0, 0 );
VertexShader も PixelShader も通常の描画と全く同じものです。
ジオメトリシェーダーは次のとおりです。
typedef VS_OUTPUT GS_OUTPUT; [maxvertexcount(4)] void GS_Main( lineadj GS_OUTPUT In[4], inout TriangleStreamgsstream ) { gsstream.Append( In[0] ); gsstream.Append( In[1] ); gsstream.Append( In[3] ); gsstream.Append( In[2] ); gsstream.RestartStrip(); }
lineadj で 4頂点入力、TriangleStrip で四角形を描画します。
これで QUADLIST の描画が可能となります。
ファイルはこちらです。
・wheelhandle_ss07t.zip