From f8af892c0d7a0e6b727778660c33f348f7ef81fd Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 11 Jun 2015 00:01:59 -0400 Subject: [PATCH] initial glcxx development --- include/glcxx.hpp | 8 +++++ include/glcxx/Buffer.hpp | 30 ++++++++++++++++ include/glcxx/Error.hpp | 19 ++++++++++ include/glcxx/Program.hpp | 73 +++++++++++++++++++++++++++++++++++++++ include/glcxx/Shader.hpp | 26 ++++++++++++++ include/glcxx/gl.hpp | 10 ++++++ src/glcxx/Buffer.cpp | 30 ++++++++++++++++ src/glcxx/Program.cpp | 64 ++++++++++++++++++++++++++++++++++ src/glcxx/Shader.cpp | 69 ++++++++++++++++++++++++++++++++++++ 9 files changed, 329 insertions(+) create mode 100644 include/glcxx.hpp create mode 100644 include/glcxx/Buffer.hpp create mode 100644 include/glcxx/Error.hpp create mode 100644 include/glcxx/Program.hpp create mode 100644 include/glcxx/Shader.hpp create mode 100644 include/glcxx/gl.hpp create mode 100644 src/glcxx/Buffer.cpp create mode 100644 src/glcxx/Program.cpp create mode 100644 src/glcxx/Shader.cpp diff --git a/include/glcxx.hpp b/include/glcxx.hpp new file mode 100644 index 0000000..cfd8314 --- /dev/null +++ b/include/glcxx.hpp @@ -0,0 +1,8 @@ +#ifndef GLCXX_HPP +#define GLCXX_HPP + +#include "glcxx/Buffer.hpp" +#include "glcxx/Program.hpp" +#include "glcxx/Shader.hpp" + +#endif diff --git a/include/glcxx/Buffer.hpp b/include/glcxx/Buffer.hpp new file mode 100644 index 0000000..de48dd9 --- /dev/null +++ b/include/glcxx/Buffer.hpp @@ -0,0 +1,30 @@ +#ifndef GLCXX_BUFFER_HPP +#define GLCXX_BUFFER_HPP + +#include "glcxx/gl.hpp" + +namespace glcxx +{ + class Buffer + { + public: + Buffer(); + + ~Buffer(); + + void create(GLenum target, GLenum usage, const void *ptr, size_t sz); + + GLuint id() const { return m_id; } + + void bind() const { glBindBuffer(m_target, m_id); } + + bool valid() const { return m_id > 0u; } + + protected: + GLuint m_id; + + GLenum m_target; + }; +}; + +#endif diff --git a/include/glcxx/Error.hpp b/include/glcxx/Error.hpp new file mode 100644 index 0000000..ec4bcf3 --- /dev/null +++ b/include/glcxx/Error.hpp @@ -0,0 +1,19 @@ +#ifndef GLCXX_ERROR_HPP +#define GLCXX_ERROR_HPP + +#include + +namespace glcxx +{ + + class Error : public std::runtime_error + { + public: + Error(const std::string & msg) : std::runtime_error(msg) + { + }; + }; + +}; + +#endif diff --git a/include/glcxx/Program.hpp b/include/glcxx/Program.hpp new file mode 100644 index 0000000..0b88aaf --- /dev/null +++ b/include/glcxx/Program.hpp @@ -0,0 +1,73 @@ +#ifndef GLCXX_PROGRAM_HPP +#define GLCXX_PROGRAM_HPP + +#include +#include +#include "glcxx/Shader.hpp" + +namespace glcxx +{ + class Program + { + public: + Program(); + + ~Program(); + + GLuint id() const { return m_id; } + + void use() const { glUseProgram(m_id); } + + bool valid() const { return m_id > 0u; } + + template + void create(Shaders... shaders) + { + allocate(); + _create(shaders...); + } + + void attach_shader(const Shader & shader) const + { + glAttachShader(m_id, shader.id()); + } + + void attach_shader(std::unique_ptr shader) const + { + glAttachShader(m_id, shader->id()); + } + + void attach_shader(std::shared_ptr shader) const + { + glAttachShader(m_id, shader->id()); + } + + void bind_attribute(const char * name, GLuint index) const + { + glBindAttribLocation(m_id, index, name); + } + + template + void bind_attributes(const char * name, GLuint index, Args... args) const + { + bind_attribute(name, index); + bind_attributes(args...); + } + + protected: + void allocate(); + + void _create() const; + + template + void _create(T shader, Shaders... args) const + { + attach_shader(shader); + _create(args...); + } + + GLuint m_id; + }; +}; + +#endif diff --git a/include/glcxx/Shader.hpp b/include/glcxx/Shader.hpp new file mode 100644 index 0000000..6841f22 --- /dev/null +++ b/include/glcxx/Shader.hpp @@ -0,0 +1,26 @@ +#ifndef GLCXX_SHADER_HPP +#define GLCXX_SHADER_HPP + +#include "glcxx/gl.hpp" + +namespace glcxx +{ + class Shader + { + public: + Shader(); + + ~Shader(); + + void create(GLenum shaderType, const char *source); + + GLuint id() const { return m_id; } + + bool valid() const { return m_id > 0u; } + + protected: + GLuint m_id; + }; +}; + +#endif diff --git a/include/glcxx/gl.hpp b/include/glcxx/gl.hpp new file mode 100644 index 0000000..03f6be8 --- /dev/null +++ b/include/glcxx/gl.hpp @@ -0,0 +1,10 @@ +#ifndef GLCXX_GL_HPP +#define GLCXX_GL_HPP + +#ifdef GLCXX_GL_INCLUDE +#include GLCXX_GL_INCLUDE +#else +#include "GL/gl.h" +#endif + +#endif diff --git a/src/glcxx/Buffer.cpp b/src/glcxx/Buffer.cpp new file mode 100644 index 0000000..1720110 --- /dev/null +++ b/src/glcxx/Buffer.cpp @@ -0,0 +1,30 @@ +#include "glcxx/Buffer.hpp" +#include "glcxx/Error.hpp" + +namespace glcxx +{ + Buffer::Buffer() + { + m_id = 0u; + } + + Buffer::~Buffer() + { + if (m_id > 0u) + { + glDeleteBuffers(1, &m_id); + } + } + + void Buffer::create(GLenum target, GLenum usage, const void *ptr, size_t sz) + { + m_target = target; + glGenBuffers(1, &m_id); + if (m_id == 0u) + { + throw Error("Failed to allocate an OpenGL buffer"); + } + bind(); + glBufferData(target, sz, ptr, usage); + } +} diff --git a/src/glcxx/Program.cpp b/src/glcxx/Program.cpp new file mode 100644 index 0000000..84d8b67 --- /dev/null +++ b/src/glcxx/Program.cpp @@ -0,0 +1,64 @@ +#include "glcxx/Program.hpp" +#include "glcxx/Error.hpp" +#include + +namespace glcxx +{ + Program::Program() + { + m_id = 0u; + } + + Program::~Program() + { + if (m_id > 0u) + { + glDeleteProgram(m_id); + } + } + + void Program::allocate() + { + m_id = glCreateProgram(); + if (m_id == 0u) + { + throw Error("Failed to allocate an OpenGL program"); + } + } + + void Program::_create() const + { + glLinkProgram(m_id); + + GLint link_status; + glGetProgramiv(m_id, GL_LINK_STATUS, &link_status); + if (link_status != GL_TRUE) + { + std::string message = "Failed to link program"; + GLint log_length = 0; + 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); + message += "\n"; + message += log; + message += "\n"; + delete[] log; + } + throw Error(message); + } + } + +#if 0 + for (;;) + { + const char *uniform_name = va_arg(va, const char *); + if (uniform_name == NULL) + break; + GLint loc = glGetUniformLocation(m_id, uniform_name); + m_uniform_locations.push_back(loc); + m_uniform_location_names[uniform_name] = loc; + } +#endif +} diff --git a/src/glcxx/Shader.cpp b/src/glcxx/Shader.cpp new file mode 100644 index 0000000..39d78f0 --- /dev/null +++ b/src/glcxx/Shader.cpp @@ -0,0 +1,69 @@ +#include "glcxx/Shader.hpp" +#include "glcxx/Error.hpp" +#include + +namespace glcxx +{ + Shader::Shader() + { + m_id = 0u; + } + + Shader::~Shader() + { + if (m_id > 0u) + { + glDeleteShader(m_id); + } + } + + void Shader::create(GLenum shaderType, const char *source) + { + GLint status; + + m_id = glCreateShader(shaderType); + if (m_id == 0u) + { + throw Error("Failed to allocate an OpenGL shader"); + } + + glShaderSource(m_id, 1, &source, NULL); + + glCompileShader(m_id); + + glGetShaderiv(m_id, GL_COMPILE_STATUS, &status); + if (status == GL_TRUE) + { + return; + } + + std::string message = "Error compiling "; + switch (shaderType) + { + case GL_VERTEX_SHADER: + message += "vertex"; + break; + case GL_FRAGMENT_SHADER: + message += "fragment"; + break; + default: + message += "unknown"; + break; + } + message += " shader"; + + GLint log_length; + 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); + message += "\nShader Log:\n"; + message += log; + message += "\n"; + delete[] log; + } + glDeleteShader(m_id); + throw Error(message); + } +}