從頂點和索引緩衝區轉譯 (Direct3D 9)

Direct3D 支援已編制索引和非索引的繪圖方法。 索引方法會針對所有頂點元件使用單一索引集。 頂點資料會儲存在頂點緩衝區中,而索引資料則會儲存在索引緩衝區中。 以下是使用頂點和索引緩衝區繪製基本類型的一些常見案例。

這些範例會比較 使用 IDirect3DDevice9::D rawPrimitiveIDirect3DDevice9::D rawIndexedPrimitive

案例 1:繪製兩個三角形而不編制索引

假設您想要繪製下圖所示的四邊形。

由兩個三角形組成的方形圖例

如果您使用三角形清單基本類型來呈現這兩個三角形,則每個三角形都會儲存為 3 個個別頂點,因此下圖會產生類似的頂點緩衝區。

定義兩個三角形三個頂點的頂點緩衝區圖表

繪圖呼叫非常簡單;從頂點緩衝區內的位置 0 開始,繪製兩個三角形。 如果已啟用擷取,頂點的順序將會很重要。 此範例假設預設的逆時針遞減狀態,因此必須依順時針順序繪製可見的三角形。 三角形清單基本類型只會從每個三角形的緩衝區中以線性順序讀取三個頂點,因此此呼叫會繪製三角形 (0、1、2) 和 (3、4、5) :

DrawPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
               0,                  // StartVertex
               2 );                // PrimitiveCount

案例 2:使用索引繪製兩個三角形

如您所注意到,頂點緩衝區包含位置 0 和 4、2 和 5 中的重復資料。 這很合理,因為兩個三角形共用兩個常見的頂點。 此重複的資料會浪費,而且頂點緩衝區可以使用索引緩衝區來壓縮。 較小的頂點緩衝區可減少必須傳送至圖形配接器的頂點資料量。 更重要的是,使用索引緩衝區可讓配接器將頂點儲存在頂點快取中;如果繪製的基本類型包含最近使用的頂點,則可以從快取擷取該頂點,而不是從頂點緩衝區讀取它,這會導致大幅提升效能。

索引緩衝區 「索引」到頂點緩衝區中,因此每個唯一頂點只需要儲存在頂點緩衝區中一次。 下圖顯示先前繪圖案例的索引方法。

先前頂點緩衝區的索引緩衝區圖表

索引緩衝區會儲存 VB 索引值,以參考頂點緩衝區內的特定頂點。 頂點緩衝區可以視為頂點陣列,因此 VB 索引只是目標頂點頂點頂點的索引。 同樣地,IB Index 是索引緩衝區中的索引。 如果您不小心,這會非常令人困惑,因此請務必清楚使用中的詞彙:VB 索引值索引到頂點緩衝區、IB 索引值索引到索引緩衝區,而索引緩衝區本身會儲存 VB 索引值。

繪圖呼叫如下所示。 下一個繪圖案例的長度會討論所有引數的意義;現在請注意,此呼叫再次指示 Direct3D 轉譯包含兩個三角形的三角形清單,從索引緩衝區內的位置 0 開始。 此呼叫會以與之前完全相同的順序繪製相同的兩個三角形,以確保適當的順時針方向:

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

案例 3:使用索引繪製一個三角形

假設您現在只想要繪製第二個三角形,但您想要使用繪製整個四邊形時所使用的相同頂點緩衝區和索引緩衝區,如下圖所示。

第二個三角形的索引緩衝區和頂點緩衝區圖表

針對此繪圖呼叫,使用的第一個 IB 索引為 3;這個值稱為 StartIndex。 使用的最低 VB 索引為 0;此值稱為 MinIndex。 即使只需要三個頂點來繪製三角形,這三個頂點仍會分散到頂點緩衝區中的四個相鄰位置;繪圖呼叫所需的連續頂點緩衝區記憶體區塊內的位置數目稱為 NumVertices,而且在此呼叫中會設定為 4。 MinIndex 和 NumVertices 值實際上只是協助 Direct3D 在軟體頂點處理期間優化記憶體存取的提示,而且可以直接設定為以效能價格包含整個頂點緩衝區。

以下是單一三角形案例的繪圖呼叫;接下來將說明 BaseVertexIndex 引數的意義:

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

案例 4:使用位移索引繪製一個三角形

BaseVertexIndex 是一個值,可有效地新增至儲存在索引緩衝區中的每個 VB 索引。 例如,如果我們在上一次呼叫期間傳入 BaseVertexIndex 的值為 50,則其功能上會與在 DrawIndexedPrimitive 呼叫期間使用下列圖表中的索引緩衝區相同:

basevertexindex 值為 50 的索引緩衝區圖表

這個值很少設定為 0 以外的任何專案,但如果您想要將索引緩衝區與頂點緩衝區分離,可能很有用:如果在填入特定網格的索引緩衝區時,頂點緩衝區內網格的位置還不知道,您只要預先假設網格頂點會位於頂點緩衝區的開頭;在進行繪製呼叫時,只要將實際的起始位置傳遞為 BaseVertexIndex 即可。

使用單一索引緩衝區繪製網格的多個實例時,也可以使用這項技術;例如,如果頂點緩衝區包含兩個網格具有相同繪製順序,但頂點稍有不同的頂點, (可能不同的擴散色彩或紋理座標) ,則可以使用 BaseVertexIndex 的不同值來繪製這兩個網格。 進一步採用這個概念,您可以使用一個索引緩衝區來繪製多個網格實例,每個實例都包含在不同的頂點緩衝區中,只要迴圈哪個頂點緩衝區作用中,並視需要調整 BaseVertexIndex。 請注意,BaseVertexIndex 值也會自動新增至 MinIndex 引數,當您看到其使用方式時,這很合理:

假設我們再次想要只使用與之前相同的索引緩衝區繪製四邊形的第二個三角形;不過,正使用不同的頂點緩衝區,其中的四邊形位於 VB 索引 50。 四個頂點的相對順序保持不變,只有頂點緩衝區內的起始位置不同。 索引緩衝區和頂點緩衝區看起來像下圖。

索引緩衝區和頂點緩衝區的圖表,其 vb 索引為 50

以下是適當的繪製呼叫;請注意,BaseVertexIndex 是唯一已從上一個案例變更的值:

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

轉譯基本類型