頂点バッファーとインデックス バッファーからのレンダリング (Direct3D 9)
インデックス付き描画メソッドとインデックスなし描画メソッドの両方が Direct3D でサポートされています。 インデックス付きメソッドでは、すべての頂点コンポーネントに対して 1 つのインデックス セットが使用されます。 頂点データは頂点バッファーに格納され、インデックス データはインデックス バッファーに格納されます。 頂点バッファーとインデックス バッファーを使用してプリミティブを描画する一般的なシナリオをいくつか次に示します。
これらの例では、IDirect3DDevice9::D rawPrimitive と IDirect3DDevice9::D rawIndexedPrimitive の使用を比較します
シナリオ 1: インデックスを作成せずに 2 つの三角形を描画する
次の図に示す四角形を描画するとします。
三角形リスト プリミティブタイプを使用して 2 つの三角形をレンダリングすると、各三角形は 3 つの個々の頂点として格納され、次の図と同様の頂点バッファーになります。
描画呼び出しは非常に簡単です。頂点バッファー内の位置 0 から、2 つの三角形を描画します。 カリングが有効になっている場合は、頂点の順序が重要になります。 次の使用例は、既定の反時計回りのカリング状態を前提としているため、表示される三角形は時計回りの順序で描画する必要があります。 三角形リスト プリミティブ型は、各三角形のバッファーから 3 つの頂点を線形順に読み取るだけであるため、この呼び出しでは三角形 (0、1、2) と (3,4, 5) が描画されます。
DrawPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
0, // StartVertex
2 ); // PrimitiveCount
シナリオ 2: インデックスを使用して 2 つの三角形を描画する
ご注意のように、頂点バッファーには、0 と 4、2、5 の場所に重複するデータが含まれています。 これは、2 つの三角形が 2 つの共通の頂点を共有するため、理にかなっています。 この重複データは無駄であり、インデックス バッファーを使用して頂点バッファーを圧縮できます。 頂点バッファーを小さくすると、グラフィックス アダプターに送信する必要がある頂点データの量が減ります。 さらに重要なのは、インデックス バッファーを使用すると、アダプターが頂点キャッシュに頂点を格納できるようになる点です。描画されるプリミティブに最近使用された頂点が含まれている場合、その頂点を頂点バッファーから読み取る代わりにキャッシュからフェッチできるため、パフォーマンスが大幅に向上します。
各一意の頂点を頂点バッファーに 1 回だけ格納する必要があるため、インデックス バッファーは頂点バッファーに "インデックス" します。 次の図は、以前の描画シナリオに対するインデックス付きアプローチを示しています。
インデックス バッファーには、頂点バッファー内の特定の頂点を参照する VB インデックス値が格納されます。 頂点バッファーは頂点の配列と考えることができるため、VB インデックスは単にターゲット頂点の頂点バッファーへのインデックスです。 同様に、IB Index はインデックス バッファーへのインデックスです。 注意しないと非常に混乱を招く可能性があるため、使用されているボキャブラリを明確にしてください。VB インデックス値は頂点バッファーにインデックス、IB インデックス値はインデックス バッファーにインデックス、インデックス バッファー自体には VB Index 値が格納されます。
描画呼び出しを次に示します。 次の描画シナリオでは、すべての引数の意味について詳しく説明します。現時点では、この呼び出しは、インデックス バッファー内の位置 0 から始まる 2 つの三角形を含む三角形リストをレンダリングするように Direct3D に再度指示することに注意してください。 この呼び出しでは、以前とまったく同じ順序で同じ 2 つの三角形が描画され、適切な時計回りの向きが保証されます。
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
0, // BaseVertexIndex
0, // MinIndex
4, // NumVertices
0, // StartIndex
2 ); // PrimitiveCount
シナリオ 3: インデックスを使用して 1 つの三角形を描画する
次の図に示すように、2 番目の三角形のみを描画するが、四角形全体を描画するときに使用するのと同じ頂点バッファーとインデックス バッファーを使用する必要があるふりをします。
この描画呼び出しでは、使用される最初の IB インデックスは 3 です。この値は StartIndex と呼ばれます。 使用される最も低い VB インデックスは 0 です。この値は MinIndex と呼ばれます。 三角形を描画するために必要な頂点は 3 つだけですが、これらの 3 つの頂点は頂点バッファー内の 4 つの隣接する位置に分散されます。描画呼び出しに必要な頂点バッファー メモリの連続したブロック内の位置の数は NumVertices と呼ばれ、この呼び出しでは 4 に設定されます。 MinIndex と NumVertices の値は、Direct3D がソフトウェアの頂点処理中にメモリ アクセスを最適化するのに役立つヒントに過ぎず、単にパフォーマンスの価格で頂点バッファー全体を含むように設定できます。
単一三角形のケースの描画呼び出しを次に示します。次に、BaseVertexIndex 引数の意味について説明します。
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
0, // BaseVertexIndex
0, // MinIndex
4, // NumVertices
3, // StartIndex
1 ); // PrimitiveCount
シナリオ 4: オフセット インデックスを使用して 1 つの三角形を描画する
BaseVertexIndex は、インデックス バッファーに格納されているすべての VB インデックスに効果的に追加される値です。 たとえば、前の呼び出し中に BaseVertexIndex に 50 の値を渡した場合、DrawIndexedPrimitive 呼び出しの間、次の図のインデックス バッファーを使用した場合と機能的には同じになります。
この値は 0 以外に設定されることはほとんどありませんが、インデックス バッファーを頂点バッファーから切り離す場合に役立ちます。特定のメッシュのインデックス バッファーを埋め込むときに、頂点バッファー内のメッシュの位置がまだわかっていない場合は、頂点バッファーの先頭にメッシュ頂点があるふりをするだけです。描画呼び出しを行うときは、実際の開始位置を BaseVertexIndex として渡すだけです。
この手法は、1 つのインデックス バッファーを使用してメッシュの複数のインスタンスを描画する場合にも使用できます。たとえば、頂点バッファーに同じ描画順序を持つ 2 つのメッシュが含まれていても、頂点が若干異なる場合 (拡散色やテクスチャ座標が異なる場合)、BaseVertexIndex に異なる値を使用して両方のメッシュを描画できます。 この概念をさらに 1 ステップ進めることで、アクティブな頂点バッファーを循環させ、必要に応じて BaseVertexIndex を調整するだけで、1 つのインデックス バッファーを使用して、それぞれ異なる頂点バッファーに含まれるメッシュの複数のインスタンスを描画できます。 BaseVertexIndex 値も MinIndex 引数に自動的に追加されます。これは、その使用方法を確認するときに意味があります。
以前と同じインデックス バッファーを使用して、四角形の 2 番目の三角形のみを再び描画するふりをします。ただし、QUAD が VB インデックス 50 にある別の頂点バッファーが使用されています。 四角形の頂点の相対順序は変更されず、頂点バッファー内の開始位置のみが異なります。 インデックス バッファーと頂点バッファーは、次の図のようになります。
適切な描画呼び出しを次に示します。BaseVertexIndex は、前のシナリオから変更された唯一の値であることに注意してください。
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
50, // BaseVertexIndex
0, // MinIndex
4, // NumVertices
3, // StartIndex
1 ); // PrimitiveCount
関連トピック