我目前正在使用Qt5 gui模块访问OpenGL函数。
然后我发现QOpenGLFunctions很有用,因为:

  • 它包装用于桌面的OpenGL和OpenGL ES,确保我以“便携式”方式使用OpenGL API。
  • 我不必担心会包含OpenGL header ,Qt会为我做。

  • 但是,我对使用它的正确方法存有疑问。
    以下几行仅列出了我知道的使用此类的三种方式。
    我的问题是:是否有使用QOpenGLFunctions的好方法?

    继承自QOpenGLFunctions

    Qt官方文档说:“从QOpenGLFunctions继承您的类,并像以前一样使用glXXXX类。但是我不喜欢这样:
  • 如果我的类(class)以前曾希望从另一个类(class)继承,则我必须进行多重继承。我不是那种东西。即使这样的情况无论如何都是安全的,它还是一种美学……
  • 每个glXXXX包装类都是非常量的。我会强制所有使用OpenGL的方法都是非常量的。那并没有太大的意义。是的,当我执行OpenGLFunctions时,glClear(...)类可以合法地是非常量的,但是为什么我的方法DrawableShape::render(...)是?

  • 关于从QOpenGLFunctions继承。它的构造函数可以接受一个参数:当前的OpenGL上下文。这个参数对我来说似乎很重要,但是没有Qt文档调用此构造函数。相反,它们让编译器选择无参数构造函数。

    具有QOpenGLFunctions作为成员

    另一种想法应该是让QOpenGLFunctions实例作为任何调用glXXXXX函数的类的成员,或者至少是对一个实例的引用,并从该实例调用每个OpenGL函数。

    传递QOpenGLFunctions作为参数

    对于使用OpenGL的每个函数,调用方都发送QOpenGLFunctions。这边走 :
    void renderRectangle(QOpenGLFunctions& opengl) const;
    

    但是我怎么能确定这个功能会需要它,而这个函数却不需要呢?我的意思是源代码会随着时间的推移而变得越来越大,而且我担心看到类的每个方法接收此参数的风险。

    最佳答案

    遵循其他面向对象的包装器库的相同原理,您可以考虑对第三种选择进行小的改动。

    定义一个代表您当前的opengl上下文的类,该类也扩展了QOpenGLFunctions

    class GL : public QOpenGLFunctions{
    
      QGLContext& context;
    
      GL(QGLContext& c) : glContext(c){ ... }
    
    };
    

    渲染线程将初始化提供当前上下文的GL实例,并将其传递给需要执行opengl操作的所有渲染实例。这样,您还可以确保在初始化和使用opengl结构和缓冲区时不会混合多个上下文。
    class Visualizer{
    
     void glInit(GL& gl){ ... }
    
     void glPaintOpaque(GL& gl){ ... }
    
     void glPaintTranslucent(GL& gl){ ... }
    
    };
    

    07-26 09:43