我正在使用 Assimp 导入 3d 模型,它为我提供其法线贴图的切线和副切线,但是我无法弄清楚用于在顶点着色器中将切线和副切线 vector 相乘的矩阵是什么样的- 它是 WorldViewProjection 矩阵还是其他一些特殊用途的“普通矩阵”?
更新:我的顶点着色器
const std::string gVertexShader = "#version 330 \n \
\n \
layout(std140) uniform; \n \
\n \
uniform UnifTransform \n \
{ \n \
mat4 mWVPMatrix; \n \
mat4 mWorldMatrix; \n \
float mTextureTilingFactor; \n \
} Transform; \n \
\n \
layout(location = 0) in vec3 vert_position; \n \
layout(location = 1) in vec3 vert_normal; \n \
layout(location = 2) in vec2 vert_texcoord; \n \
layout(location = 3) in vec3 vert_tangent; \n \
layout(location = 4) in vec3 vert_bitangent; \n \
\n \
out vec3 frag_position; \n \
out vec3 frag_normal; \n \
out vec2 frag_texcoord; \n \
out vec3 frag_tangent; \n \
out vec3 frag_bitangent; \n \
\n \
void main() \n \
{ \n \
gl_Position = Transform.mWVPMatrix * vec4(vert_position, 1.0); \n \
\n \
vec4 position = Transform.mWorldMatrix * vec4(vert_position, 1.0); \n \
vec4 normal = Transform.mWorldMatrix * vec4(vert_normal, 0.0); \n \
vec4 tangent = Transform.mWorldMatrix * vec4(vert_tangent, 0.0); // correct matrix? \n \
vec4 bitangent = Transform.mWorldMatrix * vec4(vert_bitangent, 0.0); \n \
\n \
frag_position = position.xyz; \n \
frag_normal = normal.xyz; \n \
frag_tangent = tangent.xyz; \n \
frag_bitangent = bitangent.xyz; \n \
frag_texcoord = Transform.mTextureTilingFactor * vert_texcoord; \n \
最佳答案
TBN(切线、双切线、法线)矩阵 (3x3) 通常用于从切线空间到对象空间。你可以将你的法线乘以这个来改变它们。请注意,法线本质上是方向性的,因此与您通常处理的大多数变换矩阵不同,您只需要一个 vec3
和 3x3 矩阵即可;在我看来,这就是使这个特定矩阵“特别”的原因。根据您使用此矩阵的方式,您可以将光 vector 转换为切线空间,或将法线贴图转换为对象空间。
不过,通常您不会分别乘以切线、双切线和法线 vector 。他们定义了你的 vector 空间基础,应该单独留下。用于变换进出该 vector 空间的矩阵来自这三个 vector 。
通过执行此操作(伪代码),您将创建从切线空间转换到对象空间的矩阵:
mat3 (Tangent, Bitangent, Normal);
当然,您可以使用逆函数从对象空间转到切线空间。 Assimp 可能会生成(大致)正交基 vector ,因此保证逆存在并且在这种情况下可以表示为转置。
但是,切线和副切线不保证是正交的,因为可能存在纹理倾斜,而且两者都不一定垂直于法线。一些模型导入软件在输出 TBN vector 时执行正交化作为后处理步骤,大多数教程似乎都假设这种关系总是存在。
关于c++ - 用于 OpenGL 顶点着色器的 NormalMatrix?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19693575/