I'm trying to render multiple directional and multiple point lights but it only renders the last directional and last point light in the light arrays. I checked that all the data for lighting is properly sent to the glsl fragment shader but it doesn't seem to work.
NUM_DIR_LIGHTS-1
and NUM_POINT_LIGHTS-1
are dynamically inserted into the fragment shader and also have the right values.
Calculation of the fragment color output:
vec4 ambient = vec4(0.0);
vec4 diffuse = vec4(0.0);
vec4 specular = vec4(0.0);
vec4 diffuseTexel = texture(u_Material.DiffuseMap, v_TexCoord);
vec4 specularTexel = texture(u_Material.SpecularMap, v_TexCoord);
vec4 normalTexel = texture(u_Material.NormalMap, v_TexCoord);
vec3 viewDir = normalize(u_CameraPosition - v_Position);
float dirShadow = 0.0;
// calculate material for all directional lights
vec3 normalFromMap = normalize(transpose(inverse(v_ModelRotation)) * normalTexel.xyz);
vec3 normalizedNormal = normalize(v_Normal);
for (int i = 0; i < NUM_DIR_LIGHTS-1; i++)
{
vec3 lightDir = normalize(-u_DirectionalLights[i].Direction);
// if material is mapped then apply lighting with lighting maps
if (u_Material.IsMapped)
{
// ambient lighting
ambient += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * diffuseTexel.rgb, 1.0);
// diffuse lighting
float diff = max(dot(normalFromMap, lightDir), 0.0);
diffuse += vec4(u_DirectionalLights[i].Color * diff * diffuseTexel.rgb, 1.0);
// specular lighting
vec3 reflectDir = reflect(-lightDir, normalFromMap);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
specular += vec4(u_DirectionalLights[i].Color * spec * specularTexel.rgb, 1.0);
dirShadow += calcDirLightShadow(i, lightDir, normalTexel.xyz);
}
else
{
// ambient lighting for material
ambient += vec4(u_DirectionalLights[i].Color * (u_Material.Ambient + u_DirectionalLights[i].Intensity * u_Material.Diffuse), 1.0);
// diffuse lighting for material
float diff = max(dot(normalizedNormal, lightDir), 0.0);
diffuse += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * diff * u_Material.Diffuse, 1.0);
// specular lighting for material
vec3 reflectDir = reflect(-lightDir, normalizedNormal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
specular += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * spec * u_Material.Specular, 1.0);
dirShadow += calcDirLightShadow(i, lightDir, v_Normal);
}
}
// calculate material for all point lights
vec3 pointAmbient = vec3(0.0);
vec3 pointDiffuse = vec3(0.0);
vec3 pointSpecular = vec3(0.0);
for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
// if material is mapped then apply lighting with lighting maps
if (u_Material.IsMapped)
{
// ambient lighting
pointAmbient += u_PointLights[i].Color * u_PointLights[i].Intensity * diffuseTexel.rgb;
// diffuse lighting
vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
float diff = max(dot(normalFromMap, lightDir), 0.0);
pointDiffuse += u_PointLights[i].Color * diff * diffuseTexel.rgb;
// specular lighting
vec3 reflectDir = reflect(-lightDir, normalFromMap);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
pointSpecular += u_PointLights[i].Color * spec * specularTexel.rgb;
}
else
{
// ambient lighting for material
pointAmbient += u_PointLights[i].Color * (u_Material.Ambient + u_PointLights[i].Intensity * u_Material.Diffuse);
// diffuse lighting for material
vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
float diff = max(dot(normalizedNormal, lightDir), 0.0);
pointDiffuse += u_PointLights[i].Color * u_PointLights[i].Intensity * diff * u_Material.Diffuse;
// specular lighting for material
vec3 reflectDir = reflect(-lightDir, normalizedNormal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
pointSpecular += u_PointLights[i].Color * u_PointLights[i].Intensity * spec * u_Material.Specular;
}
// calculate attenuation
float distance = length(u_PointLights[i].Position - v_Position);
float attenuation = 1.0f / (u_PointLights[i].Constant + u_PointLights[i].Linear *
distance + u_PointLights[i].Quadratic * (distance * distance));
// include attenuation in lighting
pointAmbient *= attenuation;
pointDiffuse *= attenuation;
pointSpecular *= attenuation;
}
// calculate directional lighting with shadow
vec3 lighting = vec3(ambient + (1.0 - dirShadow) * (diffuse + specular));
return vec4(lighting + pointAmbient + pointDiffuse + pointSpecular, 1.0);
I hope someone can understand why it isn't rendering all lights.
The problem is
for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
// [...]
pointAmbient *= attenuation;
pointDiffuse *= attenuation;
pointSpecular *= attenuation;
}
Here the sum of the light sources is multiplied by the attenuation within the loop that iterates through the light sources. This means that light sources that have already been added are multiplied by the attenuation of later light sources. The light from the light sources that have already been added will become weaker and weaker with each new light source that is added.
Possible solution:
vec3 pointAmbient = vec3(0.0);
vec3 pointDiffuse = vec3(0.0);
vec3 pointSpecular = vec3(0.0);
for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
// calculate attenuation
float distance = length(u_PointLights[i].Position - v_Position);
float attenuation = 1.0f / (u_PointLights[i].Constant + u_PointLights[i].Linear *
distance + u_PointLights[i].Quadratic * (distance * distance));
// if material is mapped then apply lighting with lighting maps
if (u_Material.IsMapped)
{
// ambient lighting
pointAmbient += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * diffuseTexel.rgb;
// diffuse lighting
vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
float diff = max(dot(normalFromMap, lightDir), 0.0);
pointDiffuse += attenuation * u_PointLights[i].Color * diff * diffuseTexel.rgb;
// specular lighting
vec3 reflectDir = reflect(-lightDir, normalFromMap);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
pointSpecular += attenuation * u_PointLights[i].Color * spec * specularTexel.rgb;
}
else
{
// ambient lighting for material
pointAmbient += attenuation * u_PointLights[i].Color * (u_Material.Ambient + u_PointLights[i].Intensity * u_Material.Diffuse);
// diffuse lighting for material
vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
float diff = max(dot(normalizedNormal, lightDir), 0.0);
pointDiffuse += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * diff * u_Material.Diffuse;
// specular lighting for material
vec3 reflectDir = reflect(-lightDir, normalizedNormal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
pointSpecular += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * spec * u_Material.Specular;
}
}