2016-05-29 52 views
2

我有OpenGL代碼使用一個VAO爲所有模型數據和兩個VBO。第一個用於標準頂點屬性,如位置和法線,第二個用於模型矩陣。我使用的是instanced draw,因此我將模型矩陣作爲實例化數組(基本上是頂點屬性)加載。如何在使用實例化數組時使glVertexAttribPointer調用最小化?

首先,我將標準頂點屬性加載到VBO,並使用glVertexAttribPointer設置所有內容。然後我將模型矩陣加載到另一個VBO。現在我必須在循環中調用glVertexAttribPointer。我能以某種方式防止這種情況嗎

的代碼看起來是這樣的:

// vertex data of all models in one array 
GLfloat myvertexdata[myvertexdatasize]; 

// matrix data of all models in one array 
// (one model can have multiple matrices) 
GLfloat mymatrixdata[mymatrixsize]; 

GLuint vao; 
glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 
GLuint vbo; 
glGenBuffers(1, &vbo); 
glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glBufferData(GL_ARRAY_BUFFER, myvertexdatasize*sizeof(GLfloat), myvertexdata, GL_STATIC_DRAW); 

glVertexAttribPointer(
      glGetAttribLocation(myprogram, "position"), 
      3, 
      GL_FLOAT, 
      GL_FALSE, 
      24, 
      (GLvoid*)0 
); 
glEnableVertexAttribArray(glGetAttribLocation(myprogram, "position")); 
glVertexAttribPointer(
      glGetAttribLocation(myprogram, "normal"), 
      3, 
      GL_FLOAT, 
      GL_FALSE, 
      24, 
      (GLvoid*)12 
); 
glEnableVertexAttribArray(glGetAttribLocation(myprogram, "normal")); 

GLuint matrixbuffer; 
glGenBuffers(1, &matrixbuffer); 
glBindBuffer(GL_ARRAY_BUFFER, matrixbuffer); 
glBufferData(GL_ARRAY_BUFFER, mymatrixsize*sizeof(GLfloat), mymatrixdata, GL_STATIC_DRAW); 

glUseProgram(myprogram); 


draw loop: 
    int vertices_offset = 0; 
    int matrices_offset = 0; 
    for each model i: 
     GLuint loc = glGetAttribLocation(myprogram, "model_matrix_column_1"); 
     GLsizei matrixbytes = 4*4*sizeof(GLfloat); 
     GLsizei columnbytes = 4*sizeof(GLfloat); 
     glVertexAttribPointer(
       loc, 
       4, 
       GL_FLOAT, 
       GL_FALSE, 
       matrixbytes, 
       (GLvoid*) (matrices_offset*matrixbytes + 0*columnbytes) 
     ); 
     glEnableVertexAttribArray(loc); 
     glVertexAttribDivisor(loc, 1); // matrices are in instanced array 
     // do this for the other 3 columns too... 

     glDrawArraysInstanced(GL_TRIANGLES, vertices_offset, models[i]->num_vertices(), models[i]->num_instances()); 

     vertices_offset += models[i]->num_vertices(); 
     matrices_offset += models[i]->num_matrices(); 

我想存儲在一個VBO頂點數據和矩陣的方法。問題是如何正確設置步幅。我無法想出解決方案。

任何幫助將不勝感激。

回答

3

如果您有權訪問base-instance rendering(需要GL 4.2或ARB_base_instance),那麼您可以這樣做。把實例化屬性的東西,在安裝與非實例屬性的東西:

GLuint loc = glGetAttribLocation(myprogram, "model_matrix_column_1"); 

for(int count = 0; count < 4; ++count, ++loc) 
{ 
    GLsizei matrixbytes = 4*4*sizeof(GLfloat); 
    GLsizei columnbytes = 4*sizeof(GLfloat); 
    glVertexAttribPointer(
      loc, 
      4, 
      GL_FLOAT, 
      GL_FALSE, 
      matrixbytes, 
      (GLvoid*) (count*columnbytes) 
    ); 
    glEnableVertexAttribArray(loc); 
    glVertexAttribDivisor(loc, 1); // matrices are in instanced array 
} 

然後你只需綁定VAO當你準備渲染這些模型。您繪製調用變成:

glDrawArraysInstancedBaseInstance​(GL_TRIANGLES, vertices_offset, models[i]->num_vertices(), models[i]->num_instances(), matrix_offset); 

此功能surprisingly widely available,即使是在GL預4.x的硬件(只要它有最新的驅動程序)。

但是,如果沒有基礎實例渲染,則無法執行任何操作。您將不得不爲每個要渲染的新組實例調整實例指針。這實際上是爲什麼基礎實例呈現存在。

+0

位置是否始終是後續數字? – mak

+0

@mak:你沒有發佈你的所有代碼,所以我假設你的矩陣屬性實際上是一個'mat4',這是完全可以接受的。如果是,那麼4個位置[將被順序分配](https://www.opengl.org/wiki/Vertex_Attribute)。儘管如此,你根本不應該去這些地點。您應該直接在着色器中指定它們。 –

+0

只做一次就抓取位置有什麼問題? – mak

相關問題