Select Git revision
Program.cpp

BATON Theau authored
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;
}
}
}