#include #include #include #include #include // glad and GLFW #include #include // glm math #include #include #include // HPP files #include "shader.h" #define VERTEX_FILE "./shaders/vertex.glsl" #define FRAGMENT_FILE "./shaders/fragment.glsl" #define COMPUTE_FILE "./shaders/compute.glsl" const float SCR_WIDTH = 1200.0f; const float SCR_HEIGHT = 1200.0f; int main(void) { // Initialize GLFW if (!glfwInit()) return -1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // REQUIRED on macOS glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_SAMPLES, 8); // 8x MSAA GLFWwindow *window = glfwCreateWindow((int)SCR_WIDTH, (int)SCR_HEIGHT, "RASTER", nullptr, nullptr); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cerr << "Failed to initialize GLAD\n"; return -1; } glViewport(0, 0, (int)SCR_WIDTH, (int)SCR_HEIGHT); // DEBUG std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl; // ERROR: macOS does not support compute shaders in OpenGL < 4.3. // GLuint computeProgram = createComputeProgram(COMPUTE_FILE); // ----- Vertex Data ----- // Cube // Positions float vertices[] = {// positions -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f}; unsigned int indices[] = {0, 1, 2, 2, 3, 0}; GLuint VAO, VBO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // position - VERTEX SHADER glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); // color - FRAGMENT SHADER glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)(3 * sizeof(float))); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, 0); // glBindVertexArray(0); // Load shaders GLuint shaderProgram = createShaderProgram(VERTEX_FILE, FRAGMENT_FILE); // Check if shader program was created successfully if (shaderProgram == 0) { std::cerr << "Failed to create shader programs.\n"; return -1; } // Caulculate model, view, projection matrices glm::mat4 model = glm::mat4(1.0f); glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.0f)); glm::mat4 projection = glm::perspective(glm::radians(45.0f), (SCR_WIDTH / SCR_HEIGHT) * 2, 0.1f, 100.0f); GLuint modelLoc = (unsigned int)glGetUniformLocation(shaderProgram, "model"); GLuint viewLoc = (unsigned int)glGetUniformLocation(shaderProgram, "view"); GLuint projLoc = (unsigned int)glGetUniformLocation(shaderProgram, "projection"); glUseProgram(shaderProgram); glUniformMatrix4fv((int)modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv((int)viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv((int)projLoc, 1, GL_FALSE, glm::value_ptr(projection)); GLint resLoc = glGetUniformLocation(shaderProgram, "u_resolution"); glUniform2f(resLoc, SCR_WIDTH, SCR_HEIGHT); // hardcode for now GLint timeLoc = glGetUniformLocation(shaderProgram, "u_time"); GLint scaleLoc = glGetUniformLocation(shaderProgram, "u_scale"); GLint mouseLoc = glGetUniformLocation(shaderProgram, "u_mouse"); glEnable(GL_MULTISAMPLE); float scale = 1.0f; int frameCount = 0; float mousePos[2] = {0.0f, 0.0f}; // FPS tracking double lastTime = glfwGetTime(); // when we last printed FPS double fps = 0.0; // Render loop while (!glfwWindowShouldClose(window)) { float timeValue = (float)glfwGetTime(); double xpos, ypos; // Get mouse positions glfwGetCursorPos(window, &xpos, &ypos); mousePos[0] = (float)xpos; mousePos[1] = (float)(SCR_HEIGHT - ypos); // Invert y-axis for OpenGL coordinates // Input glfwPollEvents(); // Scroll to zoom in/out if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { scale += 0.01f; if (scale > 10.0f) scale = 10.0f; // Max zoom } if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { scale -= 0.01f; if (scale < 0.1f) scale = 0.1f; // Min zoom } // --- FPS Counter --- double currentTime = glfwGetTime(); double delta = currentTime - lastTime; if (delta >= 1.0) { // print every ~1 second fps = double(frameCount) / delta; std::cout << "FPS: " << fps << " Time: " << timeValue << " Scale: " << scale << " Mouse: (" << mousePos[0] << ", " << mousePos[1] << ")" << std::endl; frameCount = 0; lastTime = currentTime; } glUniform1f(timeLoc, timeValue); glUniform1f(scaleLoc, scale); glUniform2f(mouseLoc, mousePos[0], mousePos[1]); frameCount++; glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glUseProgram(shaderProgram); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteProgram(shaderProgram); glfwDestroyWindow(window); glfwTerminate(); return 0; }