2014-07-01 52 views
2

我使用OpenGL和GLSL開發了一個小型3D引擎。是否可以將函數'glMultiDrawElements'使用索引緩衝區對象(IBO)?

我已經合併了一個頂點數據批處理系統,其目標是收集共享相同着色器程序和相同轉換的唯一頂點緩衝區對象(VBO)中的所有幾何圖形(所有對象),從而最大限度地減少狀態變化(綁定)並且也可以畫電話。

我目前使用函數'glMultiDrawElements'來渲染特定的一批數據(所以一個繪製調用)。所以,例如,如果我在我的批處理3網格中,我也有3個索引數組(一個用於每個網格)組織在'GLvoid **'數組(雙數組)中。因此,爲了呈現我的3個網格,我有一個獨特的glMultiDrawElements調用,但我必須直接傳遞給參數中double元素的函數。如果可以將所有元素(元素的雙數組)存儲在索引緩衝區對象(IBO)中(比如可以使用glDrawElements - >這裏是一個簡單的例子),但我想知道(對於性能問題)數組元素)並在glMultiDrawElements調用之前綁定它...我不這麼認爲,因爲它是一個雙數組而不是簡單的數組,但也許(我希望如此),我錯了。

下面是使用glDrawElements(僞代碼)的例子:

[...] 

//Setup data 

[...] 

#define OFFSET_BUFFER(offset) ((char*)NULL + offset) 

foreach (pMeshGeometry from meshes) //iterates for each mesh of the scene 
{ 
    pMeshGeometry->GetIndexBuffer().Lock(); //Bind IBO 
    { 
     glDrawElements(pMeshGeometry->GetPrimitiveType(),  
      pMeshGeometry->GetIndexBufferSize(), pMeshGeometry->GetIndexBuffer().GetType(), OFFSET_BUFFER(0)); //Render a specific mesh eccording to indices 
    } 
} 

目前我使用glMultiDrawElement這樣:

glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT, 
        (const GLvoid **)&this->m_IndexAttribArray[0], this->m_CountElementArray.size()); //I enter the array of pointer directly in parameter 

所以,也許對下面的例子應該是可能的:

#define OFFSET_BUFFER(offset) ((char**)NULL + offset) //Something like this 

glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT, 
        OFFSET_BUFFER(0), this->m_CountElementArray.size()); //Something like this 

所以,如果這是不可能的,我想到了函數'glDrawRangeElemen TS'。對於我的3個網格到一個獨特的VBO的例子,我只需要在每個glDrawRangeElements調用之前綁定一個IBO(這裏,3爲每個網格繪製調用 - >這樣一個glDrawRangeElements循環)。所以這裏顯然可以使用IBO。

這種方法肯定會有效,但我認爲它不是最好的!我認爲可以使用glMultiDrawElements和IBO做到這一點,但我不知道如何做到這一點。

或者這可能是不可能的。也許事實上,在參數數組中輸入directy比使用glDrawRangeElements和它的IBO的方法快,所以在這種情況下IBO的使用可能被棄用,因此不適用。

您對此有何看法?

+2

_請使用一些換行符。這個巨大的段落幾乎不可能閱讀。 –

+0

你到底在問什麼?即使有換行符,我也不確定。 – Aumnayan

+0

對不起,我認爲這很清楚。總結一下,我想知道是否可以在glMultiDrawElements中使用IBO,而不是直接在參數中使用雙數組索引。 – user1364743

回答

7

你當然可以使用索引緩衝區glMultiDrawElements()。客戶端索引數組在OpenGL核心配置文件中已棄用。因此,如果glMultiDrawElements()無法與索引緩衝區一起運行,則無法再使用它。

要看它是如何工作的,我們需要看看glMultiDrawElements()的參數是什麼意思。通話基本上只是多個glDrawElemens()通話的快捷方式。簽名是:

void glMultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, 
         const GLvoid** indices, GLsizei primcount); 

除了一些錯誤檢查的詳細信息,此調用等效於:

for (int i = 0; i < primcount; ++i) { 
    glDrawElements(mode, count[i], type, indices[i]); 
} 

現在還記得,如果索引緩存綁定,最後一個參數glDrawElements()是一個相對偏移進入緩衝區。因此glMultiDrawElements()的相應第4個元素是偏移量的數組放入緩衝區。第二個參數是一個匹配的計數數組。

人們經常使用宏來隱藏glDrawElements()最後一個參數的繁瑣類型轉換。使用這樣的:

#define BUFFER_OFFSET(offset) (static_cast<char*>(0) + (offset)) 

舉個例子,假設我們有一個索引緩存約束,我們要繪製指數陣列的3子範圍有一個單一的電話:

  • 20個指數開始在緩衝區中的索引10處。
  • 30個索引從緩衝區中的索引40開始。
  • 10個索引從緩衝區中的索引90開始。

我將使用無符號短褲(GLushort)作爲索引類型。所以在過去的某個時候,索引緩衝區已經填充了來自GLushort indexA[100]的數據。設置和繪製調用然後看起來像這樣:

GLsizei count[3] = {20, 30, 10}; 
GLvoid* indices[3] = { 
    BUFFER_OFFSET(10 * sizeof(GLushort)), 
    BUFFER_OFFSET(40 * sizeof(GLushort)), 
    BUFFER_OFFSET(90 * sizeof(GLushort)), 
}; 
glMultiDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_SHORT, indices, 3); 
+0

非常感謝您提供完整的答案。我相信你的解決方案是最好的,它是非常合乎邏輯的。我將把它整合到我的程序中。祝你有美好的一天。再見! – user1364743

相關問題