primo, spento VAO "memorizza" solo gli ultimi binding dell'attributo vertice (e il binding VBO per un buffer di indice (GL_ELEMENT_ARRAY_BUFFER_BINDING
), se ce n'è uno). Quindi non ricorda gli offset in glDrawElements()
, è necessario chiamarlo in seguito quando si utilizza VAO. Non impedisce di utilizzare array di vertici interleaved. Vorrei cercare di spiegare:
int vbo[3];
glGenBuffers(3, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, data0, size0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, data1, size1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data2, size2);
// create some buffers and fill them with data
int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// create a VAO
{
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), NULL); // this is VAO saved state
glEnableVertexAttribArray(0); // this is VAO saved state
// sets up one vertex attrib array from vbo[0] (say positions)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); // not saved in VAO
glVertexAttribPointer(1, 3, GL_FLOAT, false, 5 * sizeof(float), NULL); // this is VAO saved state
glVertexAttribPointer(2, 2, GL_FLOAT, false, 5 * sizeof(float), (const void*)(2 * sizeof(float))); // this is VAO saved state
glEnableVertexAttribArray(1); // this is VAO saved state
glEnableVertexAttribArray(2); // this is VAO saved state
// sets up two more VAAs from vbo[1] (say normals interleaved with texcoords)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]); // this is VAO saved state
// uses the third buffer as the source for indices
}
// set up state that VAO "remembers"
glBindVertexArray(0); // bind different vaos, etc ...
tardi ...
glBindVertexArray(vao); // bind our VAO (so we have VAAs 0, 1 and 2 as well as index buffer)
glDrawElements(GL_TRIANGLE_STRIP, 57, GL_UNSIGNED_INT, NULL);
glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_INT, (const void*)(57 * sizeof(unsigned int)));
// draws two parts of the mesh as triangle strips
Così si vede ... è possibile disegnare array di vertice intercalate con glDrawElements
utilizzando un singolo VAO e uno o più VBOs.
Per rispondere alla seconda parte della domanda, è possibile avere diversi VAO e VBO per diverse parti della mesh (quindi disegnare parti separate è semplice) oppure è possibile fondere tutto in una coppia VBO VAO (quindi è necessario non chiamare glBind*()
spesso) e utilizzare più chiamate glDraw*()
per disegnare singole parti della mesh (come si vede nel codice sopra - immagina il primo glDrawElements()
disegna la nave e il secondo disegna la torretta, basta aggiornare una matrice uniforme tra le chiamate).
Poiché gli shader possono contenere più matrici di modelview in uniformi, è anche possibile codificare ID di reticolo come un altro attributo di vertice e consentire al vertex shader di scegliere quale matrice utilizzare per trasformare il vertice, in base a questo attributo. Questa idea può anche essere estesa all'utilizzo di più matrici per un singolo vertice, con alcuni pesi assegnati per ciascuna matrice. Questo è comunemente usato quando si animano oggetti organici come il personaggio del giocatore (cercare "skinning").
Come oggetti buffer uniformi, l'unico vantaggio è che è possibile comprimere un sacco di dati al loro interno e che possono essere facilmente condivisi tra gli shader (basta associare l'UBO a qualsiasi shader che sia in grado di utilizzarlo). Non vi è alcun vantaggio reale nell'usarli per te, eccetto se si dovessero avere oggetti con 1OOO di matrici.
Inoltre, ho scritto i codici sorgente sopra dalla memoria. Fatemi sapere se ci sono alcuni errori/problemi ...
fredda penso lo capisco con l'interleaving, devo provarlo. Ma penso che tu abbia commesso un errore, tanto per essere sicuro, nel disimpegnare il primo glVertexAttribPointer per le posizioni dei vertici, poiché ho capito che le posizioni dei vertici sono strettamente racchiuse in vbo [0] eppure hai dato un passo? Il passo non dovrebbe essere zero per le posizioni poiché non sono interfogliati. – CodeMonkey
Mi piace l'idea dell'ID mesh nello shader e lo passiamo come attributo, ma come faccio a fare l'analisi in molte matrici nello shader (come un array uniforme)? E 'questo il punto in cui posso usare le UBO per passare in forse 10 diverse matrici di trasformazione per 10 diverse torrette e usare un indice analizzato come attributo per cercare la matrice corretta all'interno dello shader? Questo mi permetterebbe anche di usare le funzioni glMultiDrawElements/Arrays disegnando un'intera nave con più parti tutte in una volta sola? – CodeMonkey
Ciao, buona osservazione con il passo. Ma non è un errore. O potrei lasciare il passo 0 e OpenGL saprebbe (dal secondo e terzo argomento) che ho flusso di 3D GL_FLOATS (e quindi la dimensione è 3 * sizeof (float)), o posso calcolare il passo per esso. Non c'è niente di sbagliato in questo. Per chiarire ulteriormente - la falcata è la distanza tra gli indirizzi di due vertici consecutivi, NON è lo spazio tra loro (quindi 0 non significa che non ci sono byte inutilizzati tra i vertici, significa che OpenGL dovrebbe calcolare il passo reale dal numero di dimensioni e tipo di dati utilizzati). –