Wrapping OpenGL Calls

Started by
11 comments, last by RobinsonUK 12 years, 1 month ago

If you're going for a higher level graphics engine you should not think about how to wrap OpenGL. Instead you should think about how you'd like to make the calls to render something and then fill that in by using OpenGL. You might need a few iterations of adjusting requirements due to api specific limitations but you'll end up with a system that's easy to use, which is one of the most important things for anything high level.


thats exactly what I said. In my implementation I dont have glBindBuffer and stuff like that used directly, I rather have mesh.load(), mesh.render() etc. so that when I try to write a small application I dont need to remember how to use OGL stuff, I just have to supply the function with some general stuff like filename, identifier that will hold the access to the loaded asset. later I can use the identifier to render it or use it.
Of course when I need it I can create a texture manually, so instead having an identifier I just have the texture directly, fill it with stuff and use it again with texture.bind() etc. so after loading again I can forget about using OGL.
When I have to do some more special stuff like deferred rendering I just use the wrapped fbo class that I wrote, and again I dont have to know OGL, but feed the fbo. This kind of stuff is similar to what RobinsonUK described.
Advertisement
I personally have chosen a two-layered abstraction. The lower level simply wraps the OpenGL objects, VBOs, IBOs, textures and so on to the language's way of handling objects. The higher level uses those and is supposed to have things like a mesh class. Currently I handle the binding so that all the methods that require the GL object to be bound, check if it is so in the start of the method. The "trick" is that this check is only done in debug mode, the release builds don't contain any checks. It also means that to use the objects, I need to explicitly bind them whenever I'm doing anything to them - I'm not interested in abstracting all of the OpenGL away so this has been okay for me so far. First call bind and then call the actual method to do stuff with the object.

However, I've grown bit tired of the idea of doing such low level managing, what with having to have bind calls everywhere where the low level objects are used, so I'm planning to start using a state manager. The plan also includes dividing the bind operations into two categories: bind for editing and bind for drawing. The bind for editing is done implicitly in the wrapper objects' methods, for example when passing vertex data to vertex buffer. The binding for drawing is still done with an explicit bind call. The reason for the explicit binds is mostly that the alternative would be to pass all the relevant objects to some rendering method which would then bind them - but that would mean lots of stuff to pass, at least all the buffers, textures, shader... doesn't feel right, as the method would keep bloating when new stuff gets added. Anyway the state manager would have to keep track of what is bound for drawing and what is actually bound at the moment, be it for either drawing or editing, but that doesn't seem bad.

Another complication comes up at least with vertex array objects. If I first bind a VAO and then an index buffer, the index buffer will be attached to the VAO. The way I'm going to get around that is to add an AddIndexBuffer method to the VAO class which uses the implicit bind for editing method, and whenever I explicitly bind an index buffer for drawing the VAO will be automatically unbound. Same goes for vertex buffers even though they don't have the same problem. I feel it makes sense to unbind any VAOs when vertex and index buffers are bound, because those don't really mix well anyway, with VAOs essentially being a shortcut to VBO and IBO binding.
The bind for editing is done implicitly in the wrapper objects' methods, for example when passing vertex data to vertex buffer. The binding for drawing is still done with an explicit bind call.[/quote]

In fact this is exactly what I did. I also made some little classes to unbind objects using RAII principles. I think the compiler should optimise away most of it leaving me with similar performance to explicit calls to bind and unbind the object, i.e. :


class Using
{
public:
Using(std::shared_ptr<ArrayBufferGL> buffer) : MyUsing(buffer)
{
MyUsing->Use();
}
~Using()
{
MyUsing->Unuse();
}
private:
std::shared_ptr<ArrayBufferGL> MyUsing;
};


, where I can Use/Unuse the object with a stack frame:


{
ArrayBufferType::Using useArrayBuffer(mesh->ArrayBuffer());
...
}


By doing this I never "forget" to unbind an object after use.

This topic is closed to new replies.

Advertisement