みなさん、こんにちは。
今回も、C#でOpenGLを使う方法について、ご紹介します。
前回はバッファオブジェクトを使った描画方法についてお話しました。
今回は、頂点インデックスを使った描画方法についてお話します。
まずは図をご覧ください。
これは立方体を斜め45度から俯瞰した図です(面が2つ見える)。
前回までの記事では左図のように頂点配列だけで描画を行いました。
このとき、面と共有する頂点の数だけ重複して配列に入れる必要があります(例:2, 7, 10は三角形の面3つと共有している)。
頂点が重複するとメモリ量も圧迫しますので、重複を回避したい場合は「頂点インデックス配列」を使用します。
頂点インデックス配列を使った描画では、重複しない頂点配列と、頂点の番号を持った頂点インデックス配列を参照します(右図)。
頂点インデックス配列は、三角形の面ごとのインデックス値が連続して入ります(右図では 1,2,3, 1,3,4, 2,5,6, 2,6,3 の12要素の配列となる)。
1頂点のデータは 最低でも頂点座標(x,y,z)を持つため、float型の3要素で12バイトのメモリを消費しますが、頂点インデックスの1要素はint型またはunsigned int型のインデックス値であるため、4バイトで済ますことが可能です。
これは、複雑な形状であるほどメモリ量削減の効果を持ちます。
OpenTKでの頂点インデックス配列を使った描画は、次のようになります。
まず、前回の記事のように頂点配列を用意し、GPUに転送まで行います。
次に、頂点インデックス配列を作成し、以下のようにGPUに転送します。
————————–
// 頂点インデックス配列を作成
int[] indexArray = new int[]{ 1,2,3, 1,3,4, 2,5,6, 2,6,3 }; // 三角形4面分のインデックス
int indexArrayCount = indexArray.Count();
// 頂点インデックス配列をGPUに転送
int ibo;
GL.GetBuffers(1, out ibo);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
int indexBufferSize = sizeof(int) * indexArrayCount;
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, indexBufferSize, indexArray, BufferUsageHint.StaticDraw);
————————–
描画の呼び出しは少し注意が必要です。
頂点配列のみでの描画の場合は、GL.DrawArrays関数を呼び出して描画しましたが、頂点インデックス配列を使った描画ではGL.DrawElements関数を使います。
————————–
// 描画
GL.DrawElements(BeginMode.Triangles, indexBufferSize, DrawElementsType.UnsignedInt, 0);
————————–
いかがでしたでしょうか?
次回は、座標変換行列についてお話します。