49 votes

Comment calculer Tangent et Binormal?

Parler de "bump", reflet spéculaire et ce genre de choses en OpenGL Shading Language (GLSL)

J'ai:

  • Un tableau de sommets (par ex. {0.2,0.5,0.1, 0.2,0.4,0.5, ...})
  • Un tableau de normales (par ex. {0.0,0.0,1.0, 0.0,1.0,0.0, ...})
  • La position d'un point de lumière dans l'espace (par exemple, {0.0,1.0,-5.0})
  • La position de l'observateur dans l'espace (par exemple, {0.0,0.0,0.0}) (suppose que le spectateur est au centre du monde)

Maintenant, comment puis-je calculer la Binormale et Tangente pour chaque sommet? Je veux dire, quelle est la formule pour calculer la Binormals, ce que j'ai à utiliser en se basant sur ces informations? Et à propos de la tangente?

Je vais construire l'ALCALINITÉ de la Matrice de toute façon, donc si vous connaissez une formule pour construire la matrice directement sur la base de ces informations va être sympa!

Oh, yeh, j'ai les coordonnées de texture trop, si nécessaire. Et comme je parle GLSL, serait bien une per-vertex solution, je veux dire, celui qui n'a pas besoin d'avoir accès à plus d'un sommet de l'information à la fois.

---- Mise à jour -----

J'ai trouvé cette solution:

vec3 tangente;
vec3 binormale;

vec3 c1 = cross(a_normal, vec3(0.0, 0.0, 1.0));
vec3 c2 = cross(a_normal, vec3(0.0, 1.0, 0.0));

si (longueur(c1)>longueur(c2))
{
 tangente = c1;
}
d'autre
{
 tangente = c2;
}

tangente = normalize(tangente);

la binormale = cross(v_nglNormal, tangente);
la binormale = normalize(binormale);

Mais je ne sais pas si c'est correct à 100%.

38voto

datenwolf Points 85093

Pertinentes des données d'entrée à votre problème sont les coordonnées de texture. La tangente et la Binormale sont des vecteurs localement parallèle à la surface de l'objet. Et dans le cas de normal mapping ils les décrivent les locaux de l'orientation de la normale à la texture.

Donc, ce que vous avez à faire est de calculer la direction (dans le modèle de l'espace), la texture des vecteurs point. Disons que vous avez un triangle ABC, avec des coordonnées de texture HKL. Cela nous donne les vecteurs:

D = B-A
E = C-A

F = K-H
G = L-H

Maintenant, nous voulons exprimer D et E en termes de l'espace tangent T, U, i.e.

D = F.s * T + F.t * U
E = G.s * T + G.t * U

C'est un système linéaire d'équations à 6 inconnues et 6 équations, il peut être écrite comme

| D.x D.y D.z |   | F.s F.t | | T.x T.y T.z |
|             | = |         | |             |
| E.x E.y E.z |   | G.s G.t | | U.x U.y U.z |

En inversant le FG de la matrice des rendements

| T.x T.y T.z |           1         |  G.t  -F.t | | D.x D.y D.z |
|             | = ----------------- |            | |             |
| U.x U.y U.z |   F.s G.t - F.t G.s | -G.s   F.s | | E.x E.y E.z |

Avec le vertex normal de T et de U forment un espace local de base, appelé l'espace tangent, décrit par la matrice

| T.x U.x N.x |
| T.y U.y N.y |
| T.z U.z N.z |

la transformation de l'espace tangent en un objet de l'espace. Pour faire des calculs d'illumination on a besoin de l'inverse de cela. Avec un peu d'exercice, on trouve:

T' = T - (N·T) N
U' = U - (N·U) N - (T'·U) T'

normaliser les vecteurs T et U", les qualifiant de la tangente et la binormale, nous obtenons la matrice de transformation de l'objet dans l'espace tangente, où nous faisons l'éclairage:

| T'.x T'.y T'.z |
| U'.x U'.y U'.z |
| N.x  N.y  N.z  |

nous stockons T' et U' avec le vertex normal qu'une partie de la géométrie du modèle (comme le sommet d'attributs), de sorte que nous pouvons les utiliser dans le shader pour les calculs d'illumination. Je le répète: Vous n'avez pas de déterminer la tangente et la binormale dans le shader, vous précalculer et les stocker dans le cadre de la géométrie du modèle (tout comme les normales).

23voto

kvark Points 3427

Généralement, vous avez 2 façons de produire de l'ALCALINITÉ de la matrice: en ligne et hors ligne.

  • Sur-ligne = droit dans le fragment shader à l'aide de dérivés instructions. Ces dérivations de vous donner un plat d'ALCALINITÉ de base pour chaque point d'un polygone. Afin d'obtenir un bon un, nous avons re-orthogonalize elle s'appuie sur une donnée (lisse) vertex normal. Cette procédure est encore plus lourd sur GPU que l'ALCALINITÉ de l'extraction.

    // compute derivations of the world position
    vec3 p_dx = dFdx(pw_i);
    vec3 p_dy = dFdy(pw_i);
    // compute derivations of the texture coordinate
    vec2 tc_dx = dFdx(tc_i);
    vec2 tc_dy = dFdy(tc_i);
    // compute initial tangent and bi-tangent
    vec3 t = normalize( tc_dy.y * p_dx - tc_dx.y * p_dy );
    vec3 b = normalize( tc_dy.x * p_dx - tc_dx.x * p_dy ); // sign inversion
    // get new tangent from a given mesh normal
    vec3 n = normalize(n_obj_i);
    vec3 x = cross(n, t);
    t = cross(x, n);
    t = normalize(t);
    // get updated bi-tangent
    x = cross(b, n);
    b = cross(n, x);
    b = normalize(b);
    mat3 tbn = mat3(t, b, n);
    
  • Hors ligne = préparer la tangente comme un sommet de l'attribut. C'est plus difficile à obtenir, car il ne sera pas seulement ajouter un autre vertex attrib mais aussi besoin de re-composer tous les autres attributs. En outre, il ne sera pas à 100% de vous donner un meilleur rendement que vous obtiendrez un coût supplémentaire de stockage/transfert/animation(!) vector3 sommet de l'attribut.

Le calcul est décrite dans de nombreux endroits (google), y compris l' @datenwolf post.

Le problème ici est que 2 sommets peuvent avoir le même normal et coordonnées de texture, mais différentes tangentes. Cela signifie que vous ne pouvez pas ajouter un sommet de l'attribut à un sommet, vous aurez besoin de diviser le vertex 2 et spécifier différentes tangentes pour les clones.

La meilleure façon d'obtenir unique tangente (et d'autres attribs) par sommet est de le faire le plus tôt possible = à l'exportateur. Là, sur la scène de tri pur des sommets par les attributs que vous aurez juste besoin d'ajouter le vecteur tangent à la clé de tri.

Comme une solution radicale au problème envisager d'utiliser les quaternions. Un seul quaternion (vec4) peut représenter de tangentielle de l'espace de maniabilité. Il est facile de garder repère orthonormé (y compris passage pour le fragment shader), de stocker et d'extraire des normales si nécessaire. Plus d'infos sur le KRI wiki.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X