2012-01-21 20 views
7

Dopo aver cercato e letto su Modern OpenGL per aggiornare il mio progetto esistente, sono un po 'confuso, dal mio framework 3D basato su OpenGL 2.1.Modern OpenGL: VBO, GLM e Matrix Stacks

in modo, per quanto imparo ...

  • Abbiamo bisogno di generare i nostri Vertex-Buffer-Oggetti da vertici, indici, normali, colori, UV, ecc

  • poi possiamo usare GLM per matrice di trasformazione, e utilizzare solo VBO per creare o manipolare mesh, infine si passa tutto in Shader GLSL vertex simili ...

    glm::mat4 MVP = projection * view * model; 
    glUniformMatrix4fv(glGetUniformLocation(shaderProgramID, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); //or &MVP[0][0] 
    
    // uniform mat4 MVP; 
    // in vec3 Vertex; 
    // void main(void) 
    // { 
    // gl_Position = MVP * vec4(Vertex, 1.0); //instead of ftransform(); 
    // } 
    

DOMANDA: Come facciamo le trasformazioni gerarchiche senza pushMatrix/popMatrix? (o forse facciamo una trasformazione gerarchica usando i nostri VBO, è possibile?)

Se non è possibile, come ottenere lo stesso risultato di pushMatrix/popMatrix utilizzando la libreria stack> GLM e C++ <?

Diciamo che ho bisogno di qualcosa di simile:

> Set identity 
> Translate to X, Y, Z 
> Draw Mesh 1 
> Rotate 0.5 by X axis 
> Draw Mesh 2 
> Scale down to 0.1 
> Draw Mesh 3 
+1

@ BЈовић: [OpenGL Mathematics (GLM)] (http://glm.g-truc.net/), una libreria C++ di sola intestazione per matematica a matrice/vettoriale. – genpfault

risposta

5
  • Abbiamo bisogno di generare i nostri Vertex-Buffer-Oggetti da vertici, indici, normali, colori, UV, ecc

Non è proprio necessario utilizzare VBOs, Anche i Vertex Array lato client funzionano. Tuttavia è fortemente raccomandato l'uso di VBO, perché rende più facile la vita del conducente e, a lungo termine, anche il tuo come colui che deve manipolare i dati. Il sovraccarico del codice è trascurabile (equivale a generare e caricare i dati della trama) e le prestazioni aumenteranno solo.

  • quindi possiamo usare GLM per matrice di trasformazione, e utilizzare solo VBO per creare o manipolare mesh, infine si passa tutto in Shader GLSL vertex simili ...

È Non sono limitati a GLM. Qualunque libreria matematica a matrice farà. Se stai cercando qualcosa che puoi usare in C99, dai un'occhiata al mio (ancora incompleto) linmath.hhttps://github.com/datenwolf/linmath.h che è solo un file di intestazione con le funzioni static inline.Devo ancora fare un benchmark se la duplicazione del codice ha un impatto negativo sulle prestazioni (la dimensione del codice crea una pressione della cache L1).

DOMANDA: Come facciamo trasformazioni gerarchici senza pushMatrix/popMatrix? (o forse facciamo una trasformazione gerarchica usando i nostri VBO, è possibile?)

I VBO non hanno nulla a che fare con questo. Ciò che dà la maggior parte degli utenti di problemi OpenGL vecchio stile sono quelle funzioni matrix stack, che rendono OpenGL un po 'come un grafico di scena. Ma non è.

Se si dimentica lo stack matrix della vecchia OpenGL, diventa ovvio come eseguire le trasformazioni gerarchiche: in ogni ramo della gerarchia eseguire una copia della matrice di trasformazione e operare su quella. Ottieni un albero gerarchico di trasformazioni, in ogni nodo viene memorizzata la matrice corrispondente. Quindi si passa quelle matrici come uniformi allo shader del vertice; o solo una matrice se stai disegnando un oggetto rigido che ha una sola trasformazione. matrici multiple di solito usati solo per deformables come l'animazione scheletrica di un personaggio come questo

worldtransform -> 
    pelvis -> 
     left upper leg -> left lower leg -> left foot 
     right upper leg -> right lower leg -> right foot 
    torso -> 
     neck -> head -> 
      left eye 
      right eye 
      facial deformation // this is a whole chapter of it's own 
     left upper arm -> left lower arm -> left hand 
     right upper arm -> right lower arm -> right hand 

Ogni volta che un enounter -> in tale gerarchia si crea una copia della matrice e procedere a lavorare su quello. Quando si rientra a un livello più alto dell'albero, si ricomincia a lavorare da quella matrice.

+1

"deformazione facciale" // questo è un intero capitolo a sé stante => include jaw drop :) – mlvljr

4

Sì, se avete bisogno di trasformazioni gerarchici, allora si hanno a che fare da soli. Tuttavia, è praticamente banale se tutto ciò di cui hai bisogno è uno stack. Basta prendere l'ultima voce in pila e moltiplicarla con la matrice successiva che si desidera applicare e spingere il risultato in pila.

[Sulla domanda modificata]: Non è necessario alcuno stack per questo, e non c'è nemmeno una trasformazione gerarchica. Basta avere una singola matrice e applicare la traduzione, disegnare, moltiplicarla con la matrice di rotazione, disegnare, moltiplicare il ridimensionamento, disegnare.

+1

Er? Se hai la matrice iniziale M e la traduzione T, la rotazione R e la scala S, allora la tua prima matrice è M = T, la seconda è M * = R = (T * R == prima traduzione, rotazione seconda), e il terzo è M * = S = (T * R * S == tutte le matrici.) Per un braccio di robot, puoi anche iniziare in cima ed emettere chiamate a mano mentre scendi dal tuo albero. Non importa se lo "stack" è uno std :: stack o solo una parte della routine di attraversamento di scene ricorsive. – Anteru

+0

Se non si esegue M * = S, ma si usa semplicemente M * S (copia!), La matrice originale non viene modificata. Il tuo stack sarebbe simile a questo: [M], quindi premi T (risultante in una pila [M, M * T]), poi fai un pop ([M]), quindi premi di nuovo R ([M, M * R]). Non capisco il tuo problema? – Anteru

+0

Interrompere la modifica del significato dei commenti. Ho detto che puoi implementarlo tramite uno stack, o che puoi semplicemente copiare le tue matrici all'interno della tua funzione di disegno ricorsivo (che crea implicitamente una pila). Il [M, ..] è uno stack_, se lo vuoi, basta usarlo . Ma puoi facilmente andare via anche senza std :: stack. – Anteru

4

Se il rendering avviene già in modo gerarchico utilizzando, ad esempio, la ricorsione della funzione, si dispone già di uno stack matrix!

void renderMesh(Matrix transform, Mesh mesh) 
{ 
    // here call glDrawElements/glDrawArrays and send transform matrix to MVP uniform 
    mesh->draw(transform); 

    // now render all the sub-meshes, then will be transformed relative to current mesh 
    for (int i=0; i<mesh->subMeshCount(); i++) 
    { 
     Matrix subMeshTransform = mesh->getSubMeshTransform(i); 
     Mesh subMesh = mesh->getSubMesh(); 

     renderMesh(subMeshTransform * transform, subMesh); 
    } 
} 

// somwhere in main function 
... 
Matrix projection = Matrix::perspective(...); 
Matrix view = camera->getViewMatrix(); 

Matrix transform = view * projectIon; 
renderMesh(transform, rootMesh); 
0

Per quanto riguarda VAO e VBO prestazioni non sono d'accordo che VBO è più veloce, vi suggerisco di vedere questo link

http://www.openglsuperbible.com/2013/12/09/vertex-array-performance/

Si può vedere dai risultati di cui sopra che, almeno per il nostro piccolo set di esempio , VAO è più veloce su tutte le implementazioni. È ovvio che ci sono meno parametri da convalidare quando si chiama glBindVertexArray di glBindBuffer o glVertexAttribPointer. Anche quando esiste un solo attributo vertice, ci sono metà delle chiamate in OpenGL con uno switch VAO rispetto all'aggiornamento esplicito di un VAO globale. Oltre all'ovvia "minor numero di chiamate API significa più rapida esecuzione", il VAO è un luogo in cui un driver OpenGL può immagazzinare le informazioni richieste per programmare la GPU sottostante. La quantità totale di modifiche di stato inviate alla GPU è la stessa in entrambi i casi.

+0

Come è correlato alla domanda? –