allocate OpenGL object when C++ object is constructed; make create() a static factory function

This commit is contained in:
Josh Holtrop 2015-06-13 23:33:23 -04:00
parent 22020958d5
commit 4096a53edc
9 changed files with 113 additions and 101 deletions

View File

@ -12,8 +12,6 @@ namespace glcxx
~Array(); ~Array();
void create();
void bind() void bind()
{ {
glBindVertexArray(m_id); glBindVertexArray(m_id);
@ -21,8 +19,6 @@ namespace glcxx
GLuint id() const { return m_id; } GLuint id() const { return m_id; }
bool valid() const { return m_id > 0u; }
protected: protected:
GLuint m_id; GLuint m_id;
}; };

View File

@ -2,6 +2,7 @@
#define GLCXX_BUFFER_HPP #define GLCXX_BUFFER_HPP
#include "glcxx/gl.hpp" #include "glcxx/gl.hpp"
#include <memory>
namespace glcxx namespace glcxx
{ {
@ -12,18 +13,25 @@ namespace glcxx
~Buffer(); ~Buffer();
void create(GLenum target, GLenum usage, const void * ptr, size_t size); void set_buffer_data(GLenum target, GLenum usage, const void * ptr, size_t size);
GLuint id() const { return m_id; } GLuint id() const { return m_id; }
void bind() const { glBindBuffer(m_target, m_id); } void bind() const { glBindBuffer(m_target, m_id); }
bool valid() const { return m_id > 0u; } static std::shared_ptr<Buffer> create(GLenum target, GLenum usage, const void * ptr, size_t size)
{
std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>();
buffer->set_buffer_data(target, usage, ptr, size);
return buffer;
}
protected: protected:
GLuint m_id; GLuint m_id;
GLenum m_target; GLenum m_target;
void allocate();
}; };
}; };

View File

@ -18,13 +18,11 @@ namespace glcxx
void use() const { glUseProgram(m_id); } void use() const { glUseProgram(m_id); }
bool valid() const { return m_id > 0u; }
template <typename... Shaders> template <typename... Shaders>
void create(Shaders... shaders) void build(Shaders... shaders)
{ {
allocate(); allocate();
_create(shaders...); _build(shaders...);
} }
void attach_shader(const Shader & shader) const void attach_shader(const Shader & shader) const
@ -42,45 +40,58 @@ namespace glcxx
glAttachShader(m_id, shader->id()); glAttachShader(m_id, shader->id());
} }
void link() const;
GLint get_uniform_location(const char * uniform_name) GLint get_uniform_location(const char * uniform_name)
{ {
return glGetUniformLocation(m_id, uniform_name); return glGetUniformLocation(m_id, uniform_name);
} }
template <typename... Args>
static std::shared_ptr<Program> create(Args... args)
{
std::shared_ptr<Program> program = std::make_shared<Program>();
program->build(args...);
return program;
}
protected: protected:
GLuint m_id;
void allocate(); void allocate();
void _create() const; void _build() const
template <typename... Shaders>
void _create(const Shader & shader, Shaders... args) const
{ {
attach_shader(shader); link();
_create(args...);
} }
template <typename... Shaders> template <typename... Shaders>
void _create(std::unique_ptr<Shader> shader, Shaders... args) const void _build(const Shader & shader, Shaders... args) const
{ {
attach_shader(shader); attach_shader(shader);
_create(args...); _build(args...);
} }
template <typename... Shaders> template <typename... Shaders>
void _create(std::shared_ptr<Shader> shader, Shaders... args) const void _build(std::unique_ptr<Shader> shader, Shaders... args) const
{ {
attach_shader(shader); attach_shader(shader);
_create(args...); _build(args...);
} }
template <typename... Shaders> template <typename... Shaders>
void _create(const char * attribute_name, GLuint index, Shaders... args) const void _build(std::shared_ptr<Shader> shader, Shaders... args) const
{
attach_shader(shader);
_build(args...);
}
template <typename... Shaders>
void _build(const char * attribute_name, GLuint index, Shaders... args) const
{ {
glBindAttribLocation(m_id, index, attribute_name); glBindAttribLocation(m_id, index, attribute_name);
_create(args...); _build(args...);
} }
GLuint m_id;
}; };
}; };

View File

@ -2,26 +2,43 @@
#define GLCXX_SHADER_HPP #define GLCXX_SHADER_HPP
#include "glcxx/gl.hpp" #include "glcxx/gl.hpp"
#include <memory>
namespace glcxx namespace glcxx
{ {
class Shader class Shader
{ {
public: public:
Shader(); Shader(GLenum shader_type);
~Shader(); ~Shader();
void create(GLenum shader_type, const char * source, int length = -1); void set_source(const char * source, int length = -1);
void create_from_file(GLenum shader_type, const char * filename); void set_source_from_file(const char * filename);
GLuint id() const { return m_id; } GLuint id() const { return m_id; }
bool valid() const { return m_id > 0u; } static std::shared_ptr<Shader> create(GLenum shader_type, const char * source, int length = -1)
{
std::shared_ptr<Shader> shader = std::make_shared<Shader>(shader_type);
shader->set_source(source, length);
return shader;
}
static std::shared_ptr<Shader> create_from_file(GLenum shader_type, const char * filename)
{
std::shared_ptr<Shader> shader = std::make_shared<Shader>(shader_type);
shader->set_source_from_file(filename);
return shader;
}
protected: protected:
GLuint m_id; GLuint m_id;
GLenum m_shader_type;
void allocate();
}; };
}; };

View File

@ -6,18 +6,7 @@ namespace glcxx
Array::Array() Array::Array()
{ {
m_id = 0u; m_id = 0u;
}
Array::~Array()
{
if (m_id != 0u)
{
glDeleteVertexArrays(1, &m_id);
}
}
void Array::create()
{
glGenVertexArrays(1, &m_id); glGenVertexArrays(1, &m_id);
if (m_id == 0u) if (m_id == 0u)
@ -25,4 +14,9 @@ namespace glcxx
throw Error("Failed to allocate an OpenGL array"); throw Error("Failed to allocate an OpenGL array");
} }
} }
Array::~Array()
{
glDeleteVertexArrays(1, &m_id);
}
} }

View File

@ -5,26 +5,28 @@ namespace glcxx
{ {
Buffer::Buffer() Buffer::Buffer()
{ {
m_id = 0u; allocate();
} }
Buffer::~Buffer() Buffer::~Buffer()
{
if (m_id > 0u)
{ {
glDeleteBuffers(1, &m_id); glDeleteBuffers(1, &m_id);
} }
}
void Buffer::create(GLenum target, GLenum usage, const void * ptr, size_t size) void Buffer::set_buffer_data(GLenum target, GLenum usage, const void * ptr, size_t size)
{ {
m_target = target; m_target = target;
bind();
glBufferData(target, size, ptr, usage);
}
void Buffer::allocate()
{
m_id = 0u;
glGenBuffers(1, &m_id); glGenBuffers(1, &m_id);
if (m_id == 0u) if (m_id == 0u)
{ {
throw Error("Failed to allocate an OpenGL buffer"); throw Error("Failed to allocate an OpenGL buffer");
} }
bind();
glBufferData(target, size, ptr, usage);
} }
} }

View File

@ -6,27 +6,15 @@ namespace glcxx
{ {
Program::Program() Program::Program()
{ {
m_id = 0u; allocate();
} }
Program::~Program() Program::~Program()
{
if (m_id > 0u)
{ {
glDeleteProgram(m_id); glDeleteProgram(m_id);
} }
}
void Program::allocate() void Program::link() const
{
m_id = glCreateProgram();
if (m_id == 0u)
{
throw Error("Failed to allocate an OpenGL program");
}
}
void Program::_create() const
{ {
glLinkProgram(m_id); glLinkProgram(m_id);
@ -49,4 +37,13 @@ namespace glcxx
throw Error(message); throw Error(message);
} }
} }
void Program::allocate()
{
m_id = glCreateProgram();
if (m_id == 0u)
{
throw Error("Failed to allocate an OpenGL program");
}
}
} }

View File

@ -6,29 +6,21 @@
namespace glcxx namespace glcxx
{ {
Shader::Shader() Shader::Shader(GLenum shader_type)
{ {
m_id = 0u; m_shader_type = shader_type;
allocate();
} }
Shader::~Shader() Shader::~Shader()
{
if (m_id > 0u)
{ {
glDeleteShader(m_id); glDeleteShader(m_id);
} }
}
void Shader::create(GLenum shader_type, const char * source, int length) void Shader::set_source(const char * source, int length)
{ {
GLint status; GLint status;
m_id = glCreateShader(shader_type);
if (m_id == 0u)
{
throw Error("Failed to allocate an OpenGL shader");
}
GLint lengths[1] = {length}; GLint lengths[1] = {length};
glShaderSource(m_id, 1, &source, &lengths[0]); glShaderSource(m_id, 1, &source, &lengths[0]);
@ -41,7 +33,7 @@ namespace glcxx
} }
std::string message = "Error compiling "; std::string message = "Error compiling ";
switch (shader_type) switch (m_shader_type)
{ {
case GL_VERTEX_SHADER: case GL_VERTEX_SHADER:
message += "vertex"; message += "vertex";
@ -70,7 +62,7 @@ namespace glcxx
throw Error(message); throw Error(message);
} }
void Shader::create_from_file(GLenum shader_type, const char * filename) void Shader::set_source_from_file(const char * filename)
{ {
std::ifstream ifs; std::ifstream ifs;
ifs.open(filename); ifs.open(filename);
@ -83,6 +75,15 @@ namespace glcxx
ifs.seekg(0, ifs.beg); ifs.seekg(0, ifs.beg);
std::vector<char> file_contents(length); std::vector<char> file_contents(length);
ifs.read(&file_contents[0], length); ifs.read(&file_contents[0], length);
create(shader_type, &file_contents[0], length); set_source(&file_contents[0], length);
}
void Shader::allocate()
{
m_id = glCreateShader(m_shader_type);
if (m_id == 0u)
{
throw Error("Failed to allocate an OpenGL shader");
}
} }
} }

View File

@ -27,28 +27,14 @@ bool init(void)
{ {
array1 = make_shared<glcxx::Array>(); array1 = make_shared<glcxx::Array>();
array2 = make_shared<glcxx::Array>(); array2 = make_shared<glcxx::Array>();
array1->create();
array2->create();
vs = make_shared<glcxx::Shader>();
vs2 = make_shared<glcxx::Shader>();
fs = make_shared<glcxx::Shader>();
fs2 = make_shared<glcxx::Shader>();
program = make_shared<glcxx::Program>();
program2 = make_shared<glcxx::Program>();
buffer = make_shared<glcxx::Buffer>();
buffer2 = make_shared<glcxx::Buffer>();
buffer3 = make_shared<glcxx::Buffer>();
vs->create_from_file(GL_VERTEX_SHADER, "test/vert.glsl"); vs = glcxx::Shader::create_from_file(GL_VERTEX_SHADER, "test/vert.glsl");
fs->create_from_file(GL_FRAGMENT_SHADER, "test/frag.glsl"); fs = glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, "test/frag.glsl");
program->create(vs, fs, program = glcxx::Program::create(vs, fs, "position", 0);
"position", 0);
vs2->create_from_file(GL_VERTEX_SHADER, "test/vert2.glsl"); vs2 = glcxx::Shader::create_from_file(GL_VERTEX_SHADER, "test/vert2.glsl");
fs2->create_from_file(GL_FRAGMENT_SHADER, "test/frag2.glsl"); fs2 = glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, "test/frag2.glsl");
program2->create(vs2, fs2, program2 = glcxx::Program::create(vs2, fs2, "position", 0, "color", 1);
"position", 0,
"color", 1);
GLfloat coords[] = { GLfloat coords[] = {
-0.5, -0.5, -0.5, -0.5,
@ -56,20 +42,20 @@ bool init(void)
0.5, 0.5, 0.5, 0.5,
-0.5, 0.5, -0.5, 0.5,
}; };
buffer->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &coords, sizeof(coords)); buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &coords, sizeof(coords));
GLfloat coords2[] = { GLfloat coords2[] = {
0.2, 0.2, 0.2, 0.2,
0.9, 0.2, 0.9, 0.2,
0.9, 0.9, 0.9, 0.9,
}; };
buffer2->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &coords2, sizeof(coords2)); buffer2 = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &coords2, sizeof(coords2));
GLfloat colors[] = { GLfloat colors[] = {
1.0, 0.1, 0.1, 1.0, 1.0, 0.1, 0.1, 1.0,
0.1, 1.0, 0.1, 1.0, 0.1, 1.0, 0.1, 1.0,
0.1, 0.1, 1.0, 1.0, 0.1, 0.1, 1.0, 1.0,
}; };
buffer3->create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &colors, sizeof(colors)); buffer3 = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, &colors, sizeof(colors));
array1->bind(); array1->bind();
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);