我使用四元数将网格的法线向量旋转到法线贴图向量的方向。我以为我可以使用Quaternion。所以我用网格法线和(0,0,1)之间的角度创建一个四元数。缩短了libgdx中的方法,Quaternion的创建看起来像这样
vec4 createQuaternion(vec3 normal) {
float l_ang = acos(clamp(normal.z, -CONST_ONE, CONST_ONE))/CONST_TWO;
float l_sin = sin(l_ang);
return normalize(vec4(-normal.y * l_sin, normal.x * l_sin, CONST_ZERO, cos(l_ang)));
}
使用此四元数我可以在法线贴图的方向上旋转网格的法线。因此我使用了我在libgdx Quaternion中看到的方法(而v是法线贴图的法线,m是四元数):
vec3 rotateNormal(vec3 v, vec4 m) {
vec4 tmp1 = vec4(v,CONST_ZERO);
vec4 tmp2 = vec4(m);
// conjugate
tmp2.x = -tmp2.x;
tmp2.y = -tmp2.y;
tmp2.z = -tmp2.z;
tmp2 = mulLeft(tmp1, tmp2);
tmp1 = mulLeft(m, tmp2);
v.x = tmp1.x;
v.y = tmp1.y;
v.z = tmp1.z;
return v;
}
mulLeft方法看起来像这样:
vec4 mulLeft(vec4 q, vec4 a) {
float newX = q.w * a.x + q.x * a.w + q.y * a.z - q.z * a.y;
float newY = q.w * a.y + q.y * a.w + q.z * a.x - q.x * a.z;
float newZ = q.w * a.z + q.z * a.w + q.x * a.y - q.y * a.x;
float newW = q.w * a.w - q.x * a.x - q.y * a.y - q.z * a.z;
a.x = newX;
a.y = newY;
a.z = newZ;
a.w = newW;
return a;
}
对于在着色器中的使用,我只需要调用:
normal = rotateNormal(normalMap, createQuaternion(normalMesh));
和按预期工作。
我唯一考虑的是,我可以想象有一种更短的方式来写它。特别是mulLeft方法。有吗?
您如何看待整个方法,通过四元数而不是使用NTB来转换矢量? 在动画网格时,ntb看起来有点像计算。
编辑: 这是我的源代码
的测试
这是Tenfour建议的测试
EDIT2:
我把整件事缩短为:
vec3 rotateNormal(vec3 normalMap, vec3 normal) {
// create quaternion from cross(normal, vec3(0,0,1))
float l_ang = acos(clamp(normal.z, -CONST_ONE, CONST_ONE))/CONST_TWO;
float l_sin = sin(l_ang);
vec4 quat = normalize(vec4(-normal.y * l_sin, normal.x * l_sin, CONST_ZERO, cos(l_ang)));
// shortened function to double mulQuat the normalMap on the quaternion
return vec3(
quat.x*quat.x*normalMap.x - quat.y*quat.y*normalMap.x - quat.z*quat.z*normalMap.x + quat.w*quat.w*normalMap.x - CONST_TWO*quat.z*quat.w*normalMap.y + CONST_TWO*quat.y*quat.w*normalMap.z + CONST_TWO*quat.x *(quat.y*normalMap.y + quat.z*normalMap.z),
-(quat.x*quat.x*normalMap.y) - quat.z*quat.z* normalMap.y + (quat.y*quat.y + quat.w*quat.w ) * normalMap.y + CONST_TWO*quat.z *(quat.w*normalMap.x + quat.y*normalMap.z) + CONST_TWO*quat.x* (quat.y*normalMap.x - quat.w*normalMap.z),
quat.y*(-CONST_TWO*quat.w*normalMap.x + CONST_TWO*quat.z*normalMap.y) + CONST_TWO*quat.x*(quat.z*normalMap.x + quat.w*normalMap.y) - quat.x*quat.x*normalMap.z - quat.y*quat.y*normalMap.z + (quat.z*quat.z + quat.w*quat.w )* normalMap.z
);
}
输入是法线贴图的法线和网格的法线。 我相信还有比这更好的东西。那可能是什么?
答案 0 :(得分:0)
我发现了这个
vec3 rotate_vector( vec4 quat, vec3 vec )
{
return vec + 2.0 * cross( cross( vec, quat.xyz ) + quat.w * vec, quat.xyz );
}
here。那样有用吗?不确定底层数学有多少,但内置的GLSL函数通常可以利用GPU优化。