2017-09-19 49 views
2

假设您有一个带有法线贴图的3D网格。网格还拥有切线,比特和法线。法线贴图并保持切线

从切线,比特切线和法线,您可以建立TBN矩阵,它是一个将切线空间转换为世界空间的矩阵。通过这种方式,来获得真正的正常你不得不做这样的事情:

mat3 TBN = mat3(tangent, bitangent, normal); 
vec3 realNormal = TBN * normalFromTheNormalMap; 

然而,如何从这个系统中真正切线和二重?

+2

[Gram-Schmidt Orthonormalization](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)'t = normalize(tangent - realNormal * dot(tangent,realNormal));' – Rabbid76

+0

很明显......谢谢 –

回答

2

你必须Orthogonalize的载体。 Orthogonalization的常用方法是Gram–Schmidt Orthonormalization

本算法使用的情况的是,2个向量的乘积等于2个矢量乘以两矢量的大小(lenght)之间的角度的余弦

dot(N, T) == length(N) * length(T) * cos(angle_N_T) 

在此之前,该第2个单位矢量(归一化的向量)的乘积等于2个向量之间的角度的余弦,因为单位向量的长度为1。

uN = normalize(A) 
uT = normalize(B) 
cos(angle_T_N) == dot(uT, uN) 

enter image description here

如果realNormal被归一化的矢量(长度为1)和tangentbinormal是正交的,则realTangent和所述realBinormal可以计算这样的:

realTangent = normalize(tangent - realNormal * dot(tangent, realNormal)); 
realBinormal = binormal - realNormal * dot(binormal, realNormal); 
realBinormal = normalize(realBinormal - realTangent * dot(realBinormal, realTangent)); 

如果tangentbinormal被归一化矢量太,则normalize函数可通过与所述源向量的点积除以取代和真正载体:

realTangent = tangent - realNormal * dot(tangent, realNormal); 
realTangent /= dot(tangent, realTangent); 
realBinormal = binormal - realNormal * dot(binormal, realNormal); 
realBinormal = realBinormal - realTangent * dot(realBinormal, realTangent); 
realBinormal /= dot(binormal, realBinormal); 

见进一步How to calculate Tangent and Binormal?

+0

你不需要在realTangent上投影binormal吗?因为在格雷厄姆施密特过程中,您需要为第n个向量投影(n-1)次 –

+0

@AntoineMorrier好点。我扩大了答案。 – Rabbid76

+0

最后一个问题,如果我计算切线前的bi法线,还是不一样,是不是一样? –