#include "OpenGLShaderProgram.h" namespace sp { OpenGLShaderProgram::OpenGLShaderProgram() { m_extension = "glsl"; m_id = glCreateProgram(); } OpenGLShaderProgram::~OpenGLShaderProgram() { if (m_id > 0) { glDeleteProgram(m_id); } } bool OpenGLShaderProgram::loadFromMemory(const std::string& source, ShaderType type) { const char *s = source.c_str(); GLuint shader_id = glCreateShader(type == ShaderType::Vertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); glShaderSource(shader_id, 1, &s, NULL); if (!compileShader(shader_id)) { return false; } return attachShader(shader_id); } bool OpenGLShaderProgram::link() { GLint status; glLinkProgram(m_id); // Query OpenGL for link status. glGetProgramiv(m_id, GL_LINK_STATUS, &status); m_linked = status == GL_TRUE; if (!m_linked) { m_error = fetchErrorLog(); } return m_linked; } // Enable this shader // All shader operations after this call will affect this shader. void OpenGLShaderProgram::enable() const { glUseProgram(m_id); } // Disable this shader // Operations will no longer affect this shader after this call. void OpenGLShaderProgram::disable() const { glUseProgram(0); } // --------------------- // Variables. // --------------------- bool OpenGLShaderProgram::setMVPMatrix(const Matrix4f& matrix) { return setUniform("u_MVP", matrix); } // --------------------- // General Variables. // --------------------- bool OpenGLShaderProgram::setAttribute(const std::string& name, float value) const { int loc; if (getAttribLoc(name, loc)) { glVertexAttrib1f(loc, value); return true; } return false; } bool OpenGLShaderProgram::setAttribute(const std::string& name, const Matrix4f& matrix) const { int loc; if (getAttribLoc(name, loc)) { glVertexAttrib4fv(loc, matrix.e); return true; } return false; } bool OpenGLShaderProgram::setUniform(const std::string& name, const Matrix4f& matrix) const { int loc; if (getUniformLoc(name, loc)) { glUniformMatrix4fv(loc, 1, GL_FALSE, matrix.e); return true; } return false; } bool OpenGLShaderProgram::setUniform(const std::string& name, const Color& color) const { int loc; if (getUniformLoc(name, loc)) { Vector4f c = color.toRGBAf(); glUniform4f(loc, c.x, c.y, c.z, c.w); return true; } return false; } bool OpenGLShaderProgram::getAttribLoc(const std::string& name, int& loc) const { loc = glGetAttribLocation(m_id, name.c_str()); if (loc < 0) { m_error = "Attribute variable '" + name + "' was not found in shader."; return false; } return true; } bool OpenGLShaderProgram::getUniformLoc(const std::string& name, int& loc) const { loc = glGetUniformLocation(m_id, name.c_str()); if (loc < 0) { m_error = std::string("Uniform variable '" + name + "' was not found in shader."); return false; } return true; } std::string OpenGLShaderProgram::fetchErrorLog() const { GLchar buf[4096] = { '\0' }; glGetProgramInfoLog(m_id, sizeof(buf), NULL, buf); return std::string(buf); } bool OpenGLShaderProgram::compileShader(GLuint id) { glCompileShader(id); GLenum err; // Query OpenGL for status. GLint status; glGetShaderiv(id, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLchar buf[4096] = { '\0' }; glGetShaderInfoLog(id, sizeof(buf), NULL, buf); m_error = std::string(buf); return false; } return true; } bool OpenGLShaderProgram::attachShader(GLuint id) { GLenum err; glAttachShader(m_id, id); err = glGetError(); if (err == GL_INVALID_VALUE) { m_error = "Invalid Value"; return false; } else if (err == GL_INVALID_OPERATION) { m_error = "Invalid operation"; return false; } else if (err != GL_NO_ERROR) { m_error = "Unkown Error"; return false; } return true; } } // namespace sp