Auto-binding in the shell of OpenGL objects

I tend to wrap OpenGL objects in my classes. OpenGL has a concept of binding, where you link your object, do something with it, and then untie it. For example, 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); 

The wrapper will 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 set methods, and GLObject will be bound automatically.

I could just do this in every implementation of the method:

 public void Texture::setParameter(...) { this.bind(); // do something this.unBind(); } 

Although then I have to do it for each method added! Is there a better way, so it runs automatically before and after adding each method?

+4
source share
3 answers

Maybe a context object can 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 the scope:

 { TextureContext mycont(textname); mytexture->setParameter(...); mytexture->setParameter(...); mytexture->setParameter(...); } 

the mycont object lives only in the region and automatically calls its destructor (ant method unbind accordingly) after the region remains.

EDIT :

Maybe you can customize the TextureContext class to get a texture name instead of a Texture instance in the constructor before binding the texture.

+5
source

The problem here is that I want to avoid the bind () and unBind () functions

Most likely, you will not be able to completely get rid of them. glTexImage2D will require bind / unBind (or lock / unlock if you use DirectX-style names)

I could just do this in every implementation of the method:

You should not do this because you will get a significant decrease in performance. This is called "state trash", if I remember correctly. If you need to change several parameters, you must change them all at once. The binding / decoupling call will often be extremely inefficient and is not recommended in the performance recommendations I have seen (for example, DirectX SDK, nvidia documentation, random GDC papyri, etc.).

Is there a better way, so it runs automatically before and after adding each method?

Yes there is. Cache multiple state changes and delay valid OpenGL calls until they are absolutely necessary.

those. if your program asks to set the Min filter, the Mag filter, wrap_s, wrap_t and other parameters for glTexParameter , and your texture is not currently attached to any texetra, do not set the parameters now. Save them in the internal list (within this specific texture) and set them all right after texture binding. Either when the list reaches a certain size or when the user calls glGetTexParameter. Once it's time to set the parameters, snap the texture, set the parameters and untie it if necessary.

There are two potential problems with this approach:

  • The time taken to change the state of the textures can become a little unpredictable. (because you wonโ€™t be sure when the actual actual OpenGL cal result will be executed).
  • Using this method can be more difficult to detect OpenGL errors.
  • If the internal list uses dynamically allocated memory and often calls new / delete , this can lead to a bottleneck, as calls to new / delete can be slow. This can be solved using a circular buffer with a fixed size for this internal list.
+2
source

I tend to wrap OpenGL objects in my classes.

The guy goes to the doctor and says: "It hurts when I raise my hand like that." Therefore, the doctor says: "Then stop raising your hand like that."

Your problem is that you are trying to provide an object interface for a non-object based system. It will only end in tears and / or pain.

Your best bet would be to increase your level of abstraction. Instead of wrapping OpenGL objects directly, wrap the graphical API. You may have some external concept of โ€œtextureโ€ in which the OpenGL texture object will be stored, but you will not disclose functions that directly change the parameters of this texture. Or even indirectly.

Do not do promises with your API, which you cannot save. Bring the abstraction to a point where the external code just doesn't care what texture filtering mode or other parameters are.

Alternatively, filtering (and packaging) should be part of the constructor of the object, a fixed value set during creation.

+1
source

Source: https://habr.com/ru/post/1399371/


All Articles