diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag index cac4b8a..8c95e34 100644 --- a/res/shaders/simple.frag +++ b/res/shaders/simple.frag @@ -4,7 +4,13 @@ in layout(location = 0) vec3 normal; in layout(location = 1) vec2 textureCoordinates; in layout(location = 2) vec3 worldPositions; -uniform vec3 lightPositions[3]; +struct LightSource { + vec3 position; + vec3 color; +}; + +uniform LightSource lights[3]; + uniform vec3 cameraPosition; uniform vec3 ballPosition; @@ -21,7 +27,6 @@ vec3 reject(vec3 from, vec3 onto) { } const vec3 objectColor = vec3(1.0, 1.0, 1.0); -const vec3 lightColor = vec3(0.5, 0.5, 0.5); const float ambientStrength = 0.1; const float specularStrength = 0.5; @@ -36,24 +41,24 @@ void main() vec3 norm = normalize(normal); vec3 viewDir = normalize(cameraPosition - worldPositions); - vec3 ambient = ambientStrength * lightColor * objectColor; + vec3 ambient = ambientStrength * vec3(1.0, 1.0, 1.0) * objectColor; vec3 result = ambient; for (int i = 0; i < 3; i++) { - vec3 lightVector = lightPositions[i] - worldPositions; + vec3 lightVector = lights[i].position - worldPositions; vec3 lightDir = normalize(lightVector); - vec3 fragToBall = lightPositions[i] - ballPosition; + vec3 fragToBall = lights[i].position - ballPosition; float d = length(lightVector); float attenuation = 1.0 / (la + d * lb + d * d * lc); float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = diff * lightColor; + vec3 diffuse = diff * lights[i].color; vec3 halfwayDir = normalize(lightDir + viewDir); // little optimization (blinn-phong) float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess); - vec3 specular = specularStrength * spec * lightColor; + vec3 specular = specularStrength * spec * lights[i].color; // the ball's light is put inside it, thus it would cast a shadow all over the scene. // to counter-act this, we can simply exclude it. i should instead move the light. diff --git a/src/gamelogic.cpp b/src/gamelogic.cpp index afe3f76..9216c09 100644 --- a/src/gamelogic.cpp +++ b/src/gamelogic.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include "gamelogic.h" +#include "glm/detail/qualifier.hpp" #include "glm/ext/vector_float3.hpp" #include "glm/matrix.hpp" #include "sceneGraph.hpp" @@ -41,8 +43,12 @@ SceneNode* boxNode; SceneNode* ballNode; SceneNode* padNode; +struct LightSource { + glm::vec3 position; + glm::vec3 color; +}; std::vector lightNodes; -std::vector lightCoords; +std::vector lights; glm::vec3 cameraPosition; @@ -98,12 +104,6 @@ void mouseCallback(GLFWwindow* window, double x, double y) { glfwSetCursorPos(window, windowWidth / 2, windowHeight / 2); } -//// A few lines to help you if you've never used c++ structs -// struct LightSource { -// bool a_placeholder_value; -// }; -// LightSource lightSources[/*Put number of light sources you want here*/]; - void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { buffer = new sf::SoundBuffer(); if (!buffer->loadFromFile("../res/Hall of the Mountain King.ogg")) { @@ -172,7 +172,6 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { - getTimeDeltaSeconds(); std::cout << fmt::format("Initialized scene with {} SceneNodes.", totalChildren(rootNode)) << std::endl; @@ -364,10 +363,21 @@ void updateFrame(GLFWwindow* window) { updateNodeTransformations(rootNode, VP, glm::mat4(1.0f)); // Pass identity for initial model matrix - lightCoords.clear(); - for (auto* light : lightNodes) { - lightCoords.push_back(light->worldPosition); + lights.clear(); + for (auto* lightNode : lightNodes) { + LightSource light; + light.position = lightNode->worldPosition; + + if (lightNode->lightIdx == 0) { + light.color = glm::vec3(1.0f, 0.0f, 0.0f); // Warm white (ceiling) + } else if (lightNode->lightIdx == 1) { + light.color = glm::vec3(0.0f, 1.0f, 0.0f); // Cool white (pad) + } else { + light.color = glm::vec3(0.0f, 0.0f, 1.0f); // Orange (ball) + } + lights.push_back(light); } + } void updateNodeTransformations(SceneNode* node, glm::mat4 transformationThusFar, glm::mat4 modelMatrixThusFar) { @@ -403,15 +413,23 @@ void renderNode(SceneNode* node) { glUniformMatrix4fv(4, 1, GL_FALSE, glm::value_ptr(node->modelMatrix)); glUniformMatrix3fv(5, 1, GL_FALSE, glm::value_ptr(node->normalMatrix)); - GLint lightPosLoc = shader->getUniformFromName("lightPositions"); - glUniform3fv(lightPosLoc, 3, glm::value_ptr(lightCoords[0])); - GLint cameraPosLoc = shader->getUniformFromName("cameraPosition"); glUniform3fv(cameraPosLoc, 1, glm::value_ptr(cameraPosition)); GLint ballPosLoc = shader->getUniformFromName("ballPosition"); glUniform3fv(ballPosLoc, 1, glm::value_ptr(ballPosition)); + for (int i = 0; i < lights.size(); i++) { + std::string posName = "lights[" + std::to_string(i) + "].position"; + std::string colorName = "lights[" + std::to_string(i) + "].color"; + + GLint posLoc = shader->getUniformFromName(posName.c_str()); + GLint colorLoc = shader->getUniformFromName(colorName.c_str()); + + glUniform3fv(posLoc, 1, glm::value_ptr(lights[i].position)); + glUniform3fv(colorLoc, 1, glm::value_ptr(lights[i].color)); + } + switch(node->nodeType) { case GEOMETRY: if(node->vertexArrayObjectID != -1) {