2009-08-29 9 views
2

GLSLシェーダで通常のマッピングを使用するには、各頂点の法線ベクトル、接線ベクトル、およびビット角ベクトルを知る必要があります。 RenderMonkeyは、このために事前に定義された変数(rm_tangentrm_binormal)を提供することで、これを簡単にします。私は自分の3Dエンジンにこの機能を追加しようとしています。各頂点のxyz座標、uvテクスチャ座標、法線ベクトルを使用して、三角形内の各頂点の正接と双対接線を計算することは明らかです。いくつかの検索の後、私はこの関数を考案して、三角形構造の各頂点の正接と正の値を計算しました。私はこの機能を使用して、私のシェーダに計算値を送信すると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); 
} 

、モデルがRenderMonkeyに彼らがほとんどのように見えるが、彼らは非常に奇妙な方法でちらつきます。私は問題を接線と正反対に辿り、OpenGLを送信しています。これは私のコードが何か間違ったことをしていると思わせる。誰でも問題を見ることができますか、試してみるための他の方法の提案はありますか?

私はまた、上記のコードは非常にハッキーであり、何が起こっているのかを理解していないことを指摘しておきます。

答えて

4

は解決策を見つけました。ずっとシンプルな(しかしまだ少しハッキーな)コード:

void CalculateTangentSpace(void) { 
    float x1 = m_vertices[1]->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 z1 = m_vertices[1]->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); 

    Vec3<float> tangent(x1/u1, y1/u1, z1/u1); 
    tangent = tangent.Normalize(); 

    m_vertices[0]->m_tangent = new Vec3<float>(tangent); 
    m_vertices[1]->m_tangent = new Vec3<float>(tangent); 
    m_vertices[2]->m_tangent = new Vec3<float>(tangent); 

    m_vertices[0]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[0]->m_normal, m_vertices[0]->m_tangent)->Normalize()); 
    m_vertices[1]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[1]->m_normal, m_vertices[1]->m_tangent)->Normalize()); 
    m_vertices[2]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[2]->m_normal, m_vertices[2]->m_tangent)->Normalize()); 
} 
+2

申し訳ありませんが、それは間違っています。あなたは、単にエッジv01を1/u1だけスケールするだけです。 u1はゼロになるだけでなく、明らかに正しくありません。正解については、http://stackoverflow.com/questions/5255806/how-to-calculate-tangent-and-binormalを参照してください。 – Gottfried

0

u1、u2、v1、およびv2の特定の値について、 'r'計算でゼロ除算が行われ、 'r'の動作が不明になります。あなたはこれを守るべきです。分母がゼロで、あなたの問題を解決するかもしれないなら、 'r'は何であるべきかを解き明かしてください。私もこの背後にある数学をほとんど理解していません。分母がゼロの場合、R = 0を設定実装推奨

#include <cmath> 
... 
static float PRECISION = 0.000001f; 
... 
float denominator = (u1 * v2 - u2 * v1); 
float r = 0.f; 
if(fabs(denominator) > PRECISION) {  
    r = 1.0f/denominator; 
} 
... 
+0

返信ありがとうございます。残念ながらあなたの提案は役に立たない。 –

関連する問題