2013-03-10 12 views
6

Chcę po prostu mieć pewność, rozumiem obliczenie macierzy TBN poprawnienormalne mapowanie, obliczanie macierzy TBN

W vertex shader zazwyczaj używamy:

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); 

Jak rozumiem to tbn matryca przekształca wektor od Tangent space do Eye space. Właściwie chcemy odwrócić - przekształcić wektor z przestrzeni oczu na przestrzeń styczną. Zatem musimy odwrócić macierz tbn:

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

uwaga:tbn - powinna zawierać tylko obroty, za takim przypadku możemy użyć, aby odwrócić transpozycję macierzy.

I możemy przekształcić nasze wektory:

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

w kilku tutoriali, kody źródłowe Odkryłam, że autorzy zastosowali coś takiego:

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

Powyższy kod działa tak samo jak pomnożenie przez macierz transposed(tbn).

Pytanie:

powinniśmy wykorzystać macierz transponowana tbn tak jak wyjaśniono powyżej? A może czegoś brakuje?

Uwaga przez tego rozwiązania mamy wektory (light_vector) przekształcić w TBN w vertex shader, potem fragment shader mamy tylko dostać normalny od normalnej mapie. Inną opcją jest utworzenie macierzy TBN, która przekształca się z przestrzeni TBN w przestrzeń oka, a następnie w module cieniującym przekształca każdy odczyt normalny z normalnej mapy.

+0

Zdefiniuj „prawidłowego "? Wziąłeś krzyżówkę swoich normalnych i stycznych wektorów, aby uzyskać wektor bitangencki. Jest to, ogólnie rzecz biorąc, * nie * prawidłowe dla większości powierzchni. Może to być poprawne dla Ciebie, ale większość mapowania tekstur nie używa idealnie odwzorowań ortogonalnych na powierzchni. –

+0

Dobrze, zaktualizowałem pytanie. Zmieniłem także obliczenia bitangenckie. – fen

Odpowiedz

0

transpozycja nie jest odwróceniem macierzy !!!

moje macierze TBN w vertex shader wyglądać następująco:

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); 
    //... 
} 

gdzie:

  • tm_l2g_dir jest macierz transformacji z lokalnego obszaru modelu do globalnej przestrzeni sceny whitout jakiegokolwiek ruchu (zmiany tylko kierunkowskazy) dla Twój kod jest normalne matryca
  • tan, bin, ani nie są wektory do TBN matrycy (jako część moich modelach)

ani - jest wektor normalny do powierzchni od rzeczywistej pozycji wierzchołka (jako wektor można obliczyć mnożenia dwóch wierzchołków z tego wierzchołka)

tan, kosz prostopadłe wektory zwykle tekstura osiach równoległych do mapowania lub teselation modelu. Jeśli wybierzesz niewłaściwe wektory tan/bin niż czasami mogą wystąpić artefakty świetlne.Na przykład, jeśli ma cylinder niż pojemnik jest jego osi obrotu i tan jest prostopadła do niej wzdłuż okręgu (styczna)

tan pojemnika, ani nie powinno być prostopadłe do siebie

można obliczyć TBN również automatycznie, ale to spowoduje pewne artefakty. zrobić to po prostu wybrał jako tan wektor jeden vértice używany do normalnego obliczeń i bin = ani x bin

w fragment shader używam pixel_TBN z normalnej mapie, aby obliczyć rzeczywisty normalne dla fragmentu

//------------------------------------------------------------------ 
#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

co robisz z tym pikselem_TBN w shadererze fragmentów? Jak rozumiem, zmieniasz tan, bin, lub z Tangent Space w swoją globalną przestrzeń sceny. W przypadku macierzy zawierających tylko rotacje można użyć transpozycji, aby wykonać inwersję. – fen

+0

właśnie dokonaliśmy edycji prostego fragmentu części dla ciebie. Z każdym fragmentem normalnym możesz zrobić wszystko (dowolny model oświetlenia, dodając odbicie chromu z mapy cubemap ...). – Spektre

+2

Transpozycja orthormal 3x3 jest również odwrotna. Może o to chodzi w oryginalnym plakacie? – Tommy