#include "gfx.hpp" #include #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" #include "io.hpp" float aspect_; // 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); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); *window = glfwCreateWindow(640, 480, title.c_str(), NULL, NULL); if (!window) { glfwTerminate(); std::cerr << "Failed to open window with GLFW" << std::endl; return -1; } glfwSetWindowSizeCallback(*window, windowSizeCallback); 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; } void windowSizeCallback(GLFWwindow* window, int width, int height) { aspect_ = (float)width / (float)height; glViewport(0, 0, width, height); } 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) { glm::mat4 model = glm::mat4(1.0); GLint modelLocation = getShaderUniformLocation(shaderProgram, "_Model"); glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]); } void updateViewMatrix(GLuint shaderProgram, float time) { glm::mat4 view = glm::mat4(1.0); // Rotation constexpr float angle = glm::radians(10.0); glm::vec3 axis = glm::vec3(0.0, 1.0, 0.0); view = glm::rotate(view, angle * time, axis); 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); updateViewMatrix(shaderProgram, time); } 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; }