2015-04-11 14 views
5

Quindi, mi sono imbattuto in alcune stranezze tra GLSL e GLM.incoerenze con le matrici matematiche tra GLSL e GLM, oppure esiste una matrice di visualizzazione "cattiva"

Se genero seguente vista matrice (C++):

vec3 pos(4, 1, 1); 
vec3 dir(1, 0, 0); 
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1)); 

E poi, in GLSL, do:

fragColour.rgb = vec3(inverse(viewMat) * vec4(0,0,0,1))/4.f; 

Poi mi aspetto per lo schermo diventi rosso-rosato, o (1.0,0.25,0.25). Invece, divento nero.

Se faccio questo in GLM, però:

vec3 colour = vec3(glm::inverse(viewMat) * vec4(0,0,0,1))/4.f; 
cout << glm::to_string(colour) << endl; 

ottengo il risultato di aspettarsi (1.0,0.25,0.25).

Ora, se cambio la viewMat di essere invece (C++):

vec3 pos(4, 1, 1); 
vec3 dir(1, 0.000001, 0); 
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1)); 

poi bam! Ottengo (1,0,0.25,0.25) in entrambi GLSL e GLM.

Questo non ha senso per me. Perché fa questo? Questa view matrix funziona bene ovunque in GLSL - Non riesco proprio a invertirla. Questo succede ogni volta che dirY == 0.f.

Inoltre, si prega di suggerire miglioramenti per il titolo della domanda, non sono sicuro di cosa dovrebbe essere.

Modifica: Inoltre, non sembra avere nulla a che fare con lookAt's up vector (che ho impostato su Z comunque). Anche se ho impostato su (0,1,0), accade la stessa cosa. Tutto gira di lato, ma non riesco ancora a invertire la matrice delle viste in GLSL.

Modifica: Ok, quindi su suggerimento di derhass, ho provato a inviare la matrice di visualizzazione già invertita. Bam, funziona perfettamente. Quindi, sembra che la mia implementazione GL sia in qualche modo incapace di invertire quella matrice. Questo dovrebbe essere facilmente il bug GL più strano che abbia mai incontrato. Sarebbe comunque gradita una qualche spiegazione del perché sia ​​una cattiva idea quella di invertire le matrici negli shader. EditAgain: l'invio di matrici invertite nel mio motore ha comportato un enorme aumento di framerate. DEFINITIVAMENTE FACCIAMO.

+2

Bene, per quanto posso dire, questo problema è totalmente irrealizzato. Sembra che questo sia solo un problema con l'inversione in GLSL. Il modo in cui la matrice è impostata, dovrebbe essere perfettamente invertibile e i problemi numerici non dovrebbero essere un problema. Questo potrebbe essere solo un problema con la tua implementazione GL. Si noti inoltre che l'inversione delle matrici nello shader è una cattiva idea nella maggior parte dei casi, ma ovviamente dovrebbe funzionare. Raccomando di testarlo con alcune altre implementazioni GL, se possibile. – derhass

+0

@derhass Ahhh, non avevo considerato l'invio della matrice già invertita. Ci proverò. Cercherò anche di vedere se il problema si verifica anche altrove. Sto usando un driver nvidia abbastanza vecchio (quello dei repository di Ubuntu 14.04) al momento. – Jagoly

+0

Questa è stata la prima volta che ho appreso che GLSL ora ha una funzione inversa. Non è sicuramente un'operazione amichevole della GPU. Sii sempre consapevole della gerarchia delle operazioni: Per disegnare, per vertice, per frammento. Spostare sempre le cose il più in basso possibile. Hai appena colpito un percorso di codice molto improbabile facendo inverso per vertice. Si noti inoltre che un inverso generico di solito non è necessario. La maggior parte delle matrici di visualizzazione del modello dovrebbe essere "orto normale". Dove l'inversa è la stessa della trasposizione. – starmole

risposta

4

matrice 4x4 arbitraria inversione non è un compito facile e sicuro

Per molte ragioni, come minore precisione FPU sul lato GPU e la necessità di molte divisioni durante l'inversione (ben dipende dal metodo di calcolo), e non tutte le matrici hanno inverso ecc. (penso che sia anche la ragione per cui GL non ha tale implementazione) ... Per una migliore immagine su questo vedi Understanding 4x4 homogenous transform matrices e cercare la funzione matrix_inv lì quanto è complesso il calcolo realmente (usa i determinanti) . C'è anche GEM (metodo di eliminazione di Gauss), ma non è usato a causa delle sue stranezze e della necessità di ordinare le righe ...

Se le matrici sono statiche per rendering di frame che di solito è uno spreco di alimentazione GPU calcolandolo in Vertex/Fragment/Geometry shader ancora e ancora per ogni Vertice/Frammento (ecco perché il boost di velocità è lì).

Qualcuno potrebbe opporre che orthogonal homogenous matrix inversione è solo che recepisce la matrice, ma come il GL/GLSL poteva sapere che si tratta di tale matrice (l'assegno non è così semplice o) comunque in questo caso è possibile utilizzare transpose che viene realizzato in GLSL e dovrebbe essere veloce (è solo il riordino degli elementi)

+2

Mi aspetto che questa sia la risposta. L'inversione della matrice di solito porta all'instabilità numerica e, se possibile, eviterei quasi sempre di invertire una matrice. –

+0

@DietrichFai anche a me ma nella grafica soprattutto con gli effetti della fotocamera non si può evitare facilmente :( – Spektre

+0

Questo è un malinteso comune, di solito è molto facile da evitare.È possibile generare la matrice per le normali e fare proiezioni inverse e simili senza mai dover calcolare l'inverso di una matrice generale. –

Problemi correlati