2009-10-28 13 views
16

Ho un po 'di esperienza nella scrittura di applicazioni OpenGL 2 e voglio imparare usando OpenGL 3. Per questo ho comprato il "Red-book" e "Orange-book" (GLSL) di Addison Wesley che descrivono il deprecation del fisso funzionalità e la nuova pipeline programmabile (shader). Ma ciò di cui non riesco a capire è come costruire una scena con più oggetti senza usare le funzioni di traduzione *, rotazione * e ridimensionamento * deprecate.Come tradurre oggetti singoli in OpenGL 3.x?

Quello che ho usato in OGL2 era "spostarmi" nello spazio 3D usando le funzioni di traduzione e rotazione e creare gli oggetti in coordinate locali dove li volevo usando glBegin ... glEnd. In OGL3 queste funzioni sono tutte deprecate e, come ho capito, sostituite da shader. Ma non posso chiamare un programma shader per ogni oggetto che creo, posso? Questo non influenzerebbe anche tutti gli altri oggetti?

Non sono sicuro di aver spiegato il mio problema in modo soddisfacente, ma il nucleo di esso è come programmare una scena con più oggetti definiti in coordinate locali in OpenGL 3.1. Tutte le esercitazioni per principianti che ho trovato utilizza solo un singolo oggetto e non ha/risolve questo problema.

Modifica: Immagina di volere due cubi rotanti. Sarebbe un dolore modificare manualmente ogni coordinata del vertice, e non puoi semplicemente modificare la matrice modelview, perché questo preferirebbe ruotare la telecamera attorno a due cubi statici ...

risposta

20

Iniziamo con le nozioni di base.

Di solito, si vuole trasformare i vertici del triangolo locali attraverso le seguenti fasi:

local-space coords-> world-space coords -> view-space coords -> clip-space coords

In serie GL, i primi 2 trasformazioni sono fatte attraverso GL_MODELVIEW_MATRIX, il terzo viene fatto attraverso GL_PROJECTION_MATRIX

Queste trasformazioni di vista modello, per le molte trasformazioni interessanti che di solito vogliamo applicare (ad esempio, tradurre, ridimensionare e ruotare, ad esempio), possono essere espresse come moltiplicazione con matrice vettoriale quando rappresentiamo i vertici in homogeneous coordinates. In genere, il vertice V = (x, y, z) è rappresentato in questo sistema come (x, y, z, 1).

Ok. Diciamo che vogliamo trasformare un vertice V_local attraverso una traduzione, quindi una rotazione, quindi una traduzione. Ogni trasformazione può essere rappresentata come una matrice *, chiamiamoli T1, R1, T2. Vogliamo applicare la trasformazione a ciascun vertice: V_view = V_local * T1 * R1 * T2.La moltiplicazione della matrice essendo associativa, possiamo calcolare una volta per tutte M = T1 * R1 * T2.

In questo modo, è sufficiente passare M al programma vertice e calcolare V_view = V_local * M. Alla fine, un vertex shader tipico moltiplica la posizione del vertice di una singola matrice. Tutto il lavoro per calcolare quella matrice è come spostare il tuo oggetto dallo spazio locale allo spazio della clip.

Ok ... ho dato un'occhiata a una serie di dettagli importanti.

Innanzitutto, ciò che ho descritto finora copre solo la trasformazione che di solito vogliamo fare fino allo spazio della vista, non lo spazio della clip. Tuttavia, l'hardware prevede che la posizione di output del vertex shader sia rappresentata in quello spazio clip speciale. È difficile spiegare le coordinate dello spazio di clip senza una matematica significativa, quindi lo escluderò, ma il punto importante è che la trasformazione che porta i vertici a quello spazio di clip può solitamente essere espressa come lo stesso tipo di moltiplicazione di matrice. Questo è ciò che il vecchio gluPerspective, glFrustum e glOrtho compute.

In secondo luogo, questo è ciò che si applica alle posizioni dei vertici. La matematica per trasformare le normali è un po 'diversa. Questo perché vuoi che la norma rimanga perpendicolare alla superficie dopo la trasformazione (per riferimento richiede una moltiplicazione per la trasposizione inversa della vista del modello nel caso generale, ma può essere semplificata in molti casi)

Terzo, non si inviano mai le coordinate 4-D al vertex shader. In generale passi 3-D. OpenGL trasformerà quelle 3-D coordinate (o 2-D, btw) in 4-D in modo che il vertex shader non debba aggiungere le coordinate extra. espande ogni vertice per aggiungere 1 come coordinata w.

Quindi ... per rimettere tutto insieme, per ogni oggetto, è necessario calcolare quelle m magiche M basate su tutte le trasformazioni che si desidera applicare all'oggetto. All'interno dello shader, devi quindi moltiplicare ogni posizione di vertice per quella matrice e passarla all'output di vertex shader Position. tipico codice è più o meno (questo sta usando vecchia nomenclatura):

mat4 MVP; 
gl_Position=MVP * gl_Vertex; 

* le matrici effettivi possono essere trovati sul web, in particolare sulle relative pagine per ciascuna di queste funzioni: rotate, translate, scale, perspective , ortho

+1

Grazie per questa risposta molto accurata! Un dettaglio che mi mancava era che puoi cambiare la matrice MVP (ad esempio dichiarandola uniforme) tra le chiamate a glDrawElements ... Strano spostamento da khronos per lasciare comunque le specifiche di queste matrici molto comuni al programmatore. Spero che troveranno presto la loro strada in glu o simili ... – Wonko

+0

Ecco a cosa serve il middleware. GL3.2 è meno espressivo per la codifica rapida. Ma le versioni precedenti erano comunque il livello sbagliato di astrazione per l'applicazione reale. Richiedeva un quadro di gestione dello stato su di esso. Inoltre, dite che volete mantenere le matrici. Ciò significa che l'autista deve mantenere tutti gli stack matrix, come passarli solo a tutti gli shader che lo richiedono (non solo i vertici), capire quale sapore è necessario: M, MV, MVP, IT (MV), IT (M). La parte peggiore ? l'app è l'unica in grado di rendere efficiente il calcolo matematico, eseguendo molte operazioni sulla matrice contemporaneamente. GL non può farlo in modo efficiente. – Bahbar

1

Queste funzioni sono apparentemente deprecate, ma sono tecnicamente ancora perfettamente funzionante e in effetti verrà compilato. Quindi puoi certamente usare le funzioni translate3f (...) etc.

TUTTAVIA, this tutorial ha una buona spiegazione di come i nuovi shader e così via funzionano, E per più oggetti nello spazio.

È possibile creare array di x di vertici e associarli in oggetti x VAO e renderizzare la scena da lì con shader, ecc ... meh, è ​​più facile leggerlo - è davvero una buona lettura per cogliere i nuovi concetti.

Inoltre, il "Red Book" OpenGL come viene chiamato ha una nuova versione - The Official Guide to Learning OpenGL, Versions 3.0 and 3.1. Include "Discussione sul meccanismo di deprecazione di OpenGL e su come verificare i tuoi programmi per le versioni future di OpenGL".

Spero che sia di qualche aiuto!

+0

Ancora grazie per la rapida risposta. Ho letto il tutorial che hai citato, ma sebbene crei due triangoli, li crea in coordinate globali - non locali come voglio. Il problema è che quando si ha un modello più complicato, può essere complicato usare le coordinate globali, specialmente se il modello si muove. Inoltre, voglio caricare un oggetto premade da un file obj e posizionarlo da qualche parte nello spazio 3D. – Wonko

+8

@ Mark Il primo collegamento è rotto. – Jeff