gpt4 book ai didi

c++ - 镜面反射分量不正确的法线贴图和 phong 着色

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:34 26 4
gpt4 key购买 nike

我正在世界空间坐标中实现法线/凹凸贴图(我发现它们更容易使用)并且我的照明在没有法线贴图的情况下也能正常工作,但是当引入法线贴图(以及使用 TBN 矩阵计算的新 vector )时我的照明的镜面反射组件已关闭。

镜面反射分量不在相机和灯光之间,所以有些地方是错误的。但是,查看我的代码我找不到任何问题。切线和双切线来自 ASSIMP 对象加载器,eyePos 和 lightPos 也在世界坐标中。

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

这是一张展示问题的图片:

Bump mapping with wrong specular component

顶点着色器:

#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 矩阵乘以 tangentbitangent,归一化结果,然后 make 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);
}

片段着色器:

#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 );
}

关于c++ - 镜面反射分量不正确的法线贴图和 phong 着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21994094/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com