c – 法线贴图:与碎片着色器相比,顶点着色器中的TBN矩阵不同

c – 法线贴图:与碎片着色器相比,顶点着色器中的TBN矩阵不同,第1张

概述我正在研究教程的常规映射实现,为了教学目的,我想将TBN矩阵传递给片段着色器(来自顶点着色器),这样我就可以将切线空间中的法向量转换为世界空间用于照明计算.法线贴图应用于2D平面,其法线指向正z方向. 但是,当我在平面的顶点着色器中计算TBN矩阵时(因此所有顶点的所有切线/位数都相同),显示的法线完全关闭.如果我将切线/比特和法线向量传递给片段着色器并在那里构建TBN,它可以正常工作,如下图所示( 我正在研究教程的常规映射实现,为了教学目的,我想将TBN矩阵传递给片段着色器(来自顶点着色器),这样我就可以将切线空间中的法向量转换为世界空间用于照明计算.法线贴图应用于2D平面,其法线指向正z方向.

但是,当我在平面的顶点着色器中计算TBN矩阵时(因此所有顶点的所有切线/位数都相同),显示的法线完全关闭.如果我将切线/比特和法线向量传递给片段着色器并在那里构建TBN,它可以正常工作,如下图所示(显示法线):

这是它变得奇怪的地方.因为平面是平坦的,所以它的所有顶点的T,B和N矢量都是相同的,因此TBN矩阵对于每个片段也应该是相同的(因为片段插值不会改变任何东西).顶点着色器中的TBN矩阵应与片段着色器中的TBN矩阵完全相同,但视觉输出则另有说明.

顶点和片段着色器的源代码如下:

顶点:

#version 330 corelayout (location = 0) in vec3 position;layout (location = 1) in vec3 normal;layout (location = 2) in vec2 texCoords;layout (location = 3) in vec3 tangent;layout (location = 4) in vec3 bitangent;out VS_OUT {    vec3 FragPos;    vec3 normal;    vec2 TexCoords;    vec3 Tangent;    vec3 Bitangent;    mat3 TBN;} vs_out;uniform mat4 projection;uniform mat4 vIEw;uniform mat4 model;voID main(){    gl_position = projection * vIEw * model * vec4(position,1.0f);    vs_out.FragPos = vec3(model * vec4(position,1.0));       vs_out.TexCoords = texCoords;    mat3 normalMatrix = transpose(inverse(mat3(model)));    vs_out.normal = normalize(normalMatrix * normal);    vec3 T = normalize(normalMatrix * tangent);    vec3 B = normalize(normalMatrix * bitangent);    vec3 N = normalize(normalMatrix * normal);    vs_out.TBN = mat3(T,B,N);    vs_out.Tangent = T;    vs_out.Bitangent = B;}

分段

#version 330 coreout vec4 Fragcolor;in VS_OUT {    vec3 FragPos;    vec3 normal;    vec2 TexCoords;    vec3 Tangent;    vec3 Bitangent;    mat3 TBN;} fs_in;uniform sampler2D diffuseMap;uniform sampler2D normalMap;uniform vec3 lightPos;uniform vec3 vIEwPos;uniform bool normalMapPing;voID main(){               vec3 normal = fs_in.normal;    mat3 tbn;    if(normalMapPing)    {        // Obtain normal from normal map in range [0,1]        normal = texture(normalMap,fs_in.TexCoords).rgb;        // transform normal vector to range [-1,1]        normal = normalize(normal * 2.0 - 1.0);           // Then transform normal in tangent space to world-space via TBN matrix        tbn = mat3(fs_in.Tangent,fs_in.Bitangent,fs_in.normal); // TBN calculated in fragment shader        // normal = normalize(tbn * normal); // This works!        normal = normalize(fs_in.TBN * normal); // This gives incorrect results    }    // Get diffuse color    vec3 color = texture(diffuseMap,fs_in.TexCoords).rgb;    // AmbIEnt    vec3 ambIEnt = 0.1 * color;    // Diffuse    vec3 lightDir = normalize(lightPos - fs_in.FragPos);    float diff = max(dot(lightDir,normal),0.0);    vec3 diffuse = diff * color;    // specular    vec3 vIEwDir = normalize(vIEwPos - fs_in.FragPos);    vec3 reflectDir = reflect(-lightDir,normal);    vec3 halfwayDir = normalize(lightDir + vIEwDir);      float spec = pow(max(dot(normal,halfwayDir),0.0),32.0);    vec3 specular = vec3(0.2) * spec; // assuming bright white light color    Fragcolor = vec4(ambIEnt + diffuse + specular,1.0f);    Fragcolor = vec4(normal,1.0); // display normals for deBUGging}

两个TBN矩阵都明显不同.下面我编译了不同片段着色器输出的图像:

您可以看到T,B和N向量是正确的,片段着色器的tbn矩阵也是正确的,但顶点着色器fs_in.TBN中的TBN矩阵给出了完全虚假的值.

我完全不知道为什么它不起作用.我知道我可以简单地将Tangent和Bitangent向量传递给片段着色器,在那里计算它并完成它但我很好奇为什么这不起作用的确切原因?

解决方法 一些一般性评论:

1)您应该在片段着色器中规范化fs_in.Tangent,fs_in.Bitangent和fs_in.normal,因为不能保证它们在变化插值之后.它们应该被标准化,因为它们是坐标系的基础向量.

2)您不需要通过所有三个,切线,比特和正常,因为其中一个可以使用叉积计算:bitangent = cross(正切,正常).这一点也支持传递(两个)向量而不是整个矩阵.

对于您的问题,为什么fs_in.TBN在片段着色器中看起来不像tbn:

确实,你提供的图像看起来很奇怪.看起来矩阵的矢量以某种方式混淆了.你得到哪个输出,显示转置矩阵转置(fs_in.TBN)?

还要确保正确访问矩阵的列,如[1]中所述! (它看起来像是,但请仔细检查,你永远不会知道.)

[1] Geeks3D; GLSL 4×4矩阵场; http://www.geeks3d.com/20141114/glsl-4×4-matrix-mat4-fields/

总结

以上是内存溢出为你收集整理的c – 法线贴图:与碎片着色器相比,顶点着色器中的TBN矩阵不同全部内容,希望文章能够帮你解决c – 法线贴图:与碎片着色器相比,顶点着色器中的TBN矩阵不同所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1227658.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存