C++ OpenGL对象包装器中的自动绑定

C++ OpenGL对象包装器中的自动绑定,c++,opengl,C++,Opengl,我倾向于将OpenGL对象包装在它们自己的类中。在OpenGL中有绑定的概念,您可以绑定对象,对其执行一些操作,然后解除绑定。例如,纹理: glBindTexture(GL_TEXTURE_2D, TextureColorbufferName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000

我倾向于将OpenGL对象包装在它们自己的类中。在OpenGL中有绑定的概念,您可以绑定对象,对其执行一些操作,然后解除绑定。例如,纹理:

 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);
将其包装如下:

texture->bind();
    texture->setParameter(...);
    texture->setParameter(...);
texture->unBind();
这里的问题是,我希望避免使用bind和unBind函数,而是能够调用set方法,并且GLObject将自动绑定

我可以在每个方法实现中都这样做:

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

尽管如此,对于每一个添加的方法,我都必须这样做!是否有更好的方法,以便在添加每个方法之前和之后自动执行此操作?

也许上下文对象在这里会有所帮助。考虑这个小对象:

class TextureContext {
public:
    TextureContext(char* texname) {
        glBindTexture(GL_TEXTURE_2D, texname);
    }
    ~TextureContext() {
        glBindTexture(GL_TEXTURE_2D, 0);
    }
};
此对象现在在一个范围内使用:

{
    TextureContext mycont(textname);
    mytexture->setParameter(...);
    mytexture->setParameter(...);
    mytexture->setParameter(...);
}
对象mycont仅存在于作用域中,并且在离开作用域后自动调用其析构函数ant和unbind方法

编辑:

也许可以调整TextureContext类,以在构造函数中获取纹理实例,并在绑定纹理之前检索纹理名称本身

这里的问题是,我想避免使用bind和unBind函数

最有可能的是,你无法完全摆脱它们。如果使用DirectX样式名称,则glTexImage2D将需要绑定/取消绑定或锁定/解锁

我可以在每个方法实现中都这样做:

public void Texture::setParameter(...)
{
    this.bind();
    // do something
    this.unBind();
}
你不应该这样做,因为你会得到巨大的性能下降。如果我没记错的话,这就是所谓的国家毁灭。如果需要修改多个参数,则应一次性修改所有参数。频繁调用bind/unbind效率极低,我看到的性能指南中不建议这样做,如DirectX SDK、nvidia文档、随机GDC papers等

是否有更好的方法,以便在添加每个方法之前和之后自动执行

是的,有。缓存多个状态更改并延迟实际的OpenGL调用,直到它们是绝对必要的

也就是说,如果您的程序请求为glTexParameter设置Min filter、Mag filter、wrap_s、wrap_t和其他参数,并且您的纹理当前未绑定到任何texutre阶段,则现在不要设置参数。将它们存储在该特定纹理的内部列表中,并在下次绑定纹理时一次性设置它们。或者当列表达到一定大小时,或者当用户调用GLGetTestParameter时。一旦到了设置参数的时间,绑定纹理,设置参数,并在必要时解除绑定

不过,这种方法存在两个潜在问题:

花在更改纹理状态上的时间可能会变得有点不可预测。因为您无法确定何时将执行实际的OpenGL cal。 使用这种方法可能更难检测OpenGL错误。 若内部列表使用动态分配的内存并频繁调用new/delete,这可能会导致瓶颈,因为对new/delete的调用可能会很慢。这可以通过为该内部列表使用固定大小的循环缓冲区来解决。 我倾向于将OpenGL对象包装在它们自己的类中

一个男人去看医生,说:我这样举胳膊的时候都疼。医生说,那就别再那样举起你的手臂了

您的问题是,您试图为非基于对象的系统提供基于对象的接口。那只会以眼泪和/或痛苦告终

更好的解决方案是提高抽象级别。不要直接包装OpenGL对象,而是包装图形API。您可能有一些纹理的外部概念,可以存储OpenGL纹理对象,但不会公开直接更改该纹理上参数的函数。甚至间接地

不要对你的API做出你无法兑现的承诺。将抽象提高到外部代码根本不关心纹理的过滤模式和其他参数是什么的程度


或者,将过滤和包装作为对象构造函数的一部分,在创建时设置一个固定值。

如果用户希望按顺序设置多个纹理,则可能会导致问题。因此,文本上下文不应该设置0个纹理,但是以前使用的纹理是用相应的GLGET调用获得的。我不是专业的OpenGL开发者,我试图从更一般的C++编程角度回答这个问题。