• 10351阅读
  • 4回复

[转载]OpenGL in Qt 5.1 – Part 1 [复制链接]

上一主题 下一主题
离线XChinux
 

只看楼主 倒序阅读 楼主  发表于: 2013-03-21
关键词: Qt5OpenGL
原文见;http://www.kdab.com/opengl-in-qt-5-1-part-1/?utm_source=rss&utm_medium=rss&utm_campaign=opengl-in-qt-5-1-part-1



OpenGL in Qt 5.1 – Part 1


Published: March 15, 2013 by Sean Harmer




This blog is the first in a series that will show how to use OpenGLwith Qt 5. In this article, we shall take a very quick look at Qt’shistorical support for OpenGL and then go on to describe the first batchof new features coming in Qt 5.1 that will enhance Qt’s OpenGL support.Upcoming blogs in this series will describe more features and show somesimple examples of how easy it is to use Qt for OpenGL development.


A (very) brief history of Qt and OpenGL


Qt has a long history of supporting drawing with OpenGL. Most Qt developers are aware of QGLWidgetand maybe the various incarnations of the OpenGL-based paint engines.These allow drawing with raw OpenGL or with the convenience of theQPainter API respectively. In addition to these, Qt also offers somehelpful wrappers around other OpenGL object types such as QGLShaderProgram, QGLFramebufferObject, QGLBuffer etc.
During the design of Qt 5, these QGL* classes were marked as "Done"and shiny new QOpenGL* replacements were introduced and placed directlyinto the QtGui library. The reason for these changes is that the new QtQuick 2 renderer is based upon OpenGL and so is now a core part of Qt’sgraphical offerings. Also, the new QOpenGL* classes can be used asdirect replacements for the older QGL* classes. For new code, theQOpenGL* classes from QtGui are recommended.
Qt 5.0 exposed basically the same subset of OpenGL functionality asQt 4.8 did, which is pretty much the intersection of OpenGL 2 and OpenGLES 2. This also happens to be the functionality needed by Qt Quick 2.In addition to the Qt 4.8 functionality, Qt 5.0 also makes it very easyto create native windows and OpenGL contexts on any platform. No moremessing around with the idiosyncrasies of various platforms to create acontext that can support the OpenGL Core profile. Just use QOpenGLContext and save yourself from some grey hairs!
With Qt 5.1, we are beginning the adventure of exposing more and moreOpenGL functionality so as to make using OpenGL with Qt simple, elegantand hopefully fun! To this end, KDAB has invested significant resourcesinto pushing the boundaries with Qt and OpenGL.

Functions, functions everywhere!


OpenGL is, to put it bluntly, a bit of a pain to work with on someplatforms. One of the major reasons for this pain is the need to resolveentry point addresses dynamically at runtime rather than the build timelinker being able to do so. For example, on Microsoft Windows, theaddress of any function introduced since OpenGL 1.1 must be resolved atrun-time. That is nearly all of functions used in a modern OpenGLapplication!
To assist with this Qt has provided a couple of helpful utilities: QOpenGLContext::getProcAddress() and QOpenGLFunctions.The former can be used to perform manual resolution of entry points,whilst the latter is a class that has member functions mapping to thecommon subset of functions in OpenGL 2 and OpenGL ES 2. These helpersare great, as far as they go. The issues are that QOpenGLFunctions islimited in what it exposes (the above mentioned subset of OpenGL 2 andES 2) and manual resolving of entry points is extremely tedious anderror-prone. Alternatively it is possible to use an external functionresolver such as GLEW or GLee. However, it is often a pain to get these to play nicely with Qt in termsof header inclusion order etc.
Enter QOpenGLContext::versionFunctions()! This unassuming little function is your gateway to OpenGL entry point utopia This function can be used to obtain a pointer to an object with memberfunctions for every function in the requested OpenGL version andprofile. Let’s take a look at a simple example. Say we have created a QWindow sub-class on which to render and we now wish to create an OpenGL 4.3 Core profile context and resolve every function. To do so is as simple as:

  1. Window::Window( QScreen* screen )
  2.     : QWindow( screen ),
  3. {
  4.     // Tell Qt we will use OpenGL for this window
  5.     setSurfaceType( OpenGLSurface );
  6.     // Specify the format and create platform-specific surface
  7.     QSurfaceFormat format;
  8.     format.setDepthBufferSize( 24 );
  9.     format.setMajorVersion( 4 );
  10.     format.setMinorVersion( 3 );
  11.     format.setSamples( 4 );
  12.     format.setProfile( QSurfaceFormat::CoreProfile );
  13.     setFormat( format );
  14.     create();
  15.     // Create an OpenGL context
  16.     m_context = new QOpenGLContext;
  17.     m_context->setFormat( format );
  18.     m_context->create();
  19.     // Make the context current on this window
  20.     m_context->makeCurrent( this );
  21.     // Obtain a functions object and resolve all entry points
  22.     // m_funcs is declared as: QOpenGLFunctions_4_3_Core* m_funcs
  23.     m_funcs = m_context->versionFunctions();
  24.     if ( !m_funcs ) {
  25.         qWarning( "Could not obtain OpenGL versions object" );
  26.         exit( 1 );
  27.     }
  28.     m_funcs->initializeOpenGLFunctions();
  29. }


From that point on we can simply use member functions on the QOpenGLFunctions_4_3_Core object. For example:

  1. // Set a vertex attribute divisor
  2. // Used with instanced rendering
  3. // Introduced in OpenGL 3.3
  4. m_funcs->glVertexAttribDivisor( pointLocation, 1 );
  5. // Dispatch processing via a compute shader
  6. // Introduced in OpenGL 4.3
  7. m_funcs->glDispatchCompute( 512 / 16, 512 / 16, 1 );



As you can see, this easily puts all OpenGL functionality into your hands on any platform that supports it. Moreover, the QOpenGLContext, QOpenGLFunctions_4_3 and similar classestry hard to minimise the amout of work done in resolving functions bysharing backends containing the actual function pointers. In addition,this approach automatically takes care of context-specific functionaddresses (e.g. if using multiple threads and contexts or multipleGPUs). The code for these classes is generated automatically by a helperutility so it is easy to update as new OpenGL versions are released.

OpenGL Extensions


OpenGL also has a well-known extension mechanism that allows vendorsto introduce new or experimental functionality and API to see if it isuseful and well thought out. Unfortunately, if an extension introducesnew functions then these too need to be resolved as for other OpenGLfunctions as described above.
There are two stages to being able to use an OpenGL extension:
  1. Check if the implementation supports the extension
  2. If the extension introduces new API, resolve the entry points

Qt helps with both of these steps. To check if an extension is supported we can use QOpenGLContext::hasExtension(). Alternatively to get the complete list of supported extensions use OpenGLContext::extensions():

  1. // Query extensions
  2. QList<QByteArray> extensions = m_context->extensions().toList();
  3. std::sort( extensions );
  4. qDebug() << "Supported extensions (" << extensions.count() << ")";
  5. foreach ( const QByteArray &extension, extensions )
  6.     qDebug() << "    " << extension;


For the second part, we would need to use our old friend QOpenGLContext::getProcAddress(). New in Qt 5.1 though is the module QtOpenGLExtensions. This module builds as a static library and contains a class for every OpenGL extension in the Khronos registry that introduces new API. To use an OpenGL extension we can therefore use code similar to this:

  1. // Check if extension is supported
  2. if ( !m_context->hasExtension( QByteArrayLiteral(
  3.          "GL_ARB_instanced_arrays" ) )
  4.     qFatal( "GL_ARB_instanced_arrays is not supported" );
  5. // Create instance of helper class and resolve functions
  6. QOpenGLExtension_ARB_instanced_arrays* m_instanceFuncs =
  7.     new QOpenGLExtension_ARB_instanced_arrays();
  8. m_instanceFuncs->initializeOpenGLFunctions();
  9. // Call an extension function
  10. m_instanceFuncs->glVertexAttribDivisorARB( pointLocation, 1 );



As with the core OpenGL functions, the code for the extensions is generated for easy updates in the future.
Watch this space for the next installment…






二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线zhanglyl

只看该作者 1楼 发表于: 2013-03-21
我做一个实时系统,数据采集和显示的帧频无法提高,Qt 4.8 和5.0 版的Opengl支持让我太郁闷了,在开发工具的选择上不得不放弃qt,只好自己纯手工写OpenGL的实现……但愿5.1有所改进!

离线彩阳

只看该作者 2楼 发表于: 2013-03-21
回 1楼(zhanglyl) 的帖子
大概有多少帧呢?有的显卡驱动可能会限帧至60。
上海Qt开发联盟,热忱地欢迎你的加入!
离线roywillow

只看该作者 3楼 发表于: 2013-03-21
回 2楼(彩阳) 的帖子
好像是叫垂直同步?
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线彩阳

只看该作者 4楼 发表于: 2013-03-22
回 3楼(roywillow) 的帖子
垂直同步是针对渲染时候由于是一行一行地显示所产生的上下画面错位现象的修正。有些是显卡附带的功能。
上海Qt开发联盟,热忱地欢迎你的加入!
快速回复
限100 字节
 
上一个 下一个