#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow *window); void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods); void mouse_pos_callback(GLFWwindow* window, double xpos, double ypos); void mouse_button_callback(GLFWwindow* window, int button, int action, int mods); void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset); unsigned int width = 800; unsigned int height = 600; Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); float lastX = width / 2.0f; float lastY = height / 2.0f; bool firstMouse = true; bool mouseCaptured = false; float deltaTime = 0.0f; float lastFrame = 0.0f; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetKeyCallback(window, keyboard_callback); glfwSetCursorPosCallback(window, mouse_pos_callback); glfwSetMouseButtonCallback(window, mouse_button_callback); glfwSetScrollCallback(window, mouse_scroll_callback); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } glViewport(0, 0, width, height); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glEnable(GL_DEPTH_TEST); //stbi_set_flip_vertically_on_load(true); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 330 core"); // Shaders Shader light_shader("resources/shaders/vert.glsl", "resources/shaders/light_shader.glsl"); Shader light_cubeShader("resources/shaders/vert.glsl", "resources/shaders/light_object.glsl"); // Models Model croissant("resources/models/croissant/source/croissant.obj"); Model cube("resources/models/cube/cube.obj"); // Objects Object object1(croissant, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.0f, 0.0f, 0.0f)); Object object2(croissant, glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.0f, 0.0f, 0.0f)); Object object3(croissant, glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.0f, 0.0f, 0.0f)); Object light_cube(cube, glm::vec3(1.2f, 1.0f, 2.0f), glm::vec3(0.05f, 0.05f, 0.05f), glm::vec3(0.0f, 0.0f, 0.0f)); // Lights DirectLight directLight(glm::vec3(-0.2f, -1.0f, -0.3f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.2f, 0.2f, 0.2f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 1.0f)); SpotLight spotLight(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), 12.55f, 17.5f, glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.2f, 0.2f, 0.2f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, 0.09f, 0.032f); std::vector pointLights; pointLights.emplace_back(glm::vec3(1.2f, 1.0f, 2.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.2f, 0.2f, 0.2f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, 0.09f, 0.032f); pointLights.emplace_back(glm::vec3(-1.2f, 1.0f, 2.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.2f, 0.2f, 0.2f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, 0.09f, 0.032f); static float positionX = 0.0f; static float positionY = 0.0f; static float positionZ = 0.0f; static float lightCubePositionX = 0.0f; static float lightCubePositionY = 0.0f; static float lightCubePositionZ = 3.0f; static float* light_color = new float[3]{1.0f, 1.0f, 1.0f}; static float light_cutoff = 12.5f; static float light_outerCutoff = 17.5f; while(!glfwWindowShouldClose(window)) { float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); processInput(window); if (mouseCaptured) io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); double mouseX, mouseY; glfwGetCursorPos(window, &mouseX, &mouseY); ImGui::Begin("Settings"); ImGui::Text("FPS: %.2f", 1.0f / deltaTime); ImGui::SliderFloat("Object 1 Position X", &positionX, -5.0f, 5.0f); ImGui::SliderFloat("Object 1 Position Y", &positionY, -5.0f, 5.0f); ImGui::SliderFloat("Object 1 Position Z", &positionZ, -5.0f, 5.0f); ImGui::SliderFloat("Light Cube Position X", &lightCubePositionX, -5.0f, 5.0f); ImGui::SliderFloat("Light Cube Position Y", &lightCubePositionY, -5.0f, 5.0f); ImGui::SliderFloat("Light Cube Position Z", &lightCubePositionZ, -5.0f, 5.0f); ImGui::ColorEdit3("Light Cube Color", light_color); ImGui::SliderFloat("Light Cutoff", &light_cutoff, 0.0f, 90.0f); ImGui::SliderFloat("Light Outer Cutoff", &light_outerCutoff, 0.0f, 90.0f); ImGui::End(); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 projection = glm::perspective(glm::radians(45.0f), float(width) / float(height), 0.1f, 100.0f); light_shader.use(); light_shader.setMat4("view", view); light_shader.setVec3("viewPos", camera.Position); light_shader.setMat4("projection", projection); // Directional light directLight.use(light_shader); // Spotlight spotLight.setPosition(camera.Position); spotLight.setDirection(camera.Front); spotLight.setCutOff(light_cutoff); spotLight.setOuterCutOff(light_outerCutoff); spotLight.use(light_shader); // Point light light_shader.setInt("pointLightCount", static_cast(pointLights.size())); pointLights[0].setPosition(glm::vec3(lightCubePositionX, lightCubePositionY, lightCubePositionZ)); pointLights[0].setColor(glm::vec3(light_color[0], light_color[1], light_color[2])); for (size_t i = 0; i < pointLights.size(); ++i) { pointLights[i].use(light_shader, static_cast(i)); } object1.setPosition(glm::vec3(positionX, positionY, positionZ)); object1.Draw(light_shader, deltaTime); object2.setAcceleration(glm::vec3(0.0f, 0.001f, 0.0f)); object2.Draw(light_shader, deltaTime); object3.setAcceleration(glm::vec3(0.0f, -0.001f, 0.0f)); object3.Draw(light_shader, deltaTime); // Light cube shader light_cubeShader.use(); light_cubeShader.setMat4("view", view); light_cubeShader.setMat4("projection", projection); for (size_t i = 0; i < pointLights.size(); ++i) { light_cube.setPosition(pointLights[i].getPosition()); light_cubeShader.setVec3("lightColor", pointLights[i].getColor()); light_cube.Draw(light_cubeShader, deltaTime); } ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwTerminate(); return 0; } void framebuffer_size_callback(GLFWwindow* window, int new_width, int new_height) { width = new_width; height = new_height; glViewport(0, 0, new_width, new_height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS && mouseCaptured) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); mouseCaptured = false; } if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS && mouseCaptured) camera.ProcessKeyboard(FORWARD, deltaTime); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS && mouseCaptured) camera.ProcessKeyboard(BACKWARD, deltaTime); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS && mouseCaptured) camera.ProcessKeyboard(LEFT, deltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS && mouseCaptured) camera.ProcessKeyboard(RIGHT, deltaTime); if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS && !mouseCaptured && !ImGui::GetIO().WantCaptureMouse) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); mouseCaptured = true; } } void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {} void mouse_pos_callback(GLFWwindow* window, double xposIn, double yposIn) { float xpos = static_cast(xposIn); float ypos = static_cast(yposIn); if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; if (mouseCaptured) camera.ProcessMouseMovement(xoffset, yoffset); } void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {} void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {}