GeometryShader は、Shader3.0 以前はできなかったさまざまな用途に
応用することができます。
・面(primitive)単位の処理、エッジの処理
・隣接頂点の参照
・VertexShader の代わり
・頂点(primitive)の追加
・primitive の削除
・その他いろいろ
頂点シェーダーは 1頂点単位の変換なので、そのままでは他の頂点情報の
参照ができません。また動的な追加削除は矛盾を引き起こしてしまいます。
あらかじめ面単位に分割しておいたり、隣接頂点座標を1頂点に入れて
おいたりと、さまざまな工夫と前処理が必要でした。
D3D10/DX10 で追加されたジオメトリシェーダーは、このような面(プリミ
ティブ)ごとの処理を、データ側の加工無しに行うことができます。
(topology の adjacency data は別に情報が必要)
試しにポリゴンをばらばらにするシェーダーを作ってみました。
以前 Xbox1 のゲームでも同じようなシェーダーを作成し、シェーダー
だけで任意のモデルをばらばらに破壊する表現を用いたことがあります。
当時は ShaderModel1.0 だったので、あらかじめ情報を頂点に埋め込んで
おく必要がありました。専用コンバータを用意して、共有頂点を分割したり
回転中心からの距離を求めておいたりと、専用のモデルデータに
なっています。
今回はジオメトリシェーダーのおかげで、データ自体は何もいじる必要が
ありませんでした。普通に描画するデータをそのままシェーダーに渡す
だけで簡単(?)に破壊することができます。
なお Local/World 座標での演算が必要なので、Transform 自体も
ジオメトリシェーダーで行う必要があります。
そのため VertexShader は何もせず、頂点を GeometryShader に渡して
いるだけとなっています。
データは同じですが演算量は増加します。面ごとに 3頂点分の演算が発生
するので、普通に描画するよりはかなり重くなっているはずです。
破壊については、本当ならば StreamOutput を活用すべきところですが
使っていません。単純に面法線と重力方向にローカル回転させながら
吹っ飛ばしているだけです。
いつものように ss06.exe で実際に実行することができます。
DirectX10 が走る環境と DirectX SDK August2007 Runtime が必要です。
今までと違って速度調整が入っていて、約 60fps 前後で固定するように
なっています。(追記: そのままだと速すぎるからです)