#include #include #include #include #include // glad must be loaded before GLFW #include "graphics.hpp" #include "main.hpp" #include using namespace std; ShaderProgram::Base ShaderProgram::baseFromName(string name) { string lname = name; boost::algorithm::to_lower(lname); // yes, cpp needs a library to do this. // can't do a switch over strings in cpp. if (lname == "empty") { return Empty; } if (lname == "triangle") { return Triangle; } else { BOOST_LOG_TRIVIAL(fatal) << "unknown base program \"" << name << "\""; exit(EXIT_USAGE); } } /* class ShaderProgram Implementations */ string ShaderProgram::baseName() { /* BOOST_LOG_TRIVIAL(debug) << "this->base: " << this->base << " Base::Empty: " << Base::Empty << " Base::Triangle: " << Base::Triangle; */ switch (this->base) { case ShaderProgram::Base::Empty: return "Empty"; case ShaderProgram::Base::Triangle: return "Triangle"; default: // this should never occur, as the switch case should cover all variants. throw std::runtime_error("Undefined base Program"); } } ShaderProgram::ShaderProgram(Base base, char **vertexSource, char **fragSource) { this->base = base; BOOST_LOG_TRIVIAL(info) << "With base program \"" << this->baseName() << "\""; // NOTE: char arrays and char pointers are not actually the same. // glShaderSource requires a char[] as it appears. We pass the // variable by reference to avoid duplication in memory. BOOST_LOG_TRIVIAL(trace) << "creating empty shaders"; this->vertex = glCreateShader(GL_VERTEX_SHADER); this->frag = glCreateShader(GL_FRAGMENT_SHADER); BOOST_LOG_TRIVIAL(trace) << "loading vertex shader"; glShaderSource(this->vertex, 1, vertexSource, NULL); BOOST_LOG_TRIVIAL(trace) << "compiling vertex shader"; glCompileShader(this->vertex); BOOST_LOG_TRIVIAL(trace) << "loading fragments shader"; glShaderSource(this->frag, 2, fragSource, NULL); BOOST_LOG_TRIVIAL(trace) << "compiling fragments shader"; glCompileShader(this->frag); } /** runs for every frame * * will be called in `mainWindow`. * * FIXME: dont run the switch case every frame. */ int ShaderProgram::run() { switch (this->base) { case Empty: // same as default default: glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); break; } return 0; } /* functions that run out graphics stuff */ void framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); } GLFWwindow *initGl() { /* graphics stuff */ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); GLFWwindow *window = glfwCreateWindow(800, 600, "Shader Loader", NULL, NULL); if (window == NULL) { printf("Failed to create GLFW window\n"); glfwTerminate(); exit(EXIT_GL); } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { printf("Failed to initialize GLAD\n"); exit(EXIT_GL); } glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); return window; } int mainWindow(ShaderProgram *shaderProgram, GLFWwindow *window) { int result = 0; BOOST_LOG_TRIVIAL(trace) << "Entering window loop"; while (!glfwWindowShouldClose(window)) { processInput(window); shaderProgram->run(); glfwSwapBuffers(window); glfwPollEvents(); } BOOST_LOG_TRIVIAL(trace) << "Left window loop"; glfwTerminate(); return result; } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); }