Reputation: 3417
I have simple scene that involves a rotating cube and a directional (diffuse) light source, but I don't seem to get the lighting math right.
I load the vertices and normals from the obj file from this tutorial:
Some of my application code:
glm::mat4 modelview = ...
glm::mat4 projection = glm::perspective(60.0f, 16.0f/9.0f, 0.1f, 100.0f);
glm::mat4 MVP = projection * modelview;
glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(modelview)));
glUniformMatrix4fv(MVP_location, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix3fv(NormalMatrix_location, 1, GL_FALSE, &NormalMatrix[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
Vertex shader:
#version 430
in vec3 position;
in vec3 in_normal;
uniform mat4 MVP;
uniform mat3 NormalMatrix;
out vec3 Normal;
out vec4 Color;
void main()
{
gl_Position = MVP * vec4(position, 1.0);
Color = vec4(clamp(position, 0.0, 1.0), 1.0); //based on vertex position
Normal = normalize(NormalMatrix * in_normal);
}
Fragment shader:
#version 430
const vec3 Ambient = vec3(0.15, 0.15, 0.15);
const vec3 LightDirection = normalize(vec3(1.0, 0.0, 1.0));
const vec3 LightColor = vec3(1.0, 1.0, 1.0);
const float Shininess = 20.0;
const float Strength = 5.0;
in vec3 Normal;
in vec4 Color;
out vec4 FragColor;
void main()
{
FragColor = Color;
float diffuse = max(0.0, dot(Normal, LightDirection));
vec3 scatteredLight = Ambient + LightColor * diffuse;
vec3 rgb = min(FragColor.rgb * scatteredLight, vec3(1.0));
FragColor = vec4(rgb, Color.a);
}
This is what I get: my fail
Any idea what am I doing wrong?
Upvotes: 0
Views: 1438
Reputation: 1824
Let me elaborate a bit more on dari's comment.
Your normal vector is multiplied with a normal matrix derived from the view*model
matrix (called modelview
in your application). Multiplying vertices with the model matrix transforms them from local-space to world-space and multiplying vertices in world-space with a view matrix transforms them to view-space coordinates. In your case, you transformed the normal vector with the model and view matrix; this means that your normal vectors are in view-space (their direction, as seen from the viewer's perspective: the camera).
Now, you specified the light's direction vector LightDirection
in world-space (its direction is how you want it to be in the global world right? No need to transform it in any way with a model matrix).
When calculating diffuse/specular lighting, you want your direction/position vectors to all reside in the same coordinate space, otherwise you're doing calculations between different spaces which generates weird results. Since your LightDirection
is in world-space and your Normal
in view-space you get weird results.
What you thus need to do to solve your issue is either:
LightDirection
to view-space by multiplying it with the view matrix (not modelview
since that contains both the model and view matrix).modelview
) so your normal vector will end up in world-space just like LightDirection
currently is.The important thing is that both vectors are in the same space (can be either world or view, whatever you prefer).
Note that this applies to when you want to give the impression the camera is moving while the objects are stationary (allowing you to move to unlit sides of your objects); see Reto Koradi's comment below.
Upvotes: 2