Pour utiliser le mappage normal dans les shaders GLSL, vous devez connaître les vecteurs normal, tangent et bitangent de chaque sommet. RenderMonkey rend cela facile en fournissant ses propres variables prédéfinies (rm_tangent
et rm_binormal
) pour cela. J'essaye d'ajouter cette fonctionnalité à mon propre moteur 3d. Apparemment, il est possible de calculer la tangente et la tangente bi de chaque sommet dans un triangle en utilisant les coordonnées xyz de chaque sommet, les coordonnées de texture uv et le vecteur normal. Après quelques recherches, j'ai conçu cette fonction pour calculer la tangente et le bitangent pour chaque sommet de ma structure triangulaire.Calcul de l'espace tangent 3D
void CalculateTangentSpace(void) {
float x1 = m_vertices[1]->m_pos->Get(0) - m_vertices[0]->m_pos->Get(0);
float x2 = m_vertices[2]->m_pos->Get(0) - m_vertices[0]->m_pos->Get(0);
float y1 = m_vertices[1]->m_pos->Get(1) - m_vertices[0]->m_pos->Get(1);
float y2 = m_vertices[2]->m_pos->Get(1) - m_vertices[0]->m_pos->Get(1);
float z1 = m_vertices[1]->m_pos->Get(2) - m_vertices[0]->m_pos->Get(2);
float z2 = m_vertices[2]->m_pos->Get(2) - m_vertices[0]->m_pos->Get(2);
float u1 = m_vertices[1]->m_texCoords->Get(0) - m_vertices[0]->m_texCoords->Get(0);
float u2 = m_vertices[2]->m_texCoords->Get(0) - m_vertices[0]->m_texCoords->Get(0);
float v1 = m_vertices[1]->m_texCoords->Get(1) - m_vertices[0]->m_texCoords->Get(1);
float v2 = m_vertices[2]->m_texCoords->Get(1) - m_vertices[0]->m_texCoords->Get(1);
float r = 1.0f/(u1 * v2 - u2 * v1);
Vec3<float> udir((v2 * x1 - v1 * x2) * r, (v2 * y1 - v1 * y2) * r, (v2 * z1 - v1 * z2) * r);
Vec3<float> vdir((u1 * x2 - u2 * x1) * r, (u1 * y2 - u2 * y1) * r, (u1 * z2 - u2 * z1) * r);
Vec3<float> tangent[3];
Vec3<float> tempNormal;
tempNormal = *m_vertices[0]->m_normal;
tangent[0]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[0]->m_tangent=&(tangent[0].Normalize());
m_vertices[0]->m_bitangent=Vec3Cross(m_vertices[0]->m_normal, m_vertices[0]->m_tangent);
tempNormal = *m_vertices[1]->m_normal;
tangent[1]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[1]->m_tangent=&(tangent[1].Normalize());
m_vertices[1]->m_bitangent=Vec3Cross(m_vertices[1]->m_normal, m_vertices[1]->m_tangent);
tempNormal = *m_vertices[2]->m_normal;
tangent[2]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[2]->m_tangent=&(tangent[2].Normalize());
m_vertices[2]->m_bitangent=Vec3Cross(m_vertices[2]->m_normal, m_vertices[2]->m_tangent);
}
Lorsque j'utilise cette fonction et envoie les valeurs calculées à mon shaders, les modèles ressemblent presque comme ils le font dans RenderMonkey mais ils flicker dans une manière très étrange. J'ai tracé le problème à la tangente et au bitangent que j'envoie OpenGL. Cela m'amène à penser que mon code fait quelque chose de mal. Quelqu'un peut-il voir des problèmes ou avoir des suggestions pour d'autres méthodes à essayer?
Je devrais également souligner que le code ci-dessus est très hacky et j'ai très peu de compréhension des mathématiques derrière ce qui se passe.
Désolé, mais c'est faux. Ce que vous faites est simplement l'échelle du bord v01 par 1/u1. Non seulement U1 pourrait être zéro, mais ce n'est évidemment pas correct. Pour une réponse correcte, consultez http://stackoverflow.com/questions/5255806/how-to-calculate-tangent-and-binormal – Gottfried