#include "Shader.h" namespace NB{ ShaderError::ShaderError( const std::string& msg, const char* shad, const std::string& file, int line ) : std::runtime_error(formatString(msg, shad, file, line)) {} std::string ShaderError::formatString( const std::string& msg, const char* shad, const std::string& file, int line ) { std::string ret = ""; if (file != "") { ret += "In file " + file; if (line >= 0) { ret += " at line " + std::to_string(line); } ret += ":\n\t"; } ret += msg; if (shad != nullptr) { ret += " with shader error: " + std::string(shad); } return ret; } Shader::Shader(const char* vertexPath, const char* fragmentPath) { std::string vertexCode, fragmentCode; std::ifstream vShaderFile, fShaderFile; vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); vShaderFile.close(); fShaderFile.close(); vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure e) { throw ShaderError("Could not read Shader files."); } const char* vShaderCode = vertexCode.c_str(); const char* fShaderCode = fragmentCode.c_str(); unsigned int vertex, fragment; int success; char infoLog[512]; vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); throw ShaderError("Could not compile Vertex shader", infoLog); } fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); throw ShaderError("Could not compile Fragment shader", infoLog); } id = glCreateProgram(); glAttachShader(id, vertex); glAttachShader(id, fragment); glLinkProgram(id); glGetProgramiv(id, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(id, 512, NULL, infoLog); throw ShaderError("Could not link shader program", infoLog); } glDeleteShader(vertex); glDeleteShader(fragment); } Shader::Shader() { id = 0x0; } Shader::Shader(const Shader& cpy_shader) { id = cpy_shader.id; } Shader& Shader::operator=(const Shader& cpy_shader) { id = cpy_shader.id; return *this; } void Shader::use() const{ glUseProgram(id); } void Shader::setBool(const std::string& name, bool value) const { glUniform1i(glGetUniformLocation(id, name.c_str()), (int)value); } void Shader::setInt(const std::string& name, int value) const { glUniform1i(glGetUniformLocation(id, name.c_str()), (int)value); } void Shader::setFloat(const std::string& name, float value) const { glUniform1f(glGetUniformLocation(id, name.c_str()), (int)value); } void Shader::setMat4(const std::string& name, glm::mat4& value) const { glUniformMatrix4fv(glGetUniformLocation(id, name.c_str()), 1, GL_FALSE, glm::value_ptr(value)); } }