diff --git a/src/gui/GLProgram.cc b/src/gui/GLProgram.cc new file mode 100644 index 0000000..e151a65 --- /dev/null +++ b/src/gui/GLProgram.cc @@ -0,0 +1,85 @@ +#include "GLProgram.h" +#include +#include + +using namespace std; + +namespace jes +{ + GLProgram::GLProgram() + { + m_id = glCreateProgram(); + if (m_id == 0u) + { + cerr << "Error allocating GL program object" << endl; + } + } + + GLProgram::~GLProgram() + { + if (m_id > 0u) + { + glDeleteProgram(m_id); + } + } + + GLProgram & GLProgram::attach_shader(GLShaderRef shader) + { + if (m_id > 0u) + { + glAttachShader(m_id, shader->get_id()); + } + return *this; + } + + GLProgram & GLProgram::bind_attribute(const char * attribute, GLuint index) + { + if (m_id > 0u) + { + glBindAttribLocation(m_id, index, attribute); + } + return *this; + } + + bool GLProgram::link() + { + if (m_id == 0u) + return false; + + glLinkProgram(m_id); + + GLint link_status; + glGetProgramiv(m_id, GL_LINK_STATUS, &link_status); + if (link_status != GL_TRUE) + { + GLint log_length; + glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) + { + char *log = new char[log_length]; + glGetProgramInfoLog(m_id, log_length, &log_length, log); + cerr << "Program log:" << endl << log << endl; + delete[] log; + } + return false; + } + + return true; + } + + GLint GLProgram::operator[](const std::string & uniform_name) + { + if (m_id > 0u) + { + auto it = m_uniforms.find(uniform_name); + if (it != m_uniforms.end()) + { + return it->second; + } + GLint loc = glGetUniformLocation(m_id, uniform_name.c_str()); + m_uniforms[uniform_name] = loc; + return loc; + } + return -1; + } +} diff --git a/src/gui/GLProgram.h b/src/gui/GLProgram.h new file mode 100644 index 0000000..2bb7d01 --- /dev/null +++ b/src/gui/GLProgram.h @@ -0,0 +1,30 @@ +#ifndef GLPROGRAM_H +#define GLPROGRAM_H + +#include "jes/Ref.h" +#include "GLShader.h" +#include +#include +#include + +namespace jes +{ + class GLProgram + { + public: + GLProgram(); + ~GLProgram(); + GLProgram & attach_shader(GLShaderRef shader); + GLProgram & bind_attribute(const char * attribute, GLuint index); + bool link(); + GLuint get_id() { return m_id; } + void use() { glUseProgram(m_id); } + GLint operator[](const std::string & uniform_name); + protected: + GLuint m_id; + std::map m_uniforms; + }; + typedef Ref GLProgramRef; +} + +#endif diff --git a/src/gui/GLShader.cc b/src/gui/GLShader.cc new file mode 100644 index 0000000..e540694 --- /dev/null +++ b/src/gui/GLShader.cc @@ -0,0 +1,58 @@ +#include "GLShader.h" +#include + +using namespace std; + +namespace jes +{ + GLShader::~GLShader() + { + if (m_id > 0) + { + glDeleteShader(m_id); + } + } + + bool GLShader::create(GLenum shader_type, const char *source, size_t size) + { + GLint status; + + m_id = glCreateShader(shader_type); + if (m_id > 0) + { + GLint length = size; + glShaderSource(m_id, 1, &source, &length); + + glCompileShader(m_id); + + glGetShaderiv(m_id, GL_COMPILE_STATUS, &status); + if (status == GL_TRUE) + { + return true; + } + + GLint log_length; + cerr << "Error compiling "; + switch (shader_type) + { + case GL_VERTEX_SHADER: + cerr << "vertex"; + break; + case GL_FRAGMENT_SHADER: + cerr << "fragment"; + break; + } + cerr << " shader" << endl; + glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) + { + char * log = new char[log_length]; + glGetShaderInfoLog(m_id, log_length, &log_length, log); + cerr << "Shader Log:" << endl << log << endl; + delete[] log; + } + glDeleteShader(m_id); + } + return false; + } +} diff --git a/src/gui/GLShader.h b/src/gui/GLShader.h new file mode 100644 index 0000000..6ee8770 --- /dev/null +++ b/src/gui/GLShader.h @@ -0,0 +1,23 @@ +#ifndef GLSHADER_H +#define GLSHADER_H + +#include "jes/Ref.h" +#include "gl3w.h" + +namespace jes +{ + class GLShader + { + public: + GLShader() { m_id = 0u; } + ~GLShader(); + bool create(GLenum shader_type, const char *source, size_t size); + GLuint get_id() { return m_id; } + bool valid() { return m_id > 0; } + protected: + GLuint m_id; + }; + typedef Ref GLShaderRef; +} + +#endif