I'm working on a project that requires two lights in opengl. These should be directional lights. I'm 99% sure I have taken a route that is more complicated than it needed to be, but I'm not understanding the project well as is, so whatever I could get to work was the route I took. I have a pyramid object with a texture on it. I also have two separate lights, a fill light and a key light. The fill light is more for the ambient lighting, and the key light is the primary "lightbulb" per se. For all 3 objects, I have a vertex shader and fragment shader (although I don't know if I actually needed to / should have done that). I have a list of verticies that draw the shapes, contain normals, and texture coordinates. The primary pyramid object uses all 3 of these attributes, but the lights only use the verticies so they have the same shape.
My main problem is that the lights aren't working correctly. The pyramid is only lit via the ambient lighting of the key light. It doesn't properly incorporate the diffuse or specular lighting components. The fill light also seems to be largely ignored, but it seems to be because the key light is overriding all other light data.
Here is what my shaders look like for the primary pyramid:
/* Pyramid Vertex Shader Source Code */
const GLchar * pyramidVertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout (location = 1) in vec3 normal; // VAP position 1 for normals
layout (location = 2) in vec2 textureCoordinate; // Color data from Vertex Attrib Pointer 1
out vec3 Normal; // For outgoing normals to fragment shader
out vec3 FragmentPos; // For outgoing color / pixels to fragment shader
out vec2 mobileTextureCoordinate; // variable to transfer Texture data to the fragment shader
// Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates
FragmentPos = vec3(model * vec4(position, 1.0f)); // Gets fragment / pixel position in world space only (exclude view and projection)
mobileTextureCoordinate = vec2(textureCoordinate.x, 1.0f - textureCoordinate.y); // flips the texture horizontal
Normal = mat3(transpose(inverse(model))) * normal; // get normal vectors in world space only and exclude normal translation properties
}
);
/* Pyramid Fragment Shader Source Code */
const GLchar * pyramidFragmentShaderSource = GLSL(330,
in vec2 mobileTextureCoordinate; // Variable to hold incoming color data from vertex shader
in vec3 Normal; // For incoming normals
in vec3 FragmentPos; // For incoming fragment position
out vec4 pyramidColor; // For outgoing pyramid color
// Uniform variables for object color, light color, light position, and camera/view position
uniform vec3 fillLightColor;
uniform vec3 fillLightPos;
uniform vec3 keyLightColor;
uniform vec3 keyLightPos;
uniform vec3 viewPosition;
uniform sampler2D uTexture; // Useful when working with multiple textures
void main() {
/* Phong lighting model calculations to generate ambient, diffuse, and specular components */
// Calculate Ambient lighting
float ambientStrength = 0.3f; // Set ambient or global lighting strength
vec3 ambient = ambientStrength * fillLightColor; // Generate ambient light color
// Calculate Diffuse lighting for fill lamp
vec3 norm = normalize(Normal); // Normalize vectors to 1 unit
vec3 lightDirection = normalize(fillLightPos - FragmentPos); // Calculate distance (light direction) between fill light source and fragments/pixels
float impact = max(dot(norm, lightDirection), 0.0); // Calculate diffuse impact by generating dot product of normal and light
vec3 diffuse = impact * fillLightColor; // Generate diffuse light color
// Calculate Specular lighting for fill lamp
float specularIntensity = 0.8f; // Set specular light strength
float highlightSize = 16.0f; // Set specular highlight size
vec3 viewDir = normalize(viewPosition - FragmentPos); // Calculate view direction
vec3 reflectDir = reflect (-lightDirection, norm); // Calculate reflection vector
//Calculate specular component
float specularComponent = pow(max(dot(viewDir, reflectDir), 0.0), highlightSize);
vec3 specular = specularIntensity * specularComponent * fillLightColor;
// Calculate Ambient lighting for key lamp
float keyAmbientStrength = 1.0f;
vec3 keyAmbient = keyAmbientStrength * keyLightColor;
// Calculate Diffuse lighting for key lamp
vec3 keyLightDirection = normalize(keyLightPos - FragmentPos); // Calculate distance between key light source and fragments
float keyImpact = max(dot(norm, keyLightDirection), 0.0);
vec3 keyDiffuse = keyImpact * keyLightColor;
// Calculate Specular lighting for key lamp
float keySpecularIntensity = 0.8f; // Set specular light strength
float keyHighlightSize = 32.0f; // Set specular highlight size
vec3 keyReflectDir = reflect (-keyLightDirection, norm); // Calculate reflection vector
//Calculate specular component
float keySpecularComponent = pow(max(dot(viewDir, keyReflectDir), 0.0), keyHighlightSize);
vec3 keySpecular = keySpecularIntensity * keySpecularComponent * keyLightColor;
// Calculate phong result
vec3 objectColor = texture(uTexture, mobileTextureCoordinate).xyz;
vec3 fillResult = (ambient + diffuse + specular);
vec3 keyResult = (keyAmbient + keyDiffuse + keySpecular);
vec3 lightingResult = fillResult + keyResult;
vec3 phong = (lightingResult) * objectColor;
pyramidColor = vec4(phong, 1.0f); // Send lighting results to GPU
}
);
As far as I can tell, my issue is in my mathematics for calculating the lighting, but no matter how I try to change it... I'm just not smart enough to know what exactly is going on. Admittedly my linear algebra skills are garbage so I'm really having a hard time. I'm sure there are many errors in my code and how I approached the issue, but after probably upwards of 15-20 hours of trying, this is the best I could manage to load and look even remotely correct.
The fill light is pretty much supposed to be a white light, illuminating the the texture as a normal light would. The key light is supposed to be green, so the side(s) that are exposed to the key light should have a green look to them. Currently, the whole pyramid is just illuminated in the same greenish color (no shading or directional appearances to the lights).