Reputation: 1341
I tend to wrap OpenGL objects in their own classes. In OpenGL there is the concept of binding, where you bind your object, do something with it and then unbind it. For example, a texture:
glBindTexture(GL_TEXTURE_2D, TextureColorbufferName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
glBindTexture(GL_TEXTURE_2D, 0);
Wrapping this would be something like:
texture->bind();
texture->setParameter(...);
texture->setParameter(...);
texture->unBind();
The problem here, is that I want to avoid the bind() and unBind() functions, and instead just be able to call the set methods and the GLObject will be bound automaticly.
I could just do it in every method implementation:
public void Texture::setParameter(...)
{
this.bind();
// do something
this.unBind();
}
Though then I have to do that for every added method! Is there a better way, so it is automatically done before and after every method added?
Upvotes: 4
Views: 732
Reputation: 474376
I tend to wrap OpenGL objects in their own classes.
A guy goes to the doctor and say, "It hurts whenever I raise my arm like this." So the doctor says, "Then stop raising your arm like that."
Your problem is that you're trying to provide an object-based interface to a system that is not object based. That will only end in tears and/or pain.
A far better solution would be to raise the level of your abstraction. Instead of wrapping OpenGL objects directly, wrap your graphics API. You might have some external concept of "texture" which would store an OpenGL texture object, but you wouldn't expose functions that change parameters on that texture directly. Or even indirectly.
Don't make promises with your API that you can't keep. Raise the abstraction to the point where the external code simply doesn't care what the texture's filtering mode and other parameters are.
Alternatively, have the filtering (and wrapping) be part of the object's constructor, a fixed value set at creation time.
Upvotes: 1
Reputation: 26439
The problem here, is that I want to avoid the bind() and unBind() functions
Most likely, you won't be able to get rid of them completely. glTexImage2D will require bind/unBind (or lock/unlock if you wnat DirectX-style names)
I could just do it in every method implementation:
You shouldn't do that, because you'll get massive performance drop. It is called "state trashing", if I remember correctly. If you need to modify multiple parameters, you should modify them all in one go. Calling "bind"/"unbind" frequently will be extremely inefficient and isn't recommended in performance guidelines I saw (i.e. DirectX SDK, nvidia documentation, random GDC papaers, etc).
Is there a better way, so it is automatically done before and after every method added?
Yes, there is. Cache multiple state changes and delay actual OpenGL calls till they're absolutely necessary.
I.e. if your program requests to set Min filter, Mag filter, wrap_s, wrap_t and other parameters for glTexParameter
, and your texture isn't currently bound to any texutre stage, don't set parameters now. Store them in internal list (within this specific texture), and set them all at once next time texture is bound. Or when list reaches certain size, or when user calls glGetTexParameter. Once it is time to set parameters, bind texture, set parameters, and unbind it, if necessary.
There are two potential problems with this approach, though:
new
/delete
, this might result in bottleneck, because calls to new
/delete
can be slow. This can be solved by using fixed-size circular buffer for that internal list.Upvotes: 2
Reputation: 35089
Maybe a context object may help here. Consider this small object:
class TextureContext {
public:
TextureContext(char* texname) {
glBindTexture(GL_TEXTURE_2D, texname);
}
~TextureContext() {
glBindTexture(GL_TEXTURE_2D, 0);
}
};
This object is now used within a scope:
{
TextureContext mycont(textname);
mytexture->setParameter(...);
mytexture->setParameter(...);
mytexture->setParameter(...);
}
the object mycont
only lives in the scope and calls its destructor (ant the unbind method respectively) automatically once the scope is left.
EDIT:
Maybe you can adjust the TextureContext
class to take your Texture
instance instead in the constructor and retrieves the texture name itself before binding the texture.
Upvotes: 5