diff --git a/source/GfxDriver/OpenGL/OpenGLShaderProgram.cpp b/source/GfxDriver/OpenGL/OpenGLShaderProgram.cpp new file mode 100644 index 0000000..f9bb0ad --- /dev/null +++ b/source/GfxDriver/OpenGL/OpenGLShaderProgram.cpp @@ -0,0 +1,186 @@ + +#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 diff --git a/source/GfxDriver/OpenGL/OpenGLShaderProgram.h b/source/GfxDriver/OpenGL/OpenGLShaderProgram.h new file mode 100644 index 0000000..4d8c650 --- /dev/null +++ b/source/GfxDriver/OpenGL/OpenGLShaderProgram.h @@ -0,0 +1,70 @@ + +#ifndef SPECTRE_GFXDRIVER_OPENGL_OPENGLSHADERPROGRAM_H +#define SPECTRE_GFXDRIVER_OPENGL_OPENGLSHADERPROGRAM_H + +#include +#include + +namespace sp { + +class OpenGLShaderProgram : public ShaderProgram +{ +public: + OpenGLShaderProgram(); + virtual ~OpenGLShaderProgram(); + + // Load a shader from memory. + virtual bool loadFromMemory(const std::string& source, ShaderType type); + + // Link the program. + virtual bool link(); + + // Enable this shader + // All shader operations after this call will affect this shader. + virtual void enable() const; + + // Disable this shader + // Operations will no longer affect this shader after this call. + virtual void disable() const; + + // --------------------- + // Variables. + // --------------------- + + virtual bool setMVPMatrix(const Matrix4f& matrix); + + // --------------------- + // General Variables. + // --------------------- + + virtual bool setAttribute(const std::string& name, float value) const; + + virtual bool setAttribute(const std::string& name, const Matrix4f& matrix) const; + + virtual bool setUniform(const std::string& name, const Matrix4f& matrix) const; + + virtual bool setUniform(const std::string& name, const Color& color) const; + +protected : + + // Compile a shader. + bool compileShader(GLuint id); + + // Attach shader to program. + bool attachShader(GLuint id); + + bool getAttribLoc(const std::string& name, int& loc) const; + + bool getUniformLoc(const std::string& name, int& loc) const; + + std::string fetchErrorLog() const; + +protected : + + // Program ID + GLuint m_id; +}; + +} // namespace sp + +#endif /* SPECTRE_GFXDRIVER_OPENGL_OPENGLSHADERPROGRAM_H */