法线映射问题[关闭]

Posted

技术标签:

【中文标题】法线映射问题[关闭]【英文标题】:Normal Mapping Issues [closed] 【发布时间】:2020-06-14 15:58:02 【问题描述】:

我第一次尝试在我的 glsl 着色器中实现法线映射。我编写了一个计算切线和双切线的 ObjLoader - 然后我将相关信息传递给我的着色器(稍后我将显示代码)。然而,当我运行程序时,我的模型最终看起来像这样:

看起来很棒,我知道,但不是我想要实现的目标! 我知道我应该简单地计算方向向量而不移动顶点 - 但似乎在某个地方我最终犯了那个错误。

我不确定我在读取 .obj 文件并计算切线/双切线向量时是否犯了错误,或者错误是否发生在我的顶点/片段着色器中。

现在是我的代码:

在我的 ObjLoader 中——当我遇到一张脸时,我会计算脸的所有三个顶点的 deltaPositions 和 deltaUv 向量——然后计算切线和双切线向量:

然后我组织收集到的顶点数据来构建我的索引列表 - 在这个过程中,我重新构建切线和双切线向量以尊重新构建的索引列表。

最后 - 我执行正交化并计算最终的双切线向量。

绑定VAO、VBO、IBO,并分别传递所有信息后——我的shader计算如下:

顶点着色器:

void main()

    // Output position of the vertex, in clip space
    gl_Position = MVP * vec4(pos, 1.0);

    // Position of the vertex, in world space 
    v_Position = (M * vec4(pos, 0.0)).xyz;

    vec4 bitan = V * M * vec4(bitangent, 0.0);
    vec4 tang = V * M * vec4(tangent, 0.0);
    vec4 norm = vec4(normal, 0.0);

    mat3 TBN = transpose(mat3(tang.xyz, bitan.xyz, norm.xyz));

    // Vector that goes from the vertex to the camera, in camera space
    vec3 vPos_cameraspace = (V * M * vec4(pos, 1.0)).xyz;
    camdir_cameraspace = normalize(-vPos_cameraspace);

    // Vector that goes from the vertex to the light, in camera space
    vec3 lighPos_cameraspace = (V * vec4(lightPos_worldspace, 0.0)).xyz;
    lightdir_cameraspace = normalize((lighPos_cameraspace - vPos_cameraspace));

    v_TexCoord = texcoord;

    lightdir_tangentspace = TBN * lightdir_cameraspace;
    camdir_tangentspace = TBN * camdir_cameraspace;

片段着色器:

void main()

    // Light Emission Properties
    vec3 LightColor = (CalcDirectionalLight()).xyz;
    float LightPower = 20.0;

    // Cutting out texture 'black' areas of texture
    vec4 tempcolor = texture(AlbedoTexture, v_TexCoord);
    if (tempcolor.a < 0.5)
        discard;

    // Material Properties
    vec3 MaterialDiffuseColor = tempcolor.rgb;
    vec3 MaterialAmbientColor = material.ambient * MaterialDiffuseColor;
    vec3 MaterialSpecularColor = vec3(0, 0, 0);

    // Local normal, in tangent space
    vec3 TextureNormal_tangentspace = normalize(texture(NormalTexture, v_TexCoord)).rgb;
    TextureNormal_tangentspace = (TextureNormal_tangentspace * 2.0) - 1.0;

    // Distance to the light
    float distance = length(lightPos_worldspace - v_Position);

    // Normal of computed fragment, in camera space
    vec3 n = TextureNormal_tangentspace;

    // Direction of light (from the fragment)
    vec3 l = normalize(TextureNormal_tangentspace);

    // Find angle between normal and light
    float cosTheta = clamp(dot(n, l), 0, 1);

    // Eye Vector (towards the camera)
    vec3 E = normalize(camdir_tangentspace);

    // Direction in which the triangle reflects the light
    vec3 R = reflect(-l, n);

    // Find angle between eye vector and reflect vector
    float cosAlpha = clamp(dot(E, R), 0, 1);

    color = 
            MaterialAmbientColor + 
            MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance * distance) +
            MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha, 5) / (distance * distance);

【问题讨论】:

【参考方案1】:

我可以在您的代码中发现 1 个明显的错误。 TBNbitangenttangentnormal 生成。虽然bitangenttangent 从模型空间转换到视图空间,但normal 没有转换。这没有任何意义。所有 3 个向量必须与同一坐标系相关:

vec4 bitan = V * M * vec4(bitangent, 0.0);
vec4 tang  = V * M * vec4(tangent, 0.0);
vec4 norm  = V * M * vec4(normal, 0.0);

mat3 TBN = transpose(mat3(tang.xyz, bitan.xyz, norm.xyz));

【讨论】:

感谢您的回复。通过这种调整,以及将我的切线/双切线向量分组到我的顶点结构中而不是它们自己的数组中,似乎解决了这个问题!感谢您的帮助!

以上是关于法线映射问题[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的法线不会在顶点之间插值,从而产生平坦的阴影效果?

opengl vbo建议[关闭]

性能差异一维数组映射方式问题 [关闭]

Linux中的mmap文件支持映射与匿名映射[关闭]

映射函数效率低吗? [关闭]

C ++模板堆栈映射/多映射[关闭]