Skip to content
Snippets Groups Projects
Select Git revision
  • f9ada3d1381875e72c41484b8d2ed7b64c447a26
  • main default protected
  • NewGraphicSystem
  • LayeredRendering
4 results

Program.cpp

Blame
  • Théau's avatar
    BATON Theau authored
    ad9344f3
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    Program.cpp 7.20 KiB
    #include "Program.hpp"
    
    #include <glm/gtc/type_ptr.hpp>
    #include <glm/mat4x4.hpp>
    
    #include "../../errors/Shader_Error.hpp"
    
    #include <iostream>
    #include <list>
    
    namespace megu {
        Program::Program() 
        : _id(0), _usable(false), _attached(NONE) {
            this->_id = glCreateProgram();
        }
    
        Program::~Program() {
            glDeleteProgram(this->_id);
        }
    
        const uint8_t Program::Categorie(const Source::Categorie categorie) {
            switch (categorie) {
                case Source::Categorie::VERTEX:
                    return Bit_Categorie::VERTEX;
    
                case Source::Categorie::FRAGMENT:
                    return Bit_Categorie::FRAGMENT;
    
                case Source::Categorie::GEOMETRY:
                    return Bit_Categorie::GEOMETRY;
                
                case Source::Categorie::TESS_CONTROL:
                    return Bit_Categorie::TESS_CONTROL;
    
                case Source::Categorie::TESS_EVALUATION:
                    return Bit_Categorie::TESS_CONTROL;
    
                case Source::Categorie::COMPUTE:
                    return Bit_Categorie::COMPUTE;
            
                default:
                    return Bit_Categorie::NONE;
            }
        }
    
        void Program::attach(const Source & source) {
            if(source.usable()) {
                glAttachShader(this->_id, source.id());
                this->_attached |= Program::Categorie(source.categorie());
            }
        }
    
        void Program::dettach(const Source & source) {
            glDetachShader(this->_id, source.id());
            this->_attached = this->_attached & ~Program::Categorie(source.categorie());
            this->_usable = ((this->_attached & Bit_Categorie::VERTEX) != 0 && (this->_attached & Bit_Categorie::FRAGMENT) != 0);
        }
    
        void Program::link() {
            this->_usable = ((this->_attached & Bit_Categorie::VERTEX) != 0 && (this->_attached & Bit_Categorie::FRAGMENT) != 0);
            if(this->_usable) {
                glLinkProgram(this->_id);
    
                int success;
                char infoLog[512];
    
                glGetProgramiv(this->_id, GL_LINK_STATUS, &success);
                if(!success) {
                    this->_usable = false;
                    glGetProgramInfoLog(this->_id, 512, NULL, infoLog);
                    throw error::shader_error(infoLog);
                }   
    
                GLint count;
                glGetProgramiv(this->_id, GL_ACTIVE_UNIFORMS, &count);
    
                for(size_t i = 0; i < count; ++i) {
                    GLint length, size;
                    GLenum type;
                    GLchar name[64];
                    glGetActiveUniform(this->_id, static_cast<GLuint>(i), 64, &length, &size, &type, name);
                    
                    std::string var_name(name);
                    this->_locations[var_name.substr(0, var_name.find("["))] = glGetUniformLocation(this->_id, name);
                }
            }
            else {
                if((this->_attached & Bit_Categorie::VERTEX) == 0) {
                    throw error::shader_error("Missing Vertex Source attached to Program");
                }
                else if((this->_attached & Bit_Categorie::FRAGMENT) == 0) {
                    throw error::shader_error("Missing Fragment Source attached to Program");
                }
            }
        }
    
        void Program::use() const {
            if(this->_usable) {
                glUseProgram(this->_id);
            }
        }
    
        void Program::kill() {
            this->_usable = false;
            this->_attached = Bit_Categorie::NONE;
            this->_id = glCreateProgram();
        }
    
        void Program::setUniform(const std::string & name, GLint value) const {
            glUniform1i(this->_locations.at(name), value);
        }
    
        void Program::setUniform(const std::string & name, GLuint value) const {
            glUniform1ui(this->_locations.at(name), value);
        }
    
        void Program::setUniform(const std::string & name, GLfloat value) const {
            glUniform1f(this->_locations.at(name), value);
        }
    
        void Program::setUniform(const std::string & name, GLdouble value) const {
            glUniform1d(this->_locations.at(name), value);
        }
    
        void Program::setUniform(const std::string & name, GLchar value) const {
            this->setUniform(name, static_cast<GLint>(value));
        }
    
        void Program::setUniform(const std::string & name, const glm::mat4 & value) const {
            glUniformMatrix4fv(this->_locations.at(name), 1, GL_FALSE, &value[0][0]);
        }
    
        void Program::setUniform(const std::string & name, const glm::vec2 & value) const {
            glUniform2f(this->_locations.at(name), value.x, value.y);
        }
    
        void Program::setUniform(const std::string & name, const glm::vec3 & value) const {
            glUniform3f(this->_locations.at(name), value.x, value.y, value.z);
        }
    
        void Program::setUniform(const std::string & name, const glm::vec<3, uint32_t> & value) const {
            glUniform3ui(this->_locations.at(name), value.x, value.y, value.z);
        }
    
        void Program::setUniform(const std::string & name, const glm::vec<3, int32_t> & value) const {
            glUniform3i(this->_locations.at(name), value.x, value.y, value.z);
        }
    
        void Program::setUniform(const std::string & name, const glm::vec4 & value) const {
            glUniform4f(this->_locations.at(name), value.x, value.y, value.z, value.w);
        }
    
        void Program::setUniform(const std::string & name, const std::vector<GLint> & value) const {
            glUniform1iv(this->_locations.at(name), static_cast<GLsizei>(value.size()), value.data());
        }
    
        void Program::setUniform(const std::string & name, const std::vector<GLuint> & value) const {
            glUniform1uiv(this->_locations.at(name), static_cast<GLsizei>(value.size()), value.data());
        }
    
        void Program::setUniform(const std::string & name, const std::vector<GLfloat> & value) const {
            glUniform1fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), value.data());
        }
    
        void Program::setUniform(const std::string & name, const std::vector<glm::vec2> & value) const {
            glUniform2fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), (float *)value.data());
        }
    
        void Program::setUniform(const std::string & name, const std::vector<glm::vec4> & value) const {
            glUniform4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), (float *)value.data());
        }
    
        void Program::setUniform(const std::string & name, const std::vector<glm::mat4> & value) const {
            glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value[0]));
        }
    
        void Program::setUniform(const std::string & name, const std::vector<std::reference_wrapper<const glm::mat4>> & value) const {
            glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value[0].get()));
        }
    
        void Program::setUniform(const std::string & name, const std::set<std::reference_wrapper<const glm::mat4>> & value) const {
            glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value.begin()->get()));
        }
    
        void Program::setUniform(const std::string & name, const void * data, size_t size, GLenum type) const {
            switch (type) {
                case GL_FLOAT:
                    glUniform4fv(this->_locations.at(name), static_cast<GLsizei>(size), static_cast<const float*>(data));
                    break;
                
                default:
                    break;
            }
        }
    }