// glad and GLFW #include #include // glm math #include #include #include #include #include #include #include #include #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; // Shader loader helper std::string loadShaderSource(const std::string& filepath) { std::ifstream file(filepath); if (!file.is_open()) { std::cerr << "Failed to open shader file: " << filepath << std::endl; return ""; } std::stringstream buffer; std::cout << "Loaded " << filepath << " successfully!\n"; buffer << file.rdbuf(); return buffer.str(); } GLuint compileShader(GLenum type, const std::string& source) { GLuint shader = glCreateShader(type); const char* src = source.c_str(); glShaderSource(shader, 1, &src, nullptr); glCompileShader(shader); int success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { char infoLog[512]; glGetShaderInfoLog(shader, 512, nullptr, infoLog); std::cerr << "Shader compilation failed:\n" << infoLog << std::endl; exit(10); } return shader; } GLuint createShaderProgram(const std::string& vertexPath, const std::string& fragmentPath) { std::string vertexSrc = loadShaderSource(vertexPath); std::string fragmentSrc = loadShaderSource(fragmentPath); GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSrc); GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSrc); GLuint program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); int success; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { char infoLog[512]; glGetProgramInfoLog(program, 512, nullptr, infoLog); std::cerr << "Shader linking failed:\n" << infoLog << std::endl; exit(11); } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return program; } GLuint createComputeProgram(const std::string& computePath) { std::string computeSrc = loadShaderSource(computePath); GLuint computeShader = compileShader(GL_COMPUTE_SHADER, computeSrc); GLuint program = glCreateProgram(); glAttachShader(program, computeShader); glLinkProgram(program); int success; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { char infoLog[512]; glGetProgramInfoLog(program, 512, nullptr, infoLog); std::cerr << "Compute shader linking failed:\n" << infoLog << std::endl;; } glDeleteShader(computeShader); return program; } int main() { // 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, 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; }