#ifndef SHADER_H #define SHADER_H #include #include #include #include #include #include #include #include class Shader { public: unsigned int ID; // constructor generates the shader on the fly // ------------------------------------------------------------------------ Shader(const char* geometryPath, const char *vertexPath, const char *fragmentPath) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { std::stringstream vShaderStream, fShaderStream, gShaderStream; if(geometryPath){ gShaderFile.open(geometryPath); gShaderStream << gShaderFile.rdbuf(); gShaderFile.close(); geometryCode = gShaderStream.str(); } // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure &e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ: " << e.what() << std::endl; } // shader Program ID = glCreateProgram(); unsigned int vertex, fragment, geometry; // geometry shader if(geometryPath){ const char *gShaderCode = geometryCode.c_str(); geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &gShaderCode, NULL); glCompileShader(geometry); checkCompileErrors(geometry, "GEOMETRY"); glAttachShader(ID, geometry); } // vertex shader const char *vShaderCode = vertexCode.c_str(); vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); checkCompileErrors(vertex, "VERTEX"); glAttachShader(ID, vertex); // fragment Shader const char *fShaderCode = fragmentCode.c_str(); fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); glAttachShader(ID, fragment); // Constructu the program glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); // delete the shaders as they're linked into our program now and no longer necessary glDeleteShader(vertex); glDeleteShader(fragment); if(geometryPath) glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ void use() { glUseProgram(ID); } // utility uniform functions // ------------------------------------------------------------------------ void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } void setVec3(const std::string &name, glm::vec3 value) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), value.x, value.y, value.z); } void setMat4(const std::string &name, glm::mat4 value) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value)); } private: // utility function for checking shader compilation/linking errors. // ------------------------------------------------------------------------ void checkCompileErrors(unsigned int shader, std::string type) { int success; char infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } }; #endif