繁体   English   中英

具有错误的镜面反射分量的法线贴图和phong着色

[英]Normal mapping and phong shading with incorrect specular component

我正在世界空间坐标中实施法线/凹凸贴图(我发现它们更易于使用),并且在没有法线贴图的情况下我的照明效果很好,但是当引入法线贴图(以及使用TBN矩阵计算的新矢量)时,我的灯不亮了。

镜面反射组件不在相机和灯光之间,应该是错误的。 但是,查看我的代码,我找不到任何问题。 切线和切线来自ASSIMP对象加载器,并且eyePos和lightPos也在世界坐标中。

由于光照在镜面反射部分看起来正确(显示了凹凸贴图),因此我认为它与切线空间变换有关吗?

这是说明问题的图片:

凹凸贴图具有错误的镜面反射分量

顶点着色器:

#version 330
layout (location = 0) in vec4 vertex;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec3 tangent;
layout(location = 3) in vec3 bitangent;
layout(location = 5) in vec2 texCoord;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec3 lightPos; 
uniform vec3 eyePos;

out vec3 Position;
out vec2 TexCoord;

out vec3 tangentLightDir;
out vec3 tangentViewDir;

void main()
{
    gl_Position = projection * view * model * vertex;
    // Position
    Position = vec3(model * vertex);
    // Normal
    mat3 normalMat = transpose(inverse(mat3(model)));
    Normal = normalize(normalMat * normal);
    // Texture
    TexCoord = texCoord;

    // Normal mapping
    mat3 TBN = mat3(tangent, bitangent, Normal);
    TBN = transpose(TBN);
    // Get direction vectors:
    vec3 lightDir = normalize(lightPos - Position);
    vec3 viewDir = normalize(eyePos - Position); 
    // Now transform them to tangent space
    tangentLightDir = TBN * lightDir;
    tangentViewDir = TBN * viewDir;
}

片段着色器:

#version 330
in vec3 Position;
in vec2 TexCoord;

in vec3 tangentLightDir;
in vec3 tangentViewDir;

uniform sampler2D texture0;
uniform sampler2D texture_normal;

out vec4 outColor;

void main()
{
    // defaults
    vec4 ambient = vec4(0.1);
    vec4 diffuse = vec4(0.4);
    vec4 specular = vec4(0.5);
    vec4 texColor = texture(texture0, TexCoord);    

    // Phong shading
    vec3 LightDir = normalize(tangentLightDir);
    vec3 Norm = normalize(texture(texture_normal, TexCoord).xyz * 2.0 - 1.0);    

    vec3 ViewDir = normalize(tangentViewDir); 
    vec3 ReflectDir = reflect(-LightDir,Norm);
    float specularContribution = pow(max(dot(ViewDir, ReflectDir), 0.0), 32);
    // Calculate diffuse component
    vec4 I = diffuse * max(dot(LightDir, Norm), 0.0);
    diffuse = clamp(I, 0.0, 1.0);
    // Calculate specular component
    specular = specular * specularContribution;

    outColor = texColor * (diffuse + specular + ambient);
}
layout(location = 3) in vec3 bitangent;
layout(location = 5) in vec2 texCoord;

5是正确的位置吗?

关于TBN矩阵。 您必须(怎么说jhoffman0x )将normalMat矩阵乘以切线bitangent ,对结果进行规格化,然后制成TBN矩阵:

David Wolff的示例-OpenGL 4.0着色语言食谱 顶点着色器:

#version 430

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
layout (location = 2) in vec2 VertexTexCoord;
layout (location = 3) in vec4 VertexTangent;

struct LightInfo {
  vec4 Position;  // Light position in eye coords.
  vec3 Intensity; // A,D,S intensity
};
uniform LightInfo Light;

out vec3 LightDir;
out vec2 TexCoord;
out vec3 ViewDir;

uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 MVP;

void main()
{
    // Transform normal and tangent to eye space
    vec3 norm = normalize( NormalMatrix * VertexNormal );
    vec3 tang = normalize( NormalMatrix * vec3(VertexTangent) );
    // Compute the binormal
    vec3 binormal = normalize( cross( norm, tang ) ) * VertexTangent.w;

    // Matrix for transformation to tangent space
    mat3 toObjectLocal = mat3(
        tang.x, binormal.x, norm.x,
        tang.y, binormal.y, norm.y,
        tang.z, binormal.z, norm.z ) ;

    // Transform light direction and view direction to tangent space
    vec3 pos = vec3( ModelViewMatrix * vec4(VertexPosition,1.0) );
    LightDir = normalize( toObjectLocal * (Light.Position.xyz - pos) );

    ViewDir = toObjectLocal * normalize(-pos);

    TexCoord = VertexTexCoord;

    gl_Position = MVP * vec4(VertexPosition,1.0);
}

片段着色器:

#version 430

in vec3 LightDir;
in vec2 TexCoord;
in vec3 ViewDir;

layout(binding=0) uniform sampler2D ColorTex;
layout(binding=1) uniform sampler2D NormalMapTex;

struct LightInfo {
  vec4 Position;  // Light position in eye coords.
  vec3 Intensity; // A,D,S intensity
};
uniform LightInfo Light;

struct MaterialInfo {
  vec3 Ka;            // Ambient reflectivity
  vec3 Ks;            // Specular reflectivity
  float Shininess;    // Specular shininess factor
};
uniform MaterialInfo Material;

layout( location = 0 ) out vec4 FragColor;

vec3 phongModel( vec3 norm, vec3 diffR ) {
    vec3 r = reflect( -LightDir, norm );
    vec3 ambient = Light.Intensity * Material.Ka;
    float sDotN = max( dot(LightDir, norm), 0.0 );
    vec3 diffuse = Light.Intensity * diffR * sDotN;

    vec3 spec = vec3(0.0);
    if( sDotN > 0.0 )
        spec = Light.Intensity * Material.Ks *
               pow( max( dot(r,ViewDir), 0.0 ), Material.Shininess );

    return ambient + diffuse + spec;
}

void main() {
    // Lookup the normal from the normal map
    vec4 normal = 2.0 * texture( NormalMapTex, TexCoord ) - 1.0;

    vec4 texColor = texture( ColorTex, TexCoord );
    FragColor = vec4( phongModel(normal.xyz, texColor.rgb), 1.0 );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM