#include "lopenglprogram.h" #include LOpenGLShader::LOpenGLShader(LOpenGLShader::ShaderType type) : shaderType_(type), compiled_(false) {} LOpenGLShader::~LOpenGLShader() { if (shaderId_ != 0) { glDeleteShader(shaderId_); } } bool LOpenGLShader::compileShaderFromSource(const char *source) { if (!source || compiled_) { return false; } switch (shaderType_) { case Vertex: shaderId_ = glCreateShader(GL_VERTEX_SHADER); break; case Fragment: shaderId_ = glCreateShader(GL_FRAGMENT_SHADER); break; default: return false; } glShaderSource(shaderId_, 1, &source, NULL); glCompileShader(shaderId_); int success = 0; glGetShaderiv(shaderId_, GL_COMPILE_STATUS, &success); if (!success) { char infoLog[512]; glGetShaderInfoLog(shaderId_, 512, NULL, infoLog); shaderLog_ = std::string(infoLog); return false; } compiled_ = true; return true; } bool LOpenGLShader::compileShaderFromSource(const std::string &source) { if (source.empty() || compiled_) { return false; } switch (shaderType_) { case Vertex: shaderId_ = glCreateShader(GL_VERTEX_SHADER); break; case Fragment: shaderId_ = glCreateShader(GL_FRAGMENT_SHADER); break; default: return false; } auto source_ch = source.c_str(); glShaderSource(shaderId_, 1, &source_ch, nullptr); glCompileShader(shaderId_); int success = 0; glGetShaderiv(shaderId_, GL_COMPILE_STATUS, &success); if (!success) { char infoLog[512]; glGetShaderInfoLog(shaderId_, 512, nullptr, infoLog); shaderLog_ = std::string(infoLog); return false; } compiled_ = true; return true; } bool LOpenGLShader::compileShaderFromFile(const std::string &path) { std::string shaderCode; std::fstream shaderFile; std::stringstream shaderStream; shaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { shaderFile.open(path); shaderStream << shaderFile.rdbuf(); shaderFile.close(); shaderCode = shaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; } if (shaderCode.empty() || compiled_) { return false; } switch (shaderType_) { case Vertex: shaderId_ = glCreateShader(GL_VERTEX_SHADER); break; case Fragment: shaderId_ = glCreateShader(GL_FRAGMENT_SHADER); break; default: return false; } auto source_ch = shaderCode.c_str(); glShaderSource(shaderId_, 1, &source_ch, NULL); glCompileShader(shaderId_); int success = 0; glGetShaderiv(shaderId_, GL_COMPILE_STATUS, &success); if (!success) { char infoLog[512]; glGetShaderInfoLog(shaderId_, 512, NULL, infoLog); shaderLog_ = std::string(infoLog); return false; } compiled_ = true; return true; } LOpenGLProgram::LOpenGLProgram() : linked_(false) { Create(); } LOpenGLProgram::~LOpenGLProgram() { glDeleteProgram(programId_); } void LOpenGLProgram::Create() { programId_ = glCreateProgram(); } bool LOpenGLProgram::Link() const { if (!created_ || linked_ || shaderList_.empty()) { return false; } glLinkProgram(programId_); return true; } void LOpenGLProgram::Use() const { if (!linked_) return; glUseProgram(programId_); } void LOpenGLProgram::setUniformValue(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(programId_, name.c_str()), value); } void LOpenGLProgram::setUniformValue(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(programId_, name.c_str()), value); } void LOpenGLProgram::setUniformValue(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(programId_, name.c_str()), static_cast(value)); } void LOpenGLProgram::setUniformValue(const std::string &name, glm::vec3 value) const { glUniform3fv(glGetUniformLocation(programId_, name.c_str()), 1, &value[0]); } void LOpenGLProgram::setUniformValue(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(programId_, name.c_str()), x, y, z); } void LOpenGLProgram::setUniformValue(const std::string &name, glm::mat4 value) const { glUniform4fv(glGetUniformLocation(programId_, name.c_str()), 1, &value[0][0]); } bool LOpenGLProgram::addShader(std::unique_ptr shader) { if (!shader || !shader->Compiled()) { return false; } if (!created_) { return false; } glAttachShader(programId_, shader->shaderId_); shaderList_.push_back(std::move(shader)); return true; } void LOpenGLProgram::setUniformValue(const std::string &name, glm::vec2 value) const { glUniform2fv(glGetUniformLocation(programId_, name.c_str()), 1, &value[0]); } void LOpenGLProgram::removeShader(GLuint id) { for (auto ite = shaderList_.begin(); ite != shaderList_.end(); ++ite) { if ((*ite)->shaderId_ == id) { glDetachShader(programId_, id); shaderList_.erase(ite); } } }