I'm currently implementing a simple Pool game in OpenGL 3+ with GLSL shaders (custom matrix stack and the works). I've got diffuse lighting working but I'm having trouble with the specular lighting for directional lights.
I think it is best if I illustrate my problem with a video capture. Observe in the video as the camera moves toward the cue ball and when crossing the world origin (0,0,0) the specular highlight on the cue ball moves strangely. I think it is something to do with how I have set up the "camera" and how I move it, since when switching to the second camera (seen in the video at the end) which is located at an opposite direction and attached to the cue ball, the specular highlights are not to be seen at all.
[media]
[/media]
At each frame I set the perspective and camera as follows:
void Camera::Set() {
// calculate new perspective matrix
RenderSystemServices::GetRenderSystem()->CalculatePerspective(m_fov, m_clippingPlanes);
// load the modelveiw identity
MODELVIEW_LOADIDENTITY;
// apply lookat
MODELVIEW_MULTIPLY(glm::gtx::transform2::lookAt(GetPosition(), m_lookAt, m_up));
// apply rotation
MODELVIEW_MULTIPLY(glm::gtc::quaternion::mat4_cast(GetRotation()));
// store the view matrix
m_viewMatrix = MODELVIEW_TOP;
}
Also, I calculate the light position as follows:
void DirectionalLight::Set() {
const matrix3x3f normal_mat = glm::transpose(glm::inverse(glm::mat3(MODELVIEW_TOP)));
CurrentPosition = vector3f(normal_mat * GetPosition());
}
The 'CurrentPosition' is then sent to the fragment shader as 'LightPos'.
The vertex and fragment shaders are as follows.
vertex shader:
#version 130
uniform mat4 ModelViewProjectionMat;
uniform mat4 ModelViewMat;
uniform mat3 NormalMat;
in vec3 InVertex;
in vec3 InNormal;
in vec4 InColor;
in vec2 InTexCoord;
out vec3 EyeVert;
out vec3 EyeNorm;
out vec4 Color;
out vec2 TexCoord;
void main() {
TexCoord = InTexCoord;
Color = InColor;
EyeVert = vec3(ModelViewMat * vec4(InVertex, 0.0));
EyeNorm = NormalMat * InNormal;
gl_Position = ModelViewProjectionMat * vec4(InVertex, 1.0);
}
fragment shader:
#version 130
uniform sampler2D Texture0;
uniform vec3 LightPos;
uniform vec3 EyePos;
uniform vec4 LightAmbient;
uniform vec4 LightDiffuse;
uniform vec4 LightSpecular;
uniform vec4 MatAmbient;
uniform vec4 MatDiffuse;
uniform vec4 MatSpecular;
uniform vec4 MatEmission;
uniform float MatShininess;
in vec3 EyeVert;
in vec3 EyeNorm;
in vec4 Color;
in vec2 TexCoord;
out vec4 FragColor;
void main() {
vec3 normal = normalize(EyeNorm);
float lambertTerm = max(dot(normal, normalize(LightPos)), 0.0);
vec4 diffuse = MatDiffuse * LightDiffuse * lambertTerm;
vec4 ambient = MatAmbient * LightAmbient;
vec3 lightDir = normalize(LightPos);
vec3 eyeDir = normalize(EyePos - EyeVert);
vec3 halfVec = normalize(eyeDir + lightDir);
vec4 specular = MatSpecular * LightSpecular * pow(max(dot(normal, halfVec), 0.0), MatShininess);
FragColor = diffuse + ambient + specular;
}
Any ideas or questions very welcome!