2013-05-04 10 views
8

Sto avendo un problema ottenere il mio allineamento vertice hanno indicato correttamente:OpenGL 3/4 glVertexAttribPointer passo e errore di calcolo di offset

const float vertices[] = { 
/* position */ 0.75f, 0.75f, 0.0f, 1.0f, /* color */ 1.0f, 0.0f, 0.0f, 1.0f, 
/* position */ 0.75f, -0.75f, 0.0f, 1.0f, /* color */ 0.0f, 1.0f, 0.0f, 1.0f, 
/* position */ -0.75f, -0.75f, 0.0f, 1.0f, /* color */ 0.0f, 0.0f, 1.0f, 1.0f, }; 

... 

glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 
glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)16); 

glDrawArrays(GL_TRIANGLES, 0, 3); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 

io non capisco come passo e spostamento origine. Qual è il modo corretto di utilizzare glVertexAttribPointer() nella mia situazione?

risposta

21

Stride e offset sono specificate in byte. Stai usando un array di vertici interleaved con posizione e colore sia come 4 float. Per ottenere dall'elemento i-esimo in una particolare matrice di attributi alla successiva, c'è la distanza di 8 galleggianti, quindi il passo dovrebbe essere 8 * sizeof (GLfloat). L'offset è la posizione del byte del primo elemento di ogni array di attributi nel buffer, quindi nel tuo esempio per la posizione è 0 e per il colore è 4 * sizeof (GLfloat)

+0

Quali dovrebbero essere i miei due glVertexAttribPointer valori di spostamento e offset? – user2350858

+0

@ user2350858: Come ho già scritto nella risposta: stride è 8 * sizeof (GLfloat) (in genere 32) e offset 0 per la posizione e 4 * sizeof (GLfloat) per il colore (come già si fa) – derhass

15

Poiché glVertexAttribPointer spesso causa problemi, Cerco di spiegarlo ulteriormente qui.

La formula per calcolare le pos inizio dell'attributo i-esimo attributi dell'array è:

startPos(i) = offset + i * stride (da derhass' another answer)

e illustrate nel grafico seguente: tightly packed arrtibute array


Se è necessario un esempio di codice, continuare a leggere.

Da Formatting VBO Data, sappiamo che possiamo gestire i nostri dati di vertice in tre formati. Fare un esempio di disegnare un triangolo, con il colore e il colore vert trama miscelati, ecco il modo di preparare vert dati degli attributi:


# way1 ogni attributo di un VBO.

questo formato come: (xyzxyz ...) (RGBRGB ...) (INOX ....), e possiamo lasciare che sia sride = 0 e offset = 0.

void prepareVertData_moreVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 
    GLfloat vertPos[] = { 
     -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, // positon 
    }; 
    GLfloat vertColor[] = { 
     1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // color 
    }; 
    GLfloat vertTextCoord[] = { 
     0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f  // texture coordinate 
    }; 

    GLuint VBOId[3]; 

    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 
    glGenBuffers(3, VBOId); 
    // specify position attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[0]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertPos), vertPos, GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[1]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertColor), vertColor, GL_STATIC_DRAW); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[2]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertTextCoord), vertTextCoord, GL_STATIC_DRAW); 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId[0]); 
    VBOIdVec.push_back(VBOId[1]); 
    VBOIdVec.push_back(VBOId[2]); 
} 

# way2: ogni attributo è sequenziale, raggruppato in un singolo VBO.

questo formato è simile a: (xyzxyzxyz ... rgbrgb ... ststst ...), possiamo lasciare falcata = 0 ma l'offset deve essere specificato.

void prepareVertData_seqBatchVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 

    GLfloat vertices[] = { 
    -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, // position 
    1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // color 
    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f  // texture coordinate 
    }; 

    GLuint VBOId; 
    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 

    glGenBuffers(1, &VBOId); 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    // specifiy position attribute 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); // stride can aslo be 3 * sizeof(GL_FLOAT) 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(9 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(18 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId); 
} 

# Way3: attributo Interleaved in un unico VBO

questo formato è come: (xyzrgbstxyzrgbst ...), dobbiamo specificare manualmente l'offset e stride.

void prepareVertData_interleavedBatchVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 
    // interleaved data 
    GLfloat vertices[] = { 
     -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0 
     0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 1 
     0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // 2 
    }; 

    GLuint VBOId; 
    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 
    glGenBuffers(1, &VBOId); 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    // specify position attribute 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,8 * sizeof(GL_FLOAT), (GLvoid*)0); 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 
     8 * sizeof(GL_FLOAT),(GLvoid*)(3 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 
     8 * sizeof(GL_FLOAT), (GLvoid*)(6 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId); 
} 

E grazie per la risposta di derhass.

+0

Wow, ero cercando di avvolgere il mio cervello attorno alle differenze dei 3 metodi per la parte migliore di un giorno (principalmente interleaving vs gli altri, e come usare correttamente l'offset), poi l'ho visto, fianco a fianco, e tutto è diventato chiaro. Grazie. ;) Qualche idea che di solito è più veloce? –