#include "Shader.hpp" #define GLFW_INCLUDE_NONE #include #ifdef __APPLE__ #include #endif #include #include #include namespace renderer { Shader::Shader () : mID( 0 ) {} Shader::~Shader () { if( mID ) { glDeleteProgram( mID ); } } bool Shader::fromSource ( const std::string& vertexSrc, const std::string& fragmentSrc ) { return compileShader( vertexSrc.c_str(), fragmentSrc.c_str() ); } bool Shader::fromFiles ( const std::string& vertexPath, const std::string& fragmentPath ) { std::string vs = readFile( vertexPath ); std::string fs = readFile( fragmentPath ); if( vs.empty() || fs.empty() ) { return false; } return compileShader( vs.c_str(), fs.c_str() ); } void Shader::use () const { glUseProgram( mID ); } unsigned int Shader::id () const { return mID; } void Shader::setInt ( const std::string& name, int value ) const { glUniform1i( glGetUniformLocation( mID, name.c_str() ), value ); } void Shader::setFloat ( const std::string& name, float value ) const { glUniform1f( glGetUniformLocation( mID, name.c_str() ), value ); } void Shader::setVec3 ( const std::string& name, const glm::vec3& v ) const { glUniform3f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y, v.z ); } void Shader::setVec2 ( const std::string& name, const glm::vec2& v ) const { glUniform2f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y ); } void Shader::setMat4 ( const std::string& name, const glm::mat4& m ) const { glUniformMatrix4fv( glGetUniformLocation( mID, name.c_str() ), 1, GL_FALSE, &m[0][0] ); } bool Shader::compileShader ( const char* vSrc, const char* fSrc ) { GLuint vert = glCreateShader( GL_VERTEX_SHADER ); glShaderSource( vert, 1, &vSrc, nullptr ); glCompileShader( vert ); GLint success = 0; glGetShaderiv( vert, GL_COMPILE_STATUS, &success ); if( success == GL_FALSE ) { GLint len = 0; glGetShaderiv( vert, GL_INFO_LOG_LENGTH, &len ); std::string log( len, '\0' ); glGetShaderInfoLog( vert, len, &len, &log[0] ); std::cerr << "Vertex shader compile error:\n" << log << std::endl; std::cerr << "[Shader] Vertex shader ID = " << vert << std::endl; glDeleteShader( vert ); return false; } GLuint frag = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( frag, 1, &fSrc, nullptr ); glCompileShader( frag ); glGetShaderiv( frag, GL_COMPILE_STATUS, &success ); if( success == GL_FALSE ) { GLint len = 0; glGetShaderiv( frag, GL_INFO_LOG_LENGTH, &len ); std::string log( len, '\0' ); glGetShaderInfoLog( frag, len, &len, &log[0] ); std::cerr << "Fragment shader compile error:\n" << log << std::endl; glDeleteShader( frag ); glDeleteShader( vert ); return false; } mID = glCreateProgram(); glAttachShader( mID, vert ); glAttachShader( mID, frag ); glLinkProgram( mID ); glGetProgramiv( mID, GL_LINK_STATUS, &success ); if( success == GL_FALSE ) { GLint len = 0; glGetProgramiv( mID, GL_INFO_LOG_LENGTH, &len ); std::string log( len, '\0' ); glGetProgramInfoLog( mID, len, &len, &log[0] ); std::cerr << "Shader link error:\n" << log << std::endl; glDeleteProgram( mID ); mID = 0; glDeleteShader( vert ); glDeleteShader( frag ); return false; } glDetachShader( mID, vert ); glDetachShader( mID, frag ); glDeleteShader( vert ); glDeleteShader( frag ); return true; } std::string Shader::readFile ( const std::string& path ) const { std::ifstream in( path ); if( !in ) { return std::string(); } std::stringstream ss; ss << in.rdbuf(); return ss.str(); } } // namespace renderer