Hello,
I recently started looking into using GLSL and now I’ve run into a bit of a problem while trying to implement per-vertex lighting. I’ve tried working out the maths on pen and paper, have compared my code to numerous sources online yet I can’t find out where I’ve gone wrong. Ambient and diffuse lighting are working fine (if I set either to 0, the shading changes). However, specular lighting is behaving oddly: I can’t say it’s not working at all… I think it’s better if I post full shader codes first and then explain what I’ve found.
vertex shader:
#version 400
layout (location = 0) in vec3 vertexPosition_;
layout (location = 2) in vec3 vertexNormal_;
out vec3 lightIntensity_;
uniform MainMatrices {
mat4 projectionMatrix_;
mat4 modelviewMatrix_;
mat3 normalMatrix_;
};
uniform LightProperties {
// position of the light source in eye coordinates
vec4 lightPosition_;
// ambient light intensity
vec3 La_;
// diffuse light intensity
vec3 Ld_;
// specular light intensity
vec3 Ls_;
};
uniform MaterialProperties {
// ambient reflectivity
vec3 Ka_;
// diffuse reflectivity
vec3 Kd_;
// specular reflectivity
vec3 Ks_;
// shininess factor (usually [1,200])
float shininess_;
};
vec3 calculatePhongShading(in vec4 coordEye, in vec3 normal) {
// find the light's position w.r.t. the vertex position
vec3 relPos = normalize(vec3(lightPosition_ - coordEye));
// find the reflected vector
vec3 ref = reflect(-relPos, normal);
// find the "reverse" vertex direction vector (origin for eye coordinates at camera's position)
// "reverse" needed due to the direction of the reflected vector being opposite to the eye coordinate w.r.t. normal
vec3 vertDir = normalize(-coordEye.xyz);
// find the ambient component
vec3 ambient = La_ * Ka_;
// find the dot product in advance between relPos and normal
// saves having to recalculate it in order to check if specular component exists
float relPosDotNormal = max(dot(relPos, normal), 0.0);
// find the diffuse component
vec3 diffuse = Ld_ * Kd_ * relPosDotNormal;
// define the specular component
vec3 specular = vec3(0.0);
// see if there's any point in finding specular component
if(relPosDotNormal > 0.0) {
specular = Ls_ * Ks_ * pow(max(dot(ref, vertDir), 0.0), shininess_);
}
// final shading = ambient + diffuse + specular
return (ambient + diffuse + specular);
}
void main() {
// find the the vertex coordinate and the normal in eye-space coordinates
vec4 coordEye = (modelviewMatrix_ * vec4(vertexPosition_, 1.0));
vec3 normal = normalize(normalMatrix_ * vertexNormal_);
lightIntensity_ = calculatePhongShading(coordEye, normal);
// find the final vertex position
gl_Position = projectionMatrix_ * modelviewMatrix_ * vec4(vertexPosition_, 1.0);
}
fragment shader:
#version 400
in vec3 lightIntensity_;
layout (location = 0) out vec4 fragColor_;
void main() {
fragColor_ = vec4(lightIntensity_, 1.0);
}
That code produces the following result: http://i39.tinypic.com/snotgi.png
I’ve figured out that the application does get to specular calculation line by altering the following line:
// see if there's any point in finding specular component
if(relPosDotNormal > 0.0) {
specular = Ls_ * Ks_ * pow(max(dot(ref, vertDir), 1.0), shininess_);
}
This produces the following: http://i39.tinypic.com/2pt8h2x.png
I can deduce from this that my code identifies where it should apply specular highlighting but it’s not actually capable of doing it. Ls_ and Ks_ are vec3(1.0, 1.0, 1.0) and shininess_ = 100.
I’ve been going through the same code over and over again and I can’t find where I’m going wrong. Any help appreciated.
Thanks in advance!