我正在世界空间坐标中实现正常/凹凸贴图(我发现那些更容易使用)并且我的照明在没有法线贴图的情况下工作正常,但是当引入法线贴图(以及使用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);
}
答案 0 :(得分:2)
layout(location = 3) in vec3 bitangent;
layout(location = 5) in vec2 texCoord;
5 这是一个正确的位置吗?
关于TBN矩阵。你必须(怎么说 jhoffman0x )将 normalMat 矩阵乘以切线和 bitangent ,规范化结果和在制作 TBN 矩阵之后:
来自David Wolff - OpenGL 4.0 Shading Language Cookbook的示例。顶点着色器:
#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);
}
Fragment Shader:
#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 );
}