If you’re looking for some advice, I find many of your design choices to be… dubious.
Your API is needlessly objectified. As an example, take state.hpp
.
You have this _blend
type, and you create a global, non-constant blend
object. Why? What advantages does this offer over simply having those be namespace-scoped functions? None of those functions modify the members of the _blend
object. In fact, there are no members of the _blend
object. So what’s the point of them being in an object? If you want to group those functions together, then use a namespace, or static members.
The user gets zero benefit from calling blend.func
vs. blend::func
.
Also, there are a number of places where you don’t take advantage of obvious avenues for C+±ification of the OpenGL API. For example, you don’t use enum class
where appropriate. Admittedly, gl.xml
doesn’t make it easy to extract out the appropriate enumerators for every function (though it’s much better now than it used to be). But any good C++ wrapper of OpenGL ought to at least make an attempt to support this.
And then there’s just some very unfortunate design choices.
First, uniform::set
takes vector<T>
. That’s wonderful… for people who store their data in vector
s. For everyone else, it’s a terrible API. They now have to copy that data to a vector
before they can pass it to you. Which means every time you send data to a uniform, you have to allocate memory that will be almost immediately deleted.
A pointer and a size would be an interface that anyone could use, regardless of their container of choice. Or even better, the GSL type span
.
Oh, and FYI: if you want to test if a type is the same as another type, you use std::is_same
; you don’t use typeid
unless you need to make a runtime determination.
Then, there’s your base
type. This is a type whose sole purpose is to allocate storage for OpenGL objects. Ignoring the bug you have in it (not deallocating memory), you derive from this class a lot. Publicly.
But you never use it as a public base class. You aren’t using inheritance for polymorphism, since base
doesn’t have any virtual functions. You treat it like a member variable. So… why isn’t it a member variable? Why are you inheriting from it?
You also use it in a lot of places where it is quite frankly unnecessary and needlessly performance-unfriendly. Consider shader
and program
. base
has the ability to allocate an array of objects; you tell it how many to allocate. And yet, shader
and program
both… only ever allocate one such object. In fact, OpenGL doesn’t even allow you to allocate an array of shader/program objects. So neither shader
nor program
needs dynamic allocation at all; it just needs to store a GLuint
.
This is even further abused with the _mode
class. There, you’re not even using the dynamic allocation to store an OpenGL object; you’re just storing an integer. So why are you using base
for this?
I haven’t done a detailed look through this, but thus far, I cannot say that I find many of the choices made in the design of this system to be particularly good.