Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何让一个C++;编译器知道函数是`幂等的` 我正在编写一个OpenGL C++包装器。此包装器旨在减少复杂和易出错的使用_C++_Opengl - Fatal编程技术网

如何让一个C++;编译器知道函数是`幂等的` 我正在编写一个OpenGL C++包装器。此包装器旨在减少复杂和易出错的使用

如何让一个C++;编译器知道函数是`幂等的` 我正在编写一个OpenGL C++包装器。此包装器旨在减少复杂和易出错的使用,c++,opengl,C++,Opengl,例如,我目前希望用户只对OpenGL上下文稍加注意。为此,我编写了一个类gl\u texture\u 2d。众所周知,OpenGL纹理基本上具有以下操作: 将其u/v参数设置为repeat/mirror,依此类推 将其设置为min/mag过滤器为线性 基于此,我们有: class gl_texture_2d { public: void mirror_u(); // set u parameter as mirror model void mirror_v(); // set v p

例如,我目前希望用户只对
OpenGL上下文
稍加注意。为此,我编写了一个类
gl\u texture\u 2d
。众所周知,
OpenGL纹理
基本上具有以下操作:

  • 将其u/v参数设置为
    repeat
    /
    mirror
    ,依此类推
  • 将其设置为
    min
    /
    mag
    过滤器
    线性
  • 基于此,我们有:

    class gl_texture_2d 
    {
    public:
      void mirror_u(); // set u parameter as mirror model
      void mirror_v(); // set v parameter as mirror model
      void linear_min_filter(); // ...
      void linear_mag_filter(); // ...
    };
    
    我们知道,只有当OpenGL纹理对象的句柄当前绑定到OpenGL上下文时,我们才能执行这些操作。 假设我们有一个函数,可以这样做: 无效绑定(GLuint htex);//实际上是相关GL函数的别名

    好的,我们现在可以将我们的
    gl\u纹理\u 2d
    用法设计为:

    gl_texture_2d tex;
    bind(tex.handle());
    tex.mirror_u();
    tex.linear_min_filter();
    unbind(tex.handle());
    
    它证实了德国劳埃德船级社的逻辑,但它失去了包装的意义,对吗?作为一名用户,我希望像这样操作:

    gl_texture_2d tex;
    tex.mirror_u();
    tex.linear_min_filter();
    
    为了实现这一目标,我们必须实现以下功能:

    void gl_texture_2d::mirror_u()
    {
      glBindTexture(GL_TEXTURE_2D, handle());
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
      glBindTexture(GL_TEXTURE_2D, 0);
    }
    
    始终在内部执行绑定操作可确保该操作有效。但是成本太高了

    代码:

    tex.mirror_u();
    tex.mirror_v();
    
    将扩展为一对无意义的绑定/解除绑定操作

    那么,是否有任何机制可以让编译器知道:

  • 如果
    bind(b)
    紧接着
    bind(a)
    ,则可以删除
    bind(a)
  • 如果
    bind(a)
    在一个块中出现两次,则最后一次无效

  • 您将无法在编译级别执行此操作。相反,如果您真的担心这类错误的时间成本,那么管理者对象可能是一种方法:

    class state_manager {
        GLuint current_texture;
        /*Maybe other stuff?*/
    public:
        void bind_texture(gl_texture_2d const& tex) {
            if(tex.handle() != current_texture) {
                current_texture = tex.handle();
                glBindTexture(/*...*/, current_texture);
            }
        }
    };
    
    int main() {
        state_manager manager;
        /*...*/
        gl_texture_2d tex;
        manager.bind(tex);
        manager.bind(tex); //Won't execute the bind twice in a row!
        /*Do Stuff with tex bound*/
    
    }
    
    如果您正在使用,并且您绝对必须直接使用自己的API包装OpenGL调用,那么用户可能需要了解整个绑定到编辑的事情。毕竟,如果他们为了渲染目的绑定了一个纹理,然后试图修改一个纹理,这可能会损坏当前绑定

    因此,您应该将绑定到编辑的概念直接构建到API中

    也就是说,纹理对象(顺便说一句,不应该仅限于2D纹理)实际上不应该具有修改它的功能,因为不绑定OpenGL纹理(或者不绑定DSA,您确实应该学习DSA)就无法修改它。它不应该有
    mirror\u
    等等;这些函数应该是活页夹对象的一部分:

    bound_texture bind(some_texture, tex_unit);
    bind.mirror_u();
    ...
    
    bound_纹理的构造函数
    某些_纹理
    绑定到
    tex_单元
    。其成员函数将修改该纹理(注意:它们需要调用
    glActiveTexture
    ,以确保没有人更改活动纹理单元)

    bound_texture
    的析构函数应自动解除纹理绑定。但是您应该有一个
    release
    成员函数来手动解除绑定