2013-10-30 87 views
0

我正在使用Assimp导入3D模型,并为我提供正常贴图的切线和比特,但我无法弄清楚矩阵看起来像用于在顶点着色器中将切线和比特向量相乘 - 它是WorldViewProjection矩阵还是其他特殊用途的“常规矩阵”?NormalMatrix for OpenGL顶点着色器?

UPDATE:我的顶点着色器

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 \ 

回答

4

TBN(Tangent,Bitangent,Normal)矩阵(3x3)通常用于从切线空间到物体空间。你可以乘以你的法线来转换它们。请注意,法线本质上是方向性的,所以与通常处理的大多数变换矩阵不同,您只需要一个vec3和3x3矩阵来完成此操作;在我看来,这就是使这个矩阵“特殊”的原因。根据您使用此矩阵的方式,您可以将光矢量转换为切线空间,也可以将法线贴图转换为对象空间。

一般而言,您不会将Tangent,Bitangent和Normal矢量分别乘以。它们定义了您的向量空间基础,并应该单独放置。用于转换进出该向量空间的矩阵是从这三个向量中导出的。


您可以创建矩阵从切线空间转换做这个(伪代码)物空间:

mat3 (Tangent, Bitangent, Normal); 

当然你也可以使用逆从对象空间去切空间。 Assimp可能会生成(粗略)正交基向量,所以逆保证存在,并且在这种情况下可以表示为转置。

切线和二重是保证是正交然而,作为纹理sheering可以存在并且没有一个是一定垂直于法线任一。某些模型导入软件在输出TBN向量时执行正交处理作为后处理步骤,而大多数教程似乎都假定存在这种关系总是存在。

+0

虽然此片段着色器中使用此矩阵吗?我指的是顶点着色器中的一个,更新问题 – KaiserJohaan

+0

@KaiserJohaan:不一定。您可以在片段着色器中使用它来将采样的切线空间法线转换为对象空间,这在延迟着色中很常见。您还可以使用它将光照方向向量转换为顶点着色器中的切线空间 - 这在前向着色引擎中非常有用,因为它降低了片段着色器的复杂性。然而,在任何情况下,您都不需要转换每个顶点的法线,切线或比特。您可能会*改变TBN矩阵以使其切割空间来查看空间,然而(对象空间通常不是有用的) 。 –

+0

@KaiserJohaan:你能说清楚你在你的***片段着色器***中如何使用正切,平淡和正常的向量?我现在从您更新的问题中获得的印象是,您正在将采样的切线空间法线转换为不同的向量空间(本例中是世界空间)。 –

3

切线和bitangents(也称为副法线)遵循相同的规则作为法线。事实上,切线,副法线和法线构成了表面局部空间的基础,可以用3×3矩阵表示。该空间通过模型视图矩阵(也称为常规矩阵)的逆转置而被转换。

相关问题