c++ - 用于 OpenGL 顶点着色器的 NormalMatrix?

标签 c++ opengl opengl-3

我正在使用 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/

相关文章:

c++ 缺少一些输出结果

c++拆分一个字符串

c++ - 取消设置 glXMakeContextCurrent 时进程崩溃

c++ - glGetActiveUniformName 的异常行为

c++ - 将 VAO 与 glDrawElements 结合使用

c++ - 带有片段着色器的 OpenGL 3.3 不同颜色

c++ - 具有外部链接的编译器的不同行为

c++ - 重载时 friend 的替代>>?

opengl - SDL 坐标系,从 (0,0) 到 (w,h) 或 (w-1, h-1)?

c++ - GL_SHADER_STORAGE_BUFFER 内存限制