2013-03-10 5 views
6

Voglio solo essere sicuro di aver capito TBN calcolo matriciale correttamentenormal mapping, TBN calcolo matriciale

In vertex shader siamo soliti usare:

vec3 n = normalize(gl_NormalMatrix * gl_Normal); 
vec3 t = normalize(gl_NormalMatrix * Tangent.xyz); 
vec3 b = normalize(gl_NormalMatrix * Bitangent.xyz); 
mat3 tbn = mat3(t, b, n); 

quanto ho capito questa matrice tbn trasforma un vettore da Tangente spazio a Eye spazio. In realtà vogliamo il contrario: trasformare un vettore dallo spazio dell'occhio allo spazio tangente. Così abbiamo bisogno di invertire la matrice tbn:

tbn = transpose(tbn); // transpose should be OK here for doing matrix inversion 

nota:tbn - dovrebbe contenere soltanto le rotazioni, per questo caso possiamo usare trasposizione di invertire la matrice.

E possiamo trasformare i nostri vettori:

vec3 lightT = tbn * light_vector; 
...   = tbn * ... 

In diversi tutorial, codici sorgente Ho scoperto che autori hanno usato qualcosa di simile:

light.x = dot(light, t); 
light.y = dot(light, b); 
light.z = dot(light, n); 

Il codice di cui sopra fa lo stesso di moltiplicare dalla matrice transposed(tbn).

La domanda:

Dovremmo usare trasposta tbn matrice proprio come ho spiegato sopra? O forse mi manca qualcosa?

Nota con tale soluzione abbiamo vettori (light_vector) trasformati in TBN nel vertex shader, quindi in framment shader dobbiamo solo normalizzarci dalla normale mappa. Un'altra opzione è creare una matrice TBN che si trasformi dallo spazio TBN nello spazio dell'occhio e quindi nello shader del frammento trasformare ogni normale normale dalla mappa normale.

+0

Definire "corretta "? Hai preso il prodotto incrociato dei tuoi vettori normali e tangenti per ottenere il tuo vettore bitangent. Questo è, generalmente parlando, * non * corretto per la maggior parte delle superfici. Potrebbe essere corretto per il tuo, ma la maggior parte della mappatura della trama non usa mappature perfettamente ortogonali alla superficie. –

+0

Giusto, ho aggiornato la domanda. Ho anche cambiato il calcolo dei bitangent. – fen

risposta

0

trasporre non è l'inversione di matrice !!!

miei matrici TBN in vertex shader aspetto:

uniform mat4x4 tm_l2g_dir; 
layout(location=3) in vec3 tan; 
layout(location=4) in vec3 bin; 
layout(location=5) in vec3 nor; 
out smooth mat3 pixel_TBN; 

void main() 
{ 
    vec4 p; 
    //... 
    p.xyz=tan.xyz; p.w=1.0; pixel_TBN[0]=normalize((tm_l2g_dir*p).xyz); 
    p.xyz=bin.xyz; p.w=1.0; pixel_TBN[1]=normalize((tm_l2g_dir*p).xyz); 
    p.xyz=nor.xyz; p.w=1.0; pixel_TBN[2]=normalize((tm_l2g_dir*p).xyz); 
    //... 
} 

dove:

  • tm_l2g_dir è matrice di trasformazione dallo spazio modello locale allo spazio scena globale whitout qualsiasi movimento (cambia solo direzione) per il tuo codice è la tua matrice normale
  • tan, bin, né sono vettori per matrice TBN (come parte dei miei modelli)
.210

né - è vettore normale alla superficie dalla posizione attuale Vertex (può calcolare come vettore moltiplicazione di due vertici di questo vertice)

tan, bin sono vettori perpendicolari solitamente parallele axises mappatura di texture o teselation del modello. Se si scelgono vettori tan/bin errati a volte possono verificarsi alcuni artefatti di illuminazione.per esempio se si dispone cilindro di bidone è proprio asse di rotazione e tan è perpendicolare ad esso lungo il cerchio (tangente)

tan, bin, né deve essere perpendicolari tra loro

è possibile calcolare TBN anche automatico, ma ciò causerà alcuni artefatti. per farlo è sufficiente scelto come tan vettore un vertice utilizzato per il calcolo normale e bin = né x bin

nel frammento di shader io uso pixel_TBN con la mappa normale per calcolare il vero normale per frammento

//------------------------------------------------------------------ 
#version 420 core 
//------------------------------------------------------------------ 
in smooth vec2 pixel_txr; 
in smooth mat3 pixel_TBN; 
uniform sampler2D txr_normal; 
out layout(location=0) vec4 frag_col; 
const vec4 v05=vec4(0.5,0.5,0.5,0.5); 
//------------------------------------------------------------------ 
void main(void) 
    { 
    vec4 col; 
    vec3 normal; 
    col=(texture2D(txr_normal,pixel_txr.st)-v05)*2.0;  // normal/bump maping 
    normal=pixel_TBN*col.xyz; 
    // col=... other stuff to compute col 

    frag_col=col; 
    } 
//------------------------------------------------------------------ 
+1

Cosa fai con quel pixel_TBN nel tuo frammento shader? Come capisco tu trasformi tan, bin, né da Tangent Space nel tuo spazio scena globale. Per le matrici contenenti solo rotazioni, è possibile utilizzare trasporre per eseguire l'inversione. – fen

+0

hai appena modificato il semplice frammento parziale per te. Con il frammento normale puoi fare qualsiasi cosa (qualsiasi modello di illuminazione, aggiungendo riflessioni cromate da cubemap ...) – Spektre

+2

La trasposizione di un 3x3 ormonale è anche l'inverso. Forse è a questo che si riferisce il poster originale? – Tommy