I was following the skeletal animation tutorial on learnopengl.com and it works fine, animates properly. However, lighting does not work when the 3D model is moving (appears black), but works when it is static. I assume the issue is with the normals. How do you calculate normals for an animated model?
Vertex shader- the vec3 localnormal does nothing, but I assume its used for something?
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 norm;
layout(location = 2) in vec2 tex;
layout(location = 5) in ivec4 boneIds;
layout(location = 6) in vec4 weights;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
const int MAX_BONES = 100;
const int MAX_BONE_INFLUENCE = 4;
uniform mat4 finalBonesMatrices[MAX_BONES];
out vec2 TexCoords;
out vec3 FragPos;
out vec3 Normal;
void main()
{
vec4 totalPosition = vec4(0.0f);
for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++)
{
if(boneIds[i] == -1)
continue;
if(boneIds[i] >=MAX_BONES)
{
totalPosition = vec4(pos,1.0f);
break;
}
vec4 localPosition = (finalBonesMatrices[boneIds[i]] * weights[i]) * vec4(pos,1.0f);
totalPosition += localPosition;
vec3 localNormal =mat3(transpose(inverse(finalBonesMatrices[boneIds[i]]))) * norm;
}
mat4 viewModel = view * model;
gl_Position = projection * viewModel * totalPosition;
TexCoords = tex;
FragPos = pos;
Normal = norm;
}
Fragment Shader
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D texture_diffuse1;
sampler2D texture_specular1;
float shininess;
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float intensityVal;
};
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float intensityVal;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float intensityVal;
};
#define MAX_POINT_LIGHTS 1
#define MAX_SPOT_LIGHTS 1
#define MAX_DIR_LIGHTS 1
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform DirLight dirLight[MAX_DIR_LIGHTS];
uniform PointLight pointLights[MAX_POINT_LIGHTS];
uniform SpotLight spotLight[MAX_SPOT_LIGHTS];
uniform Material material;
// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 result=vec3(0.0);
// directional lighting
for(int i = 0; i < MAX_DIR_LIGHTS; i++)
result += CalcDirLight(dirLight[i], norm, viewDir);
//point lights
for(int i = 0; i < MAX_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
// spot light
for(int i = 0; i < MAX_SPOT_LIGHTS; i++)
result += CalcSpotLight(spotLight[i], norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}
// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords))*light.intensityVal;
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords))*light.intensityVal;
return (ambient + diffuse + specular);
}
// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords))*light.intensityVal;
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords))*light.intensityVal;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords))*light.intensityVal;
vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, TexCoords))*light.intensityVal;
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}
How do I pass the correct normals to the fragment shader?