Share via


頂点バッファーとインデックス バッファーからのレンダリング (Direct3D 9)

Direct3D は、インデックス付きとインデックスなしの両方の描画方法をサポートしています。インデックス付きメソッドでは、すべての頂点の成分に対して 1 つのインデックス セットが使用されます。頂点データは頂点バッファーに格納され、インデックス データはインデックス バッファーに格納されます。以下に、頂点バッファーとインデックス バッファーを使用してプリミティブを描画するための一般的なシナリオをいくつか示します。

次の例では、IDirect3DDevice9::DrawPrimitive を使用した場合と IDirect3DDevice9::DrawIndexedPrimitive を使用した場合を比較します。

シナリオ 1 : インデックスなしで 2 つの三角形を描画する

たとえば、次のクワッドを描画するとします。

Ee422176.DIP_fig1(ja-jp,VS.85).gif

トライアングル リスト プリミティブ タイプを使用して 2 つの三角形をレンダリングする場合、各三角形は 3 つの別々の頂点として格納され、次のような頂点バッファーが生成されます。

Ee422176.DIP_fig2(ja-jp,VS.85).gif

描画呼び出しは極めて単純です。頂点バッファー内の 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 つの共通する頂点を共有するため理にかなっています。この複製データは無駄で、頂点バッファーはインデックス バッファーを使用して圧縮できます。頂点バッファーが小さいと、グラフィック アダプターに送信されている頂点データの量が減ります。さらに重要なことに、インデックス バッファーを使用すると、アダプターは頂点キャッシュに頂点を格納できます。描画されるプリミティブが最近使用された頂点を含む場合、その頂点は頂点バッファーから読み出すのではなくキャッシュからフェッチできます。これによってパフォーマンスが大幅に向上します。

インデックス バッファーは、頂点バッファーに "インデックス" を付けるため、各一意の頂点は頂点バッファーに一度だけ格納する必要があります。次に、上記の描画シナリオにインデックスを付けた場合の方法について説明します。

Ee422176.DIP_fig3(ja-jp,VS.85).gif

インデックス バッファーは、頂点バッファー内の特定の頂点を参照する VB Index 値を格納します。頂点バッファーは、頂点の配列と考えられるため、VB Index はターゲット頂点の頂点バッファーへの単なるインデックスです。同様に、IB Index はインデックス バッファーへのインデックスです。これは混乱を招きやすいため、注意が必要です。使用されている語彙を明確にしておいてください。つまり、VB Index 値は頂点バッファーにインデックスを付け、IB Index 値はインデックス バッファーにインデックスを付けます。インデックス バッファー自身は VB Index 値を格納します。

描画呼び出しは次のようになります。すべての引数の意味は、次の描画シナリオで詳細に説明します。ここでは、この呼び出しが、インデックス バッファー内の 0 位置で始まる 2 つの三角形を含むトライアングル リストをレンダリングするように Direct3D に対して再び指示するということを知っておいてください。この呼び出しは、前回とまったく同じ順序で同じ 2 つの三角形を描画し、適切な時計回りが実現されます。

    
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    0,                  // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    0,                  // StartIndex
                    2 );                // PrimitiveCount

シナリオ 3 : インデックス付きで 1 つの三角形を描画する

2 つめの三角形を描画します。ただし、クワッド全体を描画したときに使用した同じ頂点バッファーとインデックス バッファーを使用することにします。

Ee422176.DIP_fig4(ja-jp,VS.85).gif

この描画呼び出しでは、使用される最初の IB Index が 3 で、この値は StartIndex と呼ばれます。使用される最も低い VB Index は 0 です。この値は MinIndex と呼ばれます。三角形を描画するために必要な頂点は 3 つだけですが、これらの 3 つの頂点は頂点バッファーの隣り合う 4 つの場所に散らばっています。描画呼び出しに必要な頂点バッファー メモリーの連続するブロック内の場所の数は、NumVertices と呼ばれ、この呼び出しでは 4 に設定されます。MinIndex 値と NumVertices 値は、実際にはソフトウェアの頂点処理中にメモリー アクセスを最適化しやすくするための単なるヒントであり、パフォーマンスの劣化を問わないのであれば、頂点バッファー全体を含めるように単純に設定できます。

次に 1 つの三角形の場合の描画呼び出しを示します。BaseVertexIndex 引数の意味は次に説明します。

    
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    0,                  // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    3,                  // StartIndex
                    1 );                // PrimitiveCount

シナリオ 4 : オフセット インデックスで 1 つの三角形を描画する

BaseVertexIndex とは、インデックス バッファーに格納される各 VB Index に効率的に追加される値です。たとえば、前回の呼び出し中に BaseVertexIndex に対して値 50 を渡した場合、これは DrawIndexedPrimitive の呼び出し中に以下のインデックス バッファーを使用することと、機能的には同じです。

Ee422176.DIP_fig5(ja-jp,VS.85).gif

この値が 0 以外の値に設定されることはほとんどありませんが、頂点バッファーからインデックス バッファーを分離したい場合には便利です。特定のメッシュに対してインデックス バッファーに格納する場合で、頂点バッファー内のメッシュの場所が知られていない場合は、単純にメッシュ頂点が頂点バッファーの最初に配置されているように見せておいて、描画呼び出しを行う時間になったら、実際の開始場所を BaseVertexIndex として渡すことができます。

この手法は、1 つのインデックス バッファーを使用してメッシュの複数のインスタンスを描画する場合にも使用できます。たとえば、頂点バッファーが、描画順はまったく同じだが頂点がわずかに異なる (おそらく異なるディフューズ色やテクスチャー座標) 2 つのメッシュを含んでいる場合、BaseVertexIndex に異なる値を指定して両方のメッシュを描画できます。この概念をさらに一歩進めると、1 つのインデックス バッファーを使用して、それぞれが異なる頂点バッファーに含まれる、複数のメッシュ インスタンスを描画することができます。この場合は、単純に頂点バッファーがアクティブなものを循環し、必要に応じて BaseVertexIndex を調整することで達成されます。BaseVertexIndex 値は、MinIndex 引数にも自動的に追加され、使用方法を確認するときに役立ちます。

ここで、前回と同じインデックス バッファーを使用して、クワッドの 2 つめの三角形のみを再描画するとします。ただしクワッドが配置されている VB Index 50 では別の頂点バッファーが使用されています。クワッドの頂点の相対的順序は変更されないままで、頂点バッファー内の開始場所のみが異なります。インデックス バッファーと頂点バッファーは次のようになります。

Ee422176.DIP_fig6(ja-jp,VS.85).gif

以下は適切な描画呼び出しです。前回のシナリオから変更されている値は BaseVertexIndex のみです。

    
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    50,                 // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    3,                  // StartIndex
                    1 );                // PrimitiveCount