I implemented lighting in my engine. But there is some problem the object does not lights up properly
The specular lighting does not work at all
Here is the vertex shader :
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coords;
layout (location = 2) in vec3 normals;
uniform mat4 projectionMatrix;
uniform mat4 worldMatrix;
uniform mat4 viewMatrix;
out vec2 coords;
out vec3 vertexNormals;
out vec3 vertexPos;
void main() {
vec4 mVerPos = worldMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * viewMatrix * worldMatrix * vec4(position, 1.0);
coords = tex_coords;
vertexNormals = normalize(worldMatrix * vec4(normals, 0.0)).xyz;
vertexPos = mVerPos.xyz;
}
Here is the fragment shader :
#version 330
struct Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
int hasTexture;
float reflectance;
};
struct PointLight {
vec3 color;
vec3 position;
float intensity;
float constant;
float linear;
float exponent;
};
struct DirLight {
vec3 position;
vec3 color;
float intensity;
};
out vec4 fragColor;
in vec2 coords;
in vec3 vertexNormals;
in vec3 vertexPos;
uniform sampler2D sampler;
uniform vec3 ambientColor;
uniform Material material;
uniform PointLight pointLight;
uniform float specularPower;
uniform DirLight dirLight;
vec4 ambientC;
vec4 diffuseC;
vec4 specularC;
void setUpColor(Material material, vec2 coords) {
if (material.hasTexture == 1) {
ambientC = texture(sampler, coords);
diffuseC = ambientC;
specularC = ambientC;
}
else {
ambientC = material.ambient;
diffuseC = material.diffuse;
specularC = material.specular;
}
}
vec4 calcLightColor(vec3 lightColor, float lightIntensity, vec3 position, vec3 to_light_dir, vec3 normal) {
vec4 diffuseColour = vec4(0, 0, 0, 0);
vec4 specColour = vec4(0, 0, 0, 0);
// Diffuse Light
float diffuseFactor = max(dot(normal, to_light_dir ), 0.0);
diffuseColour = diffuseC * vec4(lightColor, 1.0) * lightIntensity * diffuseFactor;
// Specular Light
vec3 camera_direction = normalize(-position);
vec3 from_light_dir = -to_light_dir;
vec3 reflected_light = normalize(reflect(from_light_dir, normal));
float specularFactor = max(dot(camera_direction, reflected_light), 0.0);
specularFactor = pow(specularFactor, specularPower);
specColour = specularC * lightIntensity * specularFactor * material.reflectance * vec4(lightColor, 1.0);
return (diffuseColour + specColour);
};
vec4 calcPointLight(PointLight light, vec3 position, vec3 normal)
{
vec3 light_direction = light.position - position;
vec3 to_light_source = normalize(light_direction);
vec4 lightColor = calcLightColor(light.color, light.intensity, position, to_light_source, normal);
// Attenuation
float distance = length(light_direction);
float attenuationInv = light.constant + light.linear * distance +
light.exponent * distance * distance;
return lightColor / attenuationInv;
}
vec4 calcDirLight(DirLight light, vec3 position, vec3 normal) {
return calcLightColor(light.color, light.intensity, position, normalize(light.position), normal);
}
void main() {
setUpColor(material, coords);
vec4 diffuseSpecularComp = calcDirLight(dirLight, vertexPos, vertexNormals);
diffuseSpecularComp += calcPointLight(pointLight, vertexPos, vertexNormals);
fragColor = ambientC * vec4(ambientColor, 1) + diffuseSpecularComp;
}
Here is the source code : https://www.dropbox.com/scl/fo/hwlnz913jm6c9xli2dsb6/h?dl=0&rlkey=b2zj0w6kttwu3b1di9rejwnq3
When I changed the value of zero at float diffuseFactor = max(dot(normal, to_light_dir ), 0.0); and at float specularFactor = max(dot(camera_direction, reflected_light), 0.0); the to something above like 0.1
this what I get
but the specular does not work at all.
There are a couple of problems in your code, but I'm not entirely sure which causes the problem.
Problems
vertexNormalscorrectly. It shouldn't be a problem in your specific case, because seemingly you don't scale your mesh nonuniformly, but it's worth mentioning because it's a common mistake. You multiply the object space normal with the world matrix, but you should instead multiply it with the inverse transposed of the world matrix.vertexNormals, but it's not correct. Although you normalized the normal in the vertex shader, but the fragment shader doesn't get that specific vector. It gets the linear interpolation (basically a weighted average) of the 3vertexNormalsand the result is not necessarily normalized. So you should normalize it in the fragment shader as well.setUpColorfunction, why do you assign the same value toambientC,diffuseC, andspecularC? Usually, there are different textures for these, but at least for diffuse and specular.Other random observations
positiontwice withworldMatrix, but why? It seems like wasted performance (maybe the compiler optimizes it).DirLightstruct you have apositionmember, but directional lights don't have a position, they just have a direction. I see that you compute the direction from the position, but it seems unusual.Materialstruct (and in other places) you usevec4s instead ofvec3s, but I guess, the last components are always ones. It's a waste of memory, you could just set the alpha value to1.0fat the end ofmain.Joey de Vries has amazing tutorials, including the Phong shading (using C++). In the One last thing section he also explains why it's important to use the inverse transposed matrix to transform the normal.