#include "gfx.hpp" #include #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" #include "io.hpp" const int WIDTH = 640; const int HEIGHT = 480; const float ASPECT = (float)WIDTH / (float)HEIGHT; // Initialize GLFW, OpenGL and GLEW, open a window and make it the current context. // Returns 0 for success, and -1 for any failure. // Failures are printed to STDERR. int initGraphics(GLFWwindow** window, const std::string& title) { // Set up GLFW, OpenGL and GLEW. if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return -1; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); *window = glfwCreateWindow(WIDTH, HEIGHT, title.c_str(), NULL, NULL); if (!window) { glfwTerminate(); std::cerr << "Failed to open window with GLFW" << std::endl; return -1; } glfwMakeContextCurrent(*window); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cerr << "Failed to initialize GLEW" << std::endl; return -1; } glEnable(GL_DEPTH_TEST); return 0; } GLuint compileShader(const std::string& shaderPath, GLenum shaderType) { GLuint shader; GLint success; std::string shaderSource = readFile(shaderPath); const char* source = shaderSource.c_str(); shader = glCreateShader(shaderType); glShaderSource(shader, 1, &source, NULL); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { GLchar infoLog[512]; glGetShaderInfoLog(shader, 512, NULL, infoLog); std::cerr << "shader compilation failed" << std::endl << infoLog << std::endl; } return shader; } GLuint compileShaderProgram(const std::string& fragShaderPath) { GLuint vertShader = compileShader("./vert.glsl", GL_VERTEX_SHADER); GLuint fragShader = compileShader(fragShaderPath, GL_FRAGMENT_SHADER); GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertShader); glAttachShader(shaderProgram, fragShader); glLinkProgram(shaderProgram); GLint success; GLchar infoLog[512]; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); std::cerr << "shader linking failed" << std::endl << infoLog << std::endl; exit(-1); } // We no longer need the individual shaders glDeleteShader(vertShader); glDeleteShader(fragShader); return shaderProgram; } void updateProjectionMatrix(GLuint shaderProgram) { float left = -ASPECT, right = ASPECT, bottom = -1.0, top = 1.0, near = -1.0, far = 1.0; glm::mat4 projection = glm::ortho(left, right, bottom, top, near, far); GLint projectionLocation = getShaderUniformLocation(shaderProgram, "_Projection"); glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, &projection[0][0]); } void updateModelMatrix(GLuint shaderProgram, float time) { constexpr float angle = glm::radians(10.0); glm::vec3 axis = glm::vec3(0.0, 1.0, 0.0); glm::mat4 model = glm::rotate(glm::mat4(1.0), angle * time, axis); GLint modelLocation = getShaderUniformLocation(shaderProgram, "_Model"); glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]); } void updateViewMatrix(GLuint shaderProgram) { glm::mat4 view = glm::mat4(1.0); GLint viewLocation = getShaderUniformLocation(shaderProgram, "_View"); glUniformMatrix4fv(viewLocation, 1, GL_FALSE, &view[0][0]); } void updateModelViewProjectionMatrix(GLuint shaderProgram, float time) { // Calculate matrices updateProjectionMatrix(shaderProgram); updateModelMatrix(shaderProgram, time); updateViewMatrix(shaderProgram); } GLint getShaderUniformLocation(GLuint shaderProgram, const std::string& uniformName) { GLint location = glGetUniformLocation(shaderProgram, uniformName.c_str()); if (location == -1) { std::cerr << "Could not find uniform: " << uniformName << std::endl; return -1; } return location; }