假设您有一个带有法线贴图的3D网格。网格还拥有切线,比特和法线。法线贴图并保持切线
从切线,比特切线和法线,您可以建立TBN矩阵,它是一个将切线空间转换为世界空间的矩阵。通过这种方式,来获得真正的正常你不得不做这样的事情:
mat3 TBN = mat3(tangent, bitangent, normal);
vec3 realNormal = TBN * normalFromTheNormalMap;
然而,如何从这个系统中真正切线和二重?
假设您有一个带有法线贴图的3D网格。网格还拥有切线,比特和法线。法线贴图并保持切线
从切线,比特切线和法线,您可以建立TBN矩阵,它是一个将切线空间转换为世界空间的矩阵。通过这种方式,来获得真正的正常你不得不做这样的事情:
mat3 TBN = mat3(tangent, bitangent, normal);
vec3 realNormal = TBN * normalFromTheNormalMap;
然而,如何从这个系统中真正切线和二重?
你必须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)
如果realNormal
被归一化的矢量(长度为1)和tangent
和binormal
是正交的,则realTangent
和所述realBinormal
可以计算这样的:
realTangent = normalize(tangent - realNormal * dot(tangent, realNormal));
realBinormal = binormal - realNormal * dot(binormal, realNormal);
realBinormal = normalize(realBinormal - realTangent * dot(realBinormal, realTangent));
如果tangent
和binormal
被归一化矢量太,则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);
你不需要在realTangent上投影binormal吗?因为在格雷厄姆施密特过程中,您需要为第n个向量投影(n-1)次 –
@AntoineMorrier好点。我扩大了答案。 – Rabbid76
最后一个问题,如果我计算切线前的bi法线,还是不一样,是不是一样? –
[Gram-Schmidt Orthonormalization](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)'t = normalize(tangent - realNormal * dot(tangent,realNormal));' – Rabbid76
很明显......谢谢 –