#include #include #include #include OpenGlShaderProgram::OpenGlShaderProgram(std::string vertex_file, std::string geometry_file, std::string fragment_file) { this->vertex_file = vertex_file; this->geometry_file = geometry_file; this->fragment_file = fragment_file; this->compiled = false; this->setProjectionView(glm::mat4(1.0f), glm::mat4(1.0f)); } OpenGlShaderProgram::~OpenGlShaderProgram() { this->unload(); } void OpenGlShaderProgram::setProjectionView(const glm::mat4 &projection, const glm::mat4 &view) { this->proj = projection; this->view = view; this->proj_view = projection * view; } glm::mat4 OpenGlShaderProgram::getProjection() { return this->proj; } glm::mat4 OpenGlShaderProgram::getView() { return this->view; } std::string load_shader_program_from_file(std::string &file_name) { std::ifstream ifs(file_name); std::string file_content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); return file_content; } int OpenGlShaderProgram::compile() { int ret_code = 0; int success; char info_log[512]; unsigned int vertex_shader, geometry_shader, fragment_shader; bool vertex_b = false, geo_b = false, frag_b = false; std::string src_code; const char *c_string; if (this->compiled) { glDeleteProgram(shader_program); this->compiled = false; } this->shader_program = glCreateProgram(); if (!vertex_file.empty()) { vertex_b = true; src_code = load_shader_program_from_file(this->vertex_file); c_string = src_code.c_str(); /* Compile the vertex shader */ vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, &c_string, NULL); glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertex_shader, 512, NULL, info_log); printf("Error in vertex shader: %s\n", info_log); ret_code = -1; goto delete_vertex; } glAttachShader(this->shader_program, vertex_shader); } else printf("Empty\n"); if (!this->geometry_file.empty()) { geo_b = true; src_code = load_shader_program_from_file(this->geometry_file); c_string = src_code.c_str(); /* Compile the vertex shader */ geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry_shader, 1, &c_string, NULL); glCompileShader(geometry_shader); glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(geometry_shader, 512, NULL, info_log); fprintf(stderr, "%s\n", info_log); ret_code = -1; goto delete_geo; } glAttachShader(this->shader_program, geometry_shader); } if (!this->fragment_file.empty()) { frag_b = true; src_code = load_shader_program_from_file(this->fragment_file); c_string = src_code.c_str(); /* Compile the vertex shader */ fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, &c_string, NULL); glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragment_shader, 512, NULL, info_log); fprintf(stderr, "%s\n", info_log); ret_code = -1; goto delete_frag; } glAttachShader(this->shader_program, fragment_shader); } glLinkProgram(this->shader_program); glGetShaderiv(this->shader_program, GL_LINK_STATUS, &success); if (!success) { glGetShaderInfoLog(this->shader_program, 512, NULL, info_log); printf("%s\n", info_log); ret_code = -2; } this->compiled = true; delete_frag: if (frag_b) glDeleteShader(fragment_shader); delete_geo: if (geo_b) glDeleteShader(geometry_shader); delete_vertex: if (vertex_b) glDeleteShader(vertex_shader); if (ret_code) { this->compiled = false; glDeleteProgram(this->shader_program); this->shader_program = 0; } return ret_code; } void OpenGlShaderProgram::unload() { if (this->compiled) { glDeleteProgram(this->shader_program); } this->compiled = false; } int OpenGlShaderProgram::use() { if (!this->compiled) return -1; glUseProgram(this->shader_program); this->setUniformMat4("projection_view_matrix", this->proj_view); return 0; } void OpenGlShaderProgram::setUniformFloat(const std::string &uniform, float value) { int loc = this->getUniformLoc(uniform); if (loc >= 0) { glUniform1f(loc, value); } } void OpenGlShaderProgram::setUniformVec2(const std::string &uniform, float *vector) { int loc = this->getUniformLoc(uniform); if (loc >= 0) { glUniform2fv(loc, 1, vector); } } void OpenGlShaderProgram::setUniformMat4(const std::string &uniform, const glm::mat4 &matrix) { int loc = this->getUniformLoc(uniform); if (loc >= 0) { glUniformMatrix4fv(loc, 1, GL_FALSE, &matrix[0][0]); } } int OpenGlShaderProgram::getUniformLoc(const std::string &uniform) { if (!this->compiled) return -1; return glGetUniformLocation(this->shader_program, uniform.c_str()); }