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

时间:2012-03-02 10:40:53

标签: 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);
 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();
}

虽然我必须为每个添加的方法做到这一点!有没有更好的方法,所以在每个方法添加之前和之后都会自动完成?

3 个答案:

答案 0 :(得分:5)

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

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类以在构造函数中使用Texture实例,并在绑定纹理之前检索纹理名称。

答案 1 :(得分:2)

  

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

最有可能的是,你无法完全摆脱它们。 glTexImage2D将需要bind / unBind(如果您使用DirectX风格的名称,则需要锁定/解锁)

  

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

你不应该这样做,因为你会获得巨大的性能下降。如果我没记错的话,它被称为“国家垃圾”。如果您需要修改多个参数,则应该一次性修改它们。经常调用“绑定”/“取消绑定”将是非常低效的,并且在我看到的性能指南中不推荐(即DirectX SDK,nvidia文档,随机GDC papaers等)。

  

有没有更好的方法,所以在每个方法添加之前和之后都会自动完成?

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

即。如果您的程序请求为glTexParameter设置Min过滤器,Mag过滤器,wrap_s,wrap_t和其他参数,并且您的纹理当前未绑定到任何texutre阶段,请不要立即设置参数。将它们存储在内部列表中(在此特定纹理内),并在下次绑定纹理时立即将它们全部设置。或者当列表达到特定大小时,或者当用户调用glGetTexParameter时。一旦设置参数,绑定纹理,设置参数,并在必要时解除绑定。

但这种方法存在两个潜在的问题:

  1. 改变纹理状态所花费的时间可能会变得有点不可预测。 (因为你不确定何时会执行真正的OpenGL校准)。
  2. 使用此方法检测OpenGL错误可能更难。
  3. 如果内部列表使用动态分配的内存并经常调用new / delete,则可能会导致瓶颈,因为对new / delete的调用可能会很慢。这可以通过对内部列表使用固定大小的循环缓冲区来解决。

答案 2 :(得分:1)

  

我倾向于在自己的类中包装OpenGL对象。

一个男人去看医生并说:“每当我举起这样的胳膊时,它会疼。”所以医生说,“然后停止抬起你的手臂。”

您的问题是您正在尝试为基于对象的系统提供基于对象的界面。那只会以眼泪和/或痛苦结束。

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

请勿使用您无法保留的API进行承诺。将抽象提升到外部代码根本不关心纹理的过滤模式和其他参数的程度。

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