Skip to content

OpenGL in Qt 5.1 – Part 1

This blog is the first in a series that will show how to use OpenGL with Qt 5. In this article, we shall take a very quick look at Qt’s historical support for OpenGL and then go on to describe the first batch of 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 some simple 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 QGLWidget and maybe the various incarnations of the OpenGL-based paint engines. These allow drawing with raw OpenGL or with the convenience of the QPainter API respectively. In addition to these, Qt also offers some helpful 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 directly into the QtGui library. The reason for these changes is that the new Qt Quick 2 renderer is based upon OpenGL and so is now a core part of Qt’s graphical offerings. Also, the new QOpenGL* classes can be used as direct replacements for the older QGL* classes. For new code, the QOpenGL* classes from QtGui are recommended.

Qt 5.0 exposed basically the same subset of OpenGL functionality as Qt 4.8 did, which is pretty much the intersection of OpenGL 2 and OpenGL ES 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 easy to create native windows and OpenGL contexts on any platform. No more messing around with the idiosyncrasies of various platforms to create a context 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 more OpenGL functionality so as to make using OpenGL with Qt simple, elegant and hopefully fun! To this end, KDAB has invested significant resources into 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 some platforms. One of the major reasons for this pain is the need to resolve entry point addresses dynamically at runtime rather than the build time linker being able to do so. For example, on Microsoft Windows, the address of any function introduced since OpenGL 1.1 must be resolved at run-time. That is nearly all of functions used in a modern OpenGL application!

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 the common subset of functions in OpenGL 2 and OpenGL ES 2. These helpers are great, as far as they go. The issues are that QOpenGLFunctions is limited in what it exposes (the above mentioned subset of OpenGL 2 and ES 2) and manual resolving of entry points is extremely tedious and error-prone. Alternatively it is possible to use an external function resolver such as GLEW or GLee. However, it is often a pain to get these to play nicely with Qt in terms of 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 member functions for every function in the requested OpenGL version and profile. 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:

Window::Window( QScreen* screen )
    : QWindow( screen ),
{
    // Tell Qt we will use OpenGL for this window
    setSurfaceType( OpenGLSurface );

    // Specify the format and create platform-specific surface
    QSurfaceFormat format;
    format.setDepthBufferSize( 24 );
    format.setMajorVersion( 4 );
    format.setMinorVersion( 3 );
    format.setSamples( 4 );
    format.setProfile( QSurfaceFormat::CoreProfile );
    setFormat( format );
    create();

    // Create an OpenGL context
    m_context = new QOpenGLContext;
    m_context->setFormat( format );
    m_context->create();

    // Make the context current on this window
    m_context->makeCurrent( this );

    // Obtain a functions object and resolve all entry points
    // m_funcs is declared as: QOpenGLFunctions_4_3_Core* m_funcs
    m_funcs = m_context->versionFunctions();
    if ( !m_funcs ) {
        qWarning( "Could not obtain OpenGL versions object" );
        exit( 1 );
    }
    m_funcs->initializeOpenGLFunctions();
}

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

// Set a vertex attribute divisor
// Used with instanced rendering
// Introduced in OpenGL 3.3
m_funcs->glVertexAttribDivisor( pointLocation, 1 );

// Dispatch processing via a compute shader
// Introduced in OpenGL 4.3
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 classes try hard to minimise the amout of work done in resolving functions by sharing backends containing the actual function pointers. In addition, this approach automatically takes care of context-specific function addresses (e.g. if using multiple threads and contexts or multiple GPUs). The code for these classes is generated automatically by a helper utility so it is easy to update as new OpenGL versions are released.

OpenGL Extensions

OpenGL also has a well-known extension mechanism that allows vendors to introduce new or experimental functionality and API to see if it is useful and well thought out. Unfortunately, if an extension introduces new functions then these too need to be resolved as for other OpenGL functions 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():

 // Query extensions
 QList extensions = m_context->extensions().toList();
 std::sort( extensions );
 qDebug() << "Supported extensions (" << extensions.count() << ")";
 foreach ( const QByteArray &extension, extensions )
     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:

 // Check if extension is supported
 if ( !m_context->hasExtension( QByteArrayLiteral(
          "GL_ARB_instanced_arrays" ) )
     qFatal( "GL_ARB_instanced_arrays is not supported" );

 // Create instance of helper class and resolve functions
 QOpenGLExtension_ARB_instanced_arrays* m_instanceFuncs = 
     new QOpenGLExtension_ARB_instanced_arrays();
 m_instanceFuncs->initializeOpenGLFunctions();

 // Call an extension function
 m_instanceFuncs->glVertexAttribDivisorARB( pointLocation, 1 );

As with the core OpenGL functions, the code for the extensions is generated for easy updates in the future.

Read  Part 2...

About KDAB

KDAB is a consulting company offering a wide variety of expert services in Qt, C++ and 3D/OpenGL and providing training courses in:

KDAB believes that it is critical for our business to contribute to the Qt framework and C++ thinking, to keep pushing these technologies forward to ensure they remain competitive.

Categories: KDAB Blogs / KDAB on Qt / OpenGL / QtDevelopment

Tags: /
is a senior software engineer at KDAB where he heads up our UK office and also leads the 3D R&D team. He has been developing with C++ and Qt since 1998 and is Qt 3D Maintainer and lead developer in the Qt Project. Sean has broad experience and a keen interest in scientific visualization and animation in OpenGL and Qt. He holds a PhD in Astrophysics along with a Masters in Mathematics and Astrophysics.

53 thoughts on “OpenGL in Qt 5.1 – Part 1”

  1. Thanks, nice article. But, what about specific vendor extensions? I mean extension like GL_NV_float_buffer supported by OpenGL 4.3 …

    1. Sean Harmer

      Vendor specific extensions are also provided for. For example QOpenGLExtension_NV_bindless_texture. However, there is only a class for an extension if that extension exposes new API.

  2. What if I have libs and wrappers that use glVertexAttribDivisor etc. naming convention, not m_funcs->glVertexAttribDivisor? This idea renders every possible lib that uses glXXX functions in main scrope useless?

    1. Sean Harmer

      There is another way to use the QOpenGLFunctions___ classes that I did not mention here which is to subclass from the relevant class:

      For example:

      class MyGLStuff : protected QOpenGLFunctions_4_3_Core
      {
      public:
      MyGLStuff()
      {
      initializeOpenGLFunctions(); // Assumes current context

      glVertexAttribDivisor(…);
      }
      };

      Hope that helps.

  3. Does that mean we’ll also get installers for Qt built against native OpenGL on Windows (rather than that awful ANGLE stuff)?

  4. I appreciate that the class interface for GL functions means well, but it is a potential disaster in the making:

    1) GL extensions come out much more often (in particular vendor extension) that Qt versions

    2) a number of OpenGL and OpenGL ES2 extensions have the same name, but are radically different [the biggest one being GL_EXT_separate_shader_objects, for GL that is a based off of fixed function pipeline and for GLES2 it is for programmable function pipeline and looks more like GL_ARB_separate_shader_objects].

    3) attempting to wrap GL functions in macros to make tracing GL errors is utterly hosed now in Qt.

    One of the justifications for this system is that the GL extension helper headers conflict with Qt headers should make everyone worry: this means that Qt does naughty things in the global namespace. Old crankly GL developers that have had to deal with Qt already know this on embedded: including EGL headers under a large variety of conditions in an X11 environment yields all sorts of bizarre compile errors.

    This seems like utter over-engineered non-sense too. Come on people, a whole set of freaking classes just to fetch function pointers? SDL, had one simple function to do this [to handle the hassle where core functions are not returned by the function pointer fetcher function of WGL and EGL]. Worse, the files implementing this stuff is likely machine generate [which is fine], but the machine generate file is in the repos, the header file alone is 903K . Brilliant, an almost 1MB header file for this. In contrast, GL/glext.h, the file that defines all the extensions is at 234K.. oodles smaller and much more trivial for a compiler since all it defines is functions (and macros).

    This is begging for all sorts of un-fun since there are member functions with the same exact names as the GL functions. Brilliant. I shudder at the syntax of passing these function addresses around (since member functions pointer syntax is terribly ugly). Going further, some the the Qt wrapped GL functions do _different_ things than the GL functions [glBindFramebuffer for instance]. This is done in the name of being useful, but will quite likely make all sort of problems later down the line.

    1. Sean Harmer

      I appreciate that the class interface for GL functions means well, but it is a potential disaster in the making:

      “Disaster” seems a little strong.

      1) GL extensions come out much more often (in particular vendor extension) that Qt versions

      Qt has moved to time-based releases with a period of approximately 6 months. So although there may be some lag between new extensions being released and a Qt helper for it becoming available it is not going to be very long.

      2) a number of OpenGL and OpenGL ES2 extensions have the same name, but are radically different [the biggest one being GL_EXT_separate_shader_objects, for GL that is a based off of fixed function pipeline and for GLES2 it is for programmable function pipeline and looks more like GL_ARB_separate_shader_objects].

      The classes are simply enablers. Nobody should expect the existence of such classes to be a substitute for knowing what they are doing. If using such extensions then code would likely be protected by #if defined(QT_OPENGL_ES_2) or even in compilation units that are conditionally compiled based upon the build target. For the particular extension you mentioned, the only thing they have in common is the name. The entry points, and hence member functions are different, so trying to use the ES2 extension in code compiled for desktop GL will result in a compilation error.

      3) attempting to wrap GL functions in macros to make tracing GL errors is utterly hosed now in Qt.

      No it isn’t. You can still easily wrap GL function calls in macros if you wish. However, these days it is preferable to use KHR_debug or similar (if available).

      One of the justifications for this system is that the GL extension helper headers conflict with Qt headers should make everyone worry: this means that Qt does naughty things in the global namespace. Old crankly GL developers that have had to deal with Qt already know this on embedded: including EGL headers under a large variety of conditions in an X11 environment yields all sorts of bizarre compile errors.

      One of the original motivations was indeed the difficulties imposed by the Qt headers in Qt 4 times. The OpenGL related headers in Qt have undergone large cleanups in Qt5 so the situation is now much better. I have had no trouble using Qt and OpenGL 3, 4 or ES 2 out of the box on Windows, OS X, Linux, QNX, Blackberry, and embedded Linux on various platforms (e.g. imx53). Others have reported success with the rasp-pi and other platforms. If you know of problematic platforms then please report them.

      This seems like utter over-engineered non-sense too. Come on people, a whole set of freaking classes just to fetch function pointers? SDL, had one simple function to do this [to handle the hassle where core functions are not returned by the function pointer fetcher function of WGL and EGL]. Worse, the files implementing this stuff is likely machine generate [which is fine], but the machine generate file is in the repos, the header file alone is 903K . Brilliant, an almost 1MB header file for this. In contrast, GL/glext.h, the file that defines all the extensions is at 234K.. oodles smaller and much more trivial for a compiler since all it defines is functions (and macros).

      Based on your comment about header file size I assume you are referring to the extensions. So one class per extension is over-engineered? I can’t recall the details of how SDL handles this but one advantage of using class instances to contain the function pointers rather than polluting the global namespace is that it is much easier to handle the case of multiple contexts resulting in different addresses for the same function (e.g. multiple GPUs or even the same GPU on MS Windows).

      Yes the machine-generated header is in the repository, but as noted it is in an optional static library. So people will only pull it in if actually requested explicitly. Even then, it is not as bad as you make out. Some of the file is for desktop OpenGL, the remainder for ES 2 so only the section relevant to the target build get included. Furthermore, much of the file is inline functions which the compiler will only generate code for in the final executable if the function is actually called. So the compiler can happily skip the vast majority of this file.

      As with all of the things here, they are optional. If you personally do not want to use them, then don’t. End of story. For others that cannot be bothered with the hassles of resolving entry points then these classes will help. If people later decide something in them is too heavy they can be replaced with hand-rolled code at a later date.

      This is begging for all sorts of un-fun since there are member functions with the same exact names as the GL functions. Brilliant. I shudder at the syntax of passing these function addresses around (since member functions pointer syntax is terribly ugly). Going further, some the the Qt wrapped GL functions do _different_ things than the GL functions [glBindFramebuffer for instance]. This is done in the name of being useful, but will quite likely make all sort of problems later down the line.

      The naming is a simple one-to-one mapping from OpenGL function to member function so as to not introduce any surprises. Why do you wish to pass the member function pointers around at all? These are objects, pass a pointer to the object then call the member function or depending upon the structure of your code it might be easier just to create a second instance (for an extension class) or fetch cached instance from the QOpenGLContext (for core functions class). The only callback functions that I can think of off-hand in OpenGL are the ones relating to the various debug extensions. Even with those the callback is a user-defined static non-member function.

      Your statement about the glBindFramebuffer wrapper is incorrect. These classes do not introduce any custom behaviour, they are simply thin wrappers that resolve entry points. If you are referring to the QOpenGLFramebuffer::bind() function, then yes it does add additional behaviour but that is clearly documented.

      1. > Your statement about the glBindFramebuffer wrapper is incorrect. These
        > classes do not introduce any custom behaviour, they are simply thin
        > wrappers that resolve entry points. If you are referring to the
        > QOpenGLFramebuffer::bind() function, then yes it does add additional
        > behaviour but that is clearly documented.

        Get it correct. My statement about glBindFramebuffer is correct. It substitutes 0 with the default framebuffer. That is NOT the same behavior as GL vanialla glBindFramebuffer. Now enter C++ code, someone write glBindFramebuffer(0) within a class or outside a class and it does DIFFERENT things because it is a different function getting called.

        > No it isn’t. You can still easily wrap GL function calls in macros if you
        > wish. However, these days it is preferable to use KHR_debug or
        > similar (if available).

        You are kidding right? One of the most important bits for debugging is a file and line number that originated the bad GL call. The only way to insert that data is via macros. KHR_debug provides a means of creating labels, but to get line and file one needs macros. But ok, you can still do the macro thing right? That is a big freaking depends. Suppose the macro system is something as simple as:

        GL_call(function_name, arguments)

        template_GL_call(function_name, arguments, __FILE__, __LINE__);

        where template_GL_call is a template function using the function pointer type and arguments to do the right thing. This will not work with the Qt system because in the Qt system you need to pass a this pointer to make the above work. *OH*. But ok, then one can then do a redefine like this, via machine generate jazz:

        #define glFoo(a,b,…) debug_glFoo(a,b,c,…, __LINE__, __FILE__)

        where debug_glFoo is implemented in a C/C++ machine generate file. This does not work either because Qt headers will have the same exact function names as the GL as class member functions.

        This entire hassle could have been avoided if the Qt class member functions where different, for example dropping the gl prefix, or using a slightly different prefix, say for example qtgl. You could make the argument that one could define one’s gl calling functions with one’s own prefix, so a developer code would one do

        my_glFoo

        which expands as according to a macro. But this is wrong. Qt made the addition, not the developer. Moreover, in light of glBindFramebuffer doing different things, then it is really important to know precisely which one is called. Again the simplest solution would have been for the qt class member functions to use a different prefix than gl.

        There are a number of situations where one does pass function poonters around (typically to do very similar things that have similar usage patterns, for example querying attributes and uniforms of a GLSL program). Now one needs to pass the this pointer around and use that particularly hideous pointer to member function syntax. Admittedly it does not happen often, but it does happen and is useful.

        1. Sean Harmer

          Get it correct. My statement about glBindFramebuffer is correct. It substitutes 0 with the default framebuffer. That is NOT the same behavior as GL vanialla glBindFramebuffer. Now enter C++ code, someone write glBindFramebuffer(0) within a class or outside a class and it does DIFFERENT things because it is a different function getting called.

          That would be true only if we redefine the function in the global namespace which we are not doing, these are member functions of a class. OK if you subclass then you should care for what function you are calling. However, the QOpenGLFunctions_4_3_Core class and friends do not introduce any custom behaviour at all. These are not the subject of this blog though.

          The code you are thinking of is in QOpenGLFunctions which is the historical set for the 2.x/ES2 common subset or maybe in QOpenGLFramebufferObject::bind(). Also as I pointed out earlier where Qt does introduce custom behaviour it is documented that is does so.

          You are kidding right? One of the most important bits for debugging is a file and line number that originated the bad GL call. The only way to insert that data is via macros. KHR_debug provides a means of creating labels, but to get line and file one needs macros.

          No I am not kidding at all. First of all let’s take KHR_debug, this can be executed such that the message callback is called synchronously. Therefore in your callback you can print out the precise call stack that led to the error which is even more information than file name and line number.

          Also, macro-based debugging still works perfectly fine. For example assume we have a class that inherits from QOpenGLFunctions_4_3_Core (the simple wrapper class with no additional logic):


          #define _DEBUG
          #ifdef _DEBUG
          static void checkOpenGLError( const char* stmt, const char* function, const char* file, int line )
          {
          GLenum err = glGetError();
          if (err != GL_NO_ERROR)
          {
          qDebug() << "OpenGL error" << hex << err << dec << "at" << stmt << "called from" << function << "in file" << file << "line" << line; abort(); } } #define GL_CHECK(stmt) do { \ stmt; \ checkOpenGLError(#stmt, Q_FUNC_INFO, __FILE__, __LINE__); \ } while (0) #else #define GL_CHECK(stmt) stmt #endif

          Then in code call as:


          void BasicUsageScene::render()
          {
          // Introduce a GL_INVALID_VALUE error
          GL_CHECK( glClear( /*GL_COLOR_BUFFER_BIT*/ GL_TEXTURE_2D ) );
          GL_CHECK( m_vao.bind() );
          GL_CHECK( m_shaderProgram.bind() );
          GL_CHECK( glDrawArrays( GL_TRIANGLES, 0, 3 ) );
          }

          this then aborts with output of "OpenGL error 501 at glClear( GL_TEXTURE_2D ) called from virtual void BasicUsageScene::render() in file ../ex_debug_macro/basicusagescene.cpp line 66"

          As for passing around function pointers and a pointer to the object, well there are solutions for that sort of thing. I agree that the C/C++ syntax for function pointers is horrible though.

          Once again, if you don't find this sort of thing helpful then fine just don't use it. Meanwhile, others have found it useful. At the end of the day, it's another design choice.

          1. Ok, let me get this straight, you think it is a good idea to have a developer explicitely do:

            SOME_MACRO()

            wrapped around each GL call? This is not only ugly, it is not going to work for GL functions that return a value. Rather than harping on how bad what Qt has is, I will point in a direction that would be better:

            0) Do not use the prefix gl for these member functions. Use a different prefix, so that at a glance one can know it is a member function or not.

            1) Go a step further. Rather than use member functions, just make the pointers to functions public declared with the const modifier. That way no one will accidentally change their values. Have the implementation of assigning their values do the ugly thing of the const_cast. By having simple function pointers, one can use these symbols exactly as one would anywhere else.

            2) Go even further. One of the points of these classes is that sometimes the function pointers returned are different subject to what GL context. Rather than have an end developer must keep track of what GL context was curernt when those objects loaded their function pointer, make the QGLContext objects themselves have the objects that store the function pointers. This automatically has that the correct function will be used from the currect GL context. Win-Win.

            3) Even further, one can then add a member function, for each GL function, that has a pre-code and post-code that a user can override. Such pre-code can be for example calling the GL function directly to create a label for KHR_debug, writing to a log file, whatever. One can have that under the pre and post code are made active only under debug for example, or possible decided by properties of the QGLContext before it creates the underlying GL context. Implementation would be handled by member function pointers to avoid extraneuos if’s in the execution.

            The above is admittedly harder to implement and requires more for-thought that the current system, but it would be so much more useful for debugging, logging, etc.

          2. Sean Harmer

            Ok, let me get this straight, you think it is a good idea to have a developer explicitely do:

            SOME_MACRO()

            wrapped around each GL call? This is not only ugly, it is not going to work for GL functions that return a value.

            I didn’t say it was pretty, macros often aren’t, but yes it does work for functions that return a value, just call GL_CHECK( val = glIsEnabled(blah) ) for example.

            Thank you for your other suggestions, we’ll take a good look at them. Please note that for the function objects for the core functionality the QOpenGLContext already caches the object per-context as you suggest in item 2). We can look at enabling this for the extension functions too.

            For 1), the shared back-end classes used in the implementation contain the raw function pointers, perhaps these could be exposed.

          3. One thing worth mentioning that QGLOpenGLContext does get right, it does do 2), i.e. the function pointer object is fetchable for the context, but the extension function stuff does not follow this.

          4. Sean Harmer

            Yes this was due to the extensions being split out into their own static lib. Would still be possible of course, just requires some extra casting.

  5. very nice series of articles. I’ve just recently started to use Qt for my software projects and I love it. And it is great that there is more and more support for OpenGL in it. Thanks for all the wok. I hope OpenCL will also get support like this. BTW, please do add all the links to other articles from this series to this first post (or maybe even have the whole set of links at the end of each article).

    1. Sean Harmer

      Yes, I would love to see OpenCL support added too. I don’t know if anybody is looking into this or not. Yes, I will add cross-links to the other articles once they are published.

  6. Thanks Sean, I appreciate your articles. I hope they will keep providing Qt with -opengl desktop config. I have one question however. Why would I use QopenGL and not QtOpenGL modules if I recompile with -opengl desktop option (when working with OpenGL 4.x)?

    1. Sean Harmer

      Hi, the class in the QtOpenGL module are deprecated and have a QWidget dependency. Of course if you want to you can still use QGLWidget but the other classes all have more up to date equivalents in QtGui which can all be used as drop-in replacements. For example, you can create a QGLWidget and then instead of using QGLShaderProgram, use QOpenGLShaderProgram.

      The reason this works is that internally QGLWidget creates a QGLContext, and that is in turn implemented in terms of a QOpenGLContext from QtGui.

      The QOpenGL* classes in QtGui will continue seeing further development and improvement, whereas the ones in the QtOpenGL module will not. Hope that helps to explain it.

    1. stereomatching,

      You need to enable to compatibility profile to do the most simple drawing in OpenGL. They (OpenGL, not Qt) really, really don’t want you doing anything at all outside of shaders. To enable, put this in your QGLWidget constructor:

      QGLFormat qglFormat;
      qglFormat.setVersion(3, 2);//Or whatever your version is here.
      qglFormat.setProfile(QGLFormat::CompatibilityProfile);

      setFormat(qglFormat);

  7. Thanks for the writeup. I would like an example showing exactly how to do simple drawing with a QGLWidget that inherits from QOpenGLFunctions_major_minor_profile.

    Before, I was just inheriting from QGLFunctions, which worked fine. Now, I inherit from the profile class, things are completely different and I see no documentation explaining it.

    First, calling initializeOpenGLFunctions() will return false and nothing will work. After much searching, I found that I must do this in the constructor:

    QGLFormat qglFormat;
    qglFormat.setVersion(3, 2);
    qglFormat.setProfile(QGLFormat::CoreProfile);

    setFormat(qglFormat);

    After doing that, initializeOpenGLFunctions() returns true, but then nothing draws.

    Is there any good documentation or tutorial out there that show how to properly derive from and use the OpenGL core profile classes? This would be very helpful because at the moment, they are not simple replacements. Thanks.

    PS – I am using a core profile version below what my card supports, so it should be fine.

  8. A very nice guide for opengl learners! However, I get a compile error in Qt 5.1 on
    statement m_funcs = m_context->versionFunctions();

    error: invalid conversion from ‘QAbstractOpenGLFunctions*’ to ‘QOpenGLFunctions_4_3_Core*’ [-fpermissive]

    How to solve this problem?

    1. Sean Harmer

      Try using the template version of the function like this:

      m_funcs = m_context->versionFunctions<QOpenGLFunctions_4_3_Core>();

      1. If QOpenGLContext is properly done you should be able in integrate Ogre like you would in GLFW, SFML, SDL, …. or anyother windowing toolkit.

        I haven’t tested it yet. But hopefully there isn’t a ton of abstraction there that will mess things up. If not it should be cake to integrate Ogre.

  9. I’m working with Qt 4.8 and evaluating 5.1. In 4.8 I integrated with Ogre3D by creating a native widget and drawing opengl on the native window. Is there an equivalent object that plays well with qquick?

  10. Would you update your post and add the #include’s and modules needed for the examples? Being a noob it’s not obvious.

    Thanks

  11. Hello Sean,

    Is it possible to use the WGL_AMD_gpu_association or the WGL_NV_gpu_affinity extensions to choose the graphic card for the QOpenGLContext?

    We tried it with setting the QScreen for the Context with Windows 7 and two NVIDIA Quadro Graphic cards, each connected with one screen, but the result was that only the first graphic card renders the two contexts.

    Is there any way to choose the gpu for a QOpenGLContext?

    Thanks

  12. I am new to opengl in qt especially the core profile. Could you provide a full and simple example to draw triangle that use QWindow?

    1. Sean Harmer

      Hi, yes I plan to do a blog series showing how to do just this. I’ll try to get this done soon.

  13. Apart from the Qt bug that you can’t use the core version of opengl, this blog was a lifesaver, without it I would have abondoned Qt by now. The new Qt openGL window example just freezes and crashes, it would be great if you posted source code that acually works. For me it would have saved a lot of headaches.

    1. Sean Harmer

      Hi, what’s the problem with using an OpenGL Core profile with Qt? Which version of Qt are you using? Is this with QWindow or with QtQuick 2? Which platform?

    1. Sean Harmer

      Ah, indeed QPainter and OpenGL Core profile do not play nicely together yet. For info I am currently fixing the Qt Quick 2 renderer to work with a Core profile context. This should make it into Qt 5.2.0. I have it working locally and am just tidying up the patch and testing on all platforms that I have access to.

  14. The current context seems will not return the correct opengl version

    For Windows 8 run on VMWare with Mesa Driver 7.14.1.5025 OpenGL 2.1(Callium 0.4 on SVGA 3D Build Release with 130, 2.1 mesa 8.1-devel (git-48a3d4e)) , it return the glversion 2.0 instead of 2.1

    For Windows 7 Nvidia GeForce 405 Driver 9/8/2010 8/17.12.5965 Opengl 3.3.0,
    it return the glversion 2.1 instead of 3.3

  15. If I am deploying to a mobile device, let’s say Android or BlackBerry, could I use :
    QOpenGLFunctions_4_3_Core

    or I need to use:

    QOpenGLFunctions_ES2

    1. Sean Harmer

      The latter. The former is for use on the desktop when you have OpenGL 4.3 support available.

      Hopefully when nVidia release the Tegra 5 we’ll also be able to use OpenGL 4.3 on that embedded target too.

  16. This is all great stuff. Where I am having troubles is getting beyond building ticker toy examples. A good blog on how to build objects for rendering with opengl (using qt vao and vbo , shaders for different objects etc.) what are the best practices to use Qt’s objects in a real world application that renders from even 3 different objects would clear up alot.

    Would I pass something (QOpenGLContext *) to each object from the render function on the QWindow?
    do I get a VAO from each object and render it from the QWindow itself? how does shaders get attached to the VAO’s.
    does the object need to have Context when creating or building VAO/VBO’s with Qt objects? It’s all just not quite clear enough to know how Qt envisioned it to be used. QGraphicsView is well documented with good solid examples that shows the functionality used correctly.

    I can follow along with many tutorials and books off the internet but none seem to address the bigger picture.

    If some of the examples from the QtDD presentations were available it could help sort out how to get my sea legs with this stuff.

    Thanks so much!!

  17. QGLWidget::setFormat is obsolete now. So how can I change my custom QGLwidget’s QGLFormat at runtime (without passing it to the QGLWidget ctor)?

  18. Hello, nice article series. I also watched your Modern OpenGL techniques at QtDD12, and I am glad to see that is a good OpenGL showcase. But you never discuss too much about Qt-specific features which we can’t find on any opengl book. For example: how to use OpenGL inside a regular Qt application? How to render multiple OpenGL scenes? How a context/scene can be shared between multiple windows? How do QOpenGL* classes shall be used? These are the things that regard Qt, and nobody cares to explain (but are precious to developers!).
    I believe that answering this kind of questions will be very valuable to Qt community as well as OpenGL community.

  19. QOpenGLContext doesn’t differ from QGLContext very much, which is good for team’s learning path.
    But, without a proper opengl widget, things get complicated a lot. Even with the handy createWindowContainer wrapper, some layout bugs, device-lost problem and performance issues still frequently popup especially when used together with the new Fusion theme.

    Additionally, I cannot seem to find how to turn off the vertical sync with QSurfaceFormat. Where in QGLFormat, one can simply set swap interval, QSurface only provides swap behaviors, none of them really turns off VSync.

    Any suggestions?

    1. Sean Harmer

      You can still use QGLWidget. Internally it uses QOpenGLContext anyway. There will be a QOpenGLWidget coming in Qt 5.4.

      QSurfaceFormat now has setSwapInterval(int) which you can call with a zero argument to disable vsync (or -1 for adaptive vsync).

  20. Dear Sean Harmer,

    Thank you for really helpful article! It really helped me grasp the status quo for Qt5 + OpenGL which would otherwize be shrouded in a haze for me.

    I arrived here from google with a rather difficult quest, and I was hoping that you could help me on my way. We are currently developing a Qt5 application (currently on 5.2.x) for debian x64, and for different reasons we have moved away from our original target hardware and landed on Intel atom with pineview graphics chipset.

    This does not work optimally with our QtQuick code. It is slow, buggy and just horrible. When I talk to Qt people about this they say this is exclusively related to the graphics hardware and drivers, and there are no work-arounds for Qt. When I talk with the devs behind the intel graphics driver they say that pineview is quite good, but it falls back to software rendering when you try to use certain opengl 2 features which it is not made to support.

    So, my question is, is it at all possible to coax Qt to restrict its dependancy on any of the opengl2/openglES2 features, or drop it completely in favour of the older opengl1 standard?

    Any suggestions are gratiously accepted, thanks!

    1. Sean Harmer

      Sorry but I have no experience of that particular chipset. However, QtQuick2 uses only OpenGL ES 2 features but it does require at least OpenGL ES 2 (or OpenGL 2.x) as it makes extensive use of shaders.

      Have you tried profiling to see where it gets very slow? Take a look at both the CPU side and also GPU side with a tool like apitrace.

      Good luck!

  21. Hello Mr. Harmer,

    Could you give me some advices about method for picking points / triangle elements in 3D opengl scene?
    Coventional name stroring method does not work properly, and color poicking method , might be better choice? gluUnProject did not worked properly Qt 4.x versions as I remember correctly. Do you think, gluUnProject works in Qt 5x?

    Thanks for you reply,

    1. Sean Harmer

      Picking and selection are undergoing development right now. We know exactly what form it will take yet. At present we are focussing on ray casting.

      1. Thanks for your reply. Dont you think that raycasting algorithm is slow for huge rendering system (3-5 million points)? I need to calculate intersections and check the all nearest points.
        If I store all coordinates in one QVector or QHash, It takes time to check nearest points.

        Thanks for your helping.
        Regards,
        Zsolt

        1. Sean Harmer

          It depends 🙂 Usually one would use some kind of spatial structure to eliminate non intersecting sub trees. Then proceed to a narrow phase where if needed you can test against individual triangles.

Leave a Reply

Your email address will not be published. Required fields are marked *