QOpenGLFunctions的使用
1. QOpenGLFunctions 说明
QOpenGLFunctions 类提供了跨平台的OpenGl ES2.0 API版本。
OpenGL 2.0 提供了OpenGL中的子类集合,可以提供跨多个平台的桌面系统以及嵌入式OpenGL的实现。然而,却很难使用子类因为子类需要解决许多平台系统的操作问题。
因此 QOpenGLFunctions提供了这样的API,可以保证在所有的OpenGL系统中使用,并且也关注不同系统中的OpenGL的版本API的使用。Qt推荐直接继承的方式来使用 QOpenGLFunctions类。
2. QOpenGLFunctions 使用
class MyGLWindow : public QWindow, protected QOpenGLFunctions { Q_OBJECT public: MyGLWindow(QScreen *screen = 0); protected: void initializeGL(); void paintGL(); QOpenGLContext *m_context; }; MyGLWindow(QScreen *screen) : QWindow(screen), QOpenGLWidget(parent) { setSurfaceType(OpenGLSurface); create(); // Create an OpenGL context m_context = new QOpenGLContext; m_context->create(); // Setup scene and render it initializeGL(); paintGL() } void MyGLWindow::initializeGL() { m_context->makeCurrent(this); initializeOpenGLFunctions(); }
paintGL函数中可以使用任意的Opengl ES 2.0 API且不需要明确声明。如直接使用glActiveTexture():
written by www.icmzn.com
void MyGLWindow::paintGL() { m_context->makeCurrent(this); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureId); ... m_context->swapBuffers(this); m_context->doneCurrent(); }
An alternative approach is to query the context's associated QOpenGLFunctions instance. This is somewhat faster than the previous approach due to avoiding the creation of a new instance, but the difference is fairly small since the internal data structures are shared, and function resolving happens only once for a given context, regardless of the number of QOpenGLFunctions instances initialized for it.
可选的方式是查找当前环境关联的QOpenGLFunctions实例, 这比之前快,因为避免了新实例的创建。但是,差异不大因为内部数据结构是共享的,且函数解析往往只在给定的环境中调用一次。
QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions();
glFuncs->glActiveTexture(GL_TEXTURE1);
QOpenGLFunctions provides wrappers for all OpenGL ES 2.0 functions, including the common subset of OpenGL 1.x and ES 2.0. While such functions, for example glClear() or glDrawArrays(), can be called also directly, as long as the application links to the platform-specific OpenGL library, calling them viaQOpenGLFunctions enables the possibility of dynamically loading the OpenGL implementation.
QOpenGLFunctions 提供了对OpenGL ES2.0 包装。包括f OpenGL 1.x and ES 2.0.的子类。只要应用程序链接到指定平台的Opengl库中个,则可以直接调用相应的API,通过借助于QOpenGLFunctions 可以确保能够动态加载Opengl的实现库。
3. 不同版本的 QOpenGLFunctions
The QAbstractOpenGLFunctions class is the base class of a family of classes that expose all functions for each OpenGL version and profile.
QAbstractOpenGLFunctions 类提供了对每个Opengl版本的API函数的基本集合。
OpenGL implementations on different platforms are able to link to a variable number of OpenGL functions depending upon the OpenGL ABI on that platform. For example, on Microsoft Windows only functions up to those in OpenGL 1.1 can be linked to at build time. All other functions must be resolved at runtime. The traditional solution to this has been to use either QOpenGLContext::getProcAddress() or QOpenGLFunctions. The former is tedious and error prone and means dealing directly with function pointers. The latter only exposes those functions common to OpenGL ES 2 and desktop OpenGL. There is however much new OpenGL functionality that is useful when writing real world OpenGL applications.
OpenGL 实现不同平台上的相应的API,因为其可以直接连接到相应平台上的API接口。如在微软系统中,只能提供Opengl 1.1 接口使用。其他的函数必须在运行时解析。传统的解决方法是使用 QOpenGLContext::getProcAddress() or QOpenGLFunctions. 前者直接操作相应的函数指针,因此乏味且容易出错。后者则展示了嵌入式Opengl ES 2 和桌面Opengl的公共接口函数。则在使用Opengl 应用显示渲染时,足够新的函数API。
Qt now provides a family of classes which all inherit from QAbstractOpenGLFunctions which expose every core OpenGL function by way of a corresponding member function. There is a class for every valid combination of OpenGL version and profile. Each class follows the naming convention:
Qt 现在提供了继承自的 QAbstractOpenGLFunctions大家族, 都提供了OpenGl 核心函数对应相应的函数版本。因此对应每个有效的Opengl版本都有相应的类。且每个类遵循下述规约:
上述每个类都继承自 QAbstractOpenGLFunctions 。其中Opengl 3.1 移除了大量的deprecated 函数,因此足够简洁且更加通用的API。而对于Opengl 3.2 ,则采用了定义两种类的方式: Opengl 3.2 core 以及 Opengl 3.2 Compatibility。
对于Core类型的类,则其不包含在前一版本Opengl 3.1中摒弃的函数API;对于Compatibility 类型的类,则其包含所有的函数API在core版本,以及相应的前一版本Opengl 3.1中并且的函数API。通过这样的方法,Compatibility 的类允许用户使用新版本的Opengl,但是也可以保持使用合法的core API . 因此推荐使用 Core的类。
但是需要注意的是,对于API接口实现,如苹果公司,没有实现显影的Compatibility的类,因此,如果你希望使用新的Opengl的API在OSX系统中,你应该确保你使用Core 类通过借助于QSurfaceFormat::setProfile()
Qt 提供了多有版本与Core以及Compatibility的实现,对于Opengl版本Opengl 3.1 到Opengl 4.3,如下所示:
- QOpenGLFunctions_3_1
- QOpenGLFunctions_3_2_Core
- QOpenGLFunctions_3_2_Compatibility
- QOpenGLFunctions_3_3_Core
- QOpenGLFunctions_3_3_Compatibility
- QOpenGLFunctions_4_0_Core
- QOpenGLFunctions_4_0_Compatibility
- QOpenGLFunctions_4_1_Core
- QOpenGLFunctions_4_1_Compatibility
- QOpenGLFunctions_4_2_Core
- QOpenGLFunctions_4_2_Compatibility
- QOpenGLFunctions_4_3_Core
- QOpenGLFunctions_4_3_Compatibility
A pointer to an object of the class corresponding to the version and profile of OpenGL in use can be obtained from QOpenGLContext::versionFunctions(). If obtained in this way, note that the QOpenGLContext retains ownership of the object. This is so that only one instance need be created.
QAbstractOpenGLFunctions * QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile = QOpenGLVersionProfile()) const
函数 QOpenGLContext::versionFunctions可以返回对于该环境中versionProfile相应的QAbstgractOpenglFuncation指针。在使用人一个API之前,需要通过使用当前环境变量通过该函数 QAbstractOpenGLFunctions::initializeOpenGLFunctions()来初始化,然后才能使用。注意:如果这样使用,则当前的Opengl环境变量则仍然是返回的对象指针所致的Object。这是因为只能有一个instance创建。
Before calling any of the exposed OpenGL functions you must ensure that the object has resolved the function pointers to the OpenGL functions. This only needs to be done once per instance with initializeOpenGLFunctions(). Once initialized, the object can be used to call any OpenGL function for the corresponding version and profile. Note that initializeOpenGLFunctions() can fail in some circumstances so check the return value. Situations in which initialization can fail are if you have a functions object for a version or profile that contains functions that are not part of the context being used to resolve the function pointers.
在调用任何的OpenGL functions之前,必须要确保当前的Object已经解决了函数指针指向Opengl 函数的问题。这只需要在初始化initializeOpenGLFunctions()时,执行一次。一旦初始化, 当前的对象Object能够使用来调用Opengl 的API 到相应的版本中。注意:在一些环境中,初始化initializeOpenGLFunctions()也会发生调用失败的情况,因此来检查返回的值。如对于使用的版本不兼容当前的环境的情况下,就会初始化失败。
If you exclusively use function objects then you will get compile time errors if you attempt to use a function not included in that version and profile. This is obviously a lot easier to debug than undefined behavior at run time.
如果你仅仅(只,独家)使用函数Object,如果你调用该函数对象之外的版本API,则将会返回兼容的异常。
TYPE * QOpenGLContext::versionFunctions() const
该函数则返回当前环境中的函数版本的函数对象指针。同时,也要在使用之前调用initializeOpenGLFunctions来再次初始化该函数对象,将该对象重新绑定到当前的环境实例中。
一般都是来使用该函数的模板类型,从而可以自动转换为正确的函数来行。因此是可以请求一个不同版本的函数对象,即与当前环境对象中的函数对象不同。即如下图采用模板方法来获取指定的函数对象版本。
代码示例:
QOpenGLFunctions_3_3_Core* funcs = 0; funcs = context->versionFunctions<QOpenGLFunctions_3_3_Core>(); if (!funcs) { qWarning() << "Could not obtain required OpenGL context version"; exit(1); } funcs->initializeOpenGLFunctions();
注意:请求其他不同的函数对象也可能会调用失败,并且返回NULL空指针,即请求不满足当前使用环境中的函数对象。例如:
- Requesting a 3.3 core profile functions object would succeed.
- Requesting a 3.3 compatibility profile functions object would fail. We would fail to resolve the deprecated functions.
- Requesting a 4.3 core profile functions object would fail. We would fail to resolve the new core functions introduced in versions 4.0-4.3.
- Requesting a 3.1 functions object would succeed. There is nothing in 3.1 that is not also in 3.3 core.
4. 使用某一个版本的QOpenGLFunctions
QOpenGLFunctions_2_1 ,提供了OpenGL 2.1 的规范。即其包装了Opengl2.1 的规范,可以直接使用Opengl2.1 的API。
endl;