立体の描画

 球体を一つ描画します。まだ陰影を付けていないので、球体という感じはしませんが、ワイヤーフレーム表示にしてみると、下の図のように表示されます。よく見ると、ポリゴンの最小単位は三角形です。その三角形が2つ合わさって一つの四角形を作り出し、その四角形が、縦、横に並んでいます。

頂点の座標は、半径1の球上の各点を球座標から直交座標への変換公式で求めています。今回のように、頂点数が多くなると、これまでのように頂点バッファのみを使った描画方法ではなく、インデックスバッファを使うのが一般的になります。今までは、頂点データを作るときに、描画される時の順番を意識して頂点データを並べていました。インデックスバッファを使うと、頂点データの情報と並び順の情報を分けて記述することが出来ます。

 以下では、頂点データの作成、インデックスデータの作成、インデックスバッファの作成と描画について説明を行いたいと思います。

​コード解説

① 球体の頂点データの作成
 球体の頂点データを作成するために用意した変数と、計算部分です。

1行目から6行目で球体に関するデータを保持する変数の宣言をしています。1、2行目では、球体の縦横の分割数を指定する定数です。u_maxが縦方向の分割数(最小値は3)で、v_maxが横方向の分割数(最小値は2)です。3行目は球体の頂点データを保持する変数、4行目は球体のインデックスデータを保持する変数です。5行目、6行目は、球体の頂点数、インデックス数を計算しています。

頂点数の計算方法の参考図として、上のマス目の図を見て下さい。上のマス目は、縦の分割数が10、横の分割数が5の球体を展開したものです(ちょうど球体の地球儀とそれを描いた世界地図との関係のイメージ)。一番右側が点線になっているのは、球体上では、左端と右端は同じ位置にあるため、頂点数を数えるためには、実線の所だけに注目すると良いです。すると、実線の縦線は「u_max」と常に同じ数であり、横線は「v_max + 1」と同じであるため、その2つを掛けた数が頂点数になります。

インデックス数も上のマス目を参考に算出できます。インデックスは「平面の描画」の所で出てきた、複数の四角形が繋がったSTRIP描画と同じ順番で指定します。すると、一番上の横一列のマス目では点線部分も含む、「 ( u_max + 1 ) * 2」だけのインデックス数が必要になり、それがさらに「v_max」行だけ必要になるため、その2つを掛け合わせた数がインデックス数になります。

​9行目から18行目までは、実際に頂点データの計算をしています。XMConvertToRadians関数は角度(°)をラジアンの値に変換してくれる関数です。変換されたラジアン値と、球座標から直交座標の変換公式を使い球体上の頂点座標を求めています。

② 球体のインデックスデータの作成
 球体を描画するために必要なインデックスを実際に作成している所です。

インデックスデータの作成方法は、​上記の①での考え方の通りです。一番右端(点線部分)のデータと左端のデータは同じものなので、その時だけif文で分けて処理をしています。

サンプル​コード

< 動作確認環境 >
 ・Windows10 Pro
 ・Visual Studio Community 2017


基本的には空のプロジェクトを作ってもらい、以下のソースコードをコピペするだけでうまく実行できるかと思います。もしうまくいかない場合がありましたら、サンプルコードの実行に関する注意事項を一度参照してみてください。

​ソースコード

シェーダのソースコード (shader.hlsl ※必ずこの名前で保存してください)

ソースコードを見ていただくと分かる通り、これまでに出てきた頂点バッファの作成時とほとんど変わりがありません。唯一違うところは、BindFlagsの値をD3D11_BIND_INDEX_BUFFERに指定していることだけです。もう一つの違いは、13行目の一文です。これは、描画ループ内に書かれている関数ですが、これまでのDrawではなく、DrawIndexedが使われています。

③ インデックスバッファの作成と描画
 インデックスデータを扱うためのインデックスバッファを作成します。