Question

I have read all the questions on SO that i could find about qt 4 and 5 opengl. This one came the closest OpenGL vs QOpenGL/QtOpenGL in Qt 5: differences and limitations? , I have no idea why it was closed because its a great question. The only aspect I see it missing is the speed difference.

I have also read this https://qt-project.org/forums/viewthread/22921 which had a similar question, but as the back and forth about 4 vs 5, mostly discussing new features.

My question is, is using the built in methods of QT5 faster than making a custom widget using the opengl API directly? If I am concerned about performance, is using QT a bad choice and there

EDIT:

To be a little more specific, I need to use physx, tcp/ip communication, and large numbers of quickly updating vertices and meshes. The goal is to do this as close as realtime as possible. Things like rendering is not a concern, but any bit of overhead from qt is damaging. (Everything is in 3D with C++)

Was it helpful?

Solution

I have read all the questions on SO that i could find about qt 4 and 5 opengl. This one came the closest OpenGL vs QOpenGL/QtOpenGL in Qt 5: differences and limitations? , I have no idea why it was closed because its a great question. The only aspect I see it missing is the speed difference.

To be a little more specific, I need to use physx, tcp/ip communication, and large numbers of quickly updating vertices and meshes. The goal is to do this as close as realtime as possible. Things like rendering is not a concern, but any bit of overhead from qt is damaging. (Everything is in 3D with C++)

There are multiple questions in your question.

"Raw" OpenGL vs "Qt" OpenGL

This question is ill posed, in that there's no such thing as "Qt OpenGL". OpenGL is the standard owned and published by Khronos. Qt just uses it.

What Qt can do for you is helping your application manage several things.

Window/context creation

Have you ever tried creating an OpenGL context under Win32? It requires a bunch of boilerplade code (see here or here), which involves creating a temporary context to check for WGL capabilities, then creating the actual context in the end...

Have you ever tried creating an OpenGL context under X11? It requires a bunch of boilerplade code (see here), which involves checking for GLX_ARB_create_context presence and then use it to create the context, or fall back to a GLX 1.3 code path and...

Have you ever tried creating an OpenGL context under Mac OS X?

Have you ever tried creating an OpenGL context under Android?

Have you ever tried creating an OpenGL context under QNX?

Have you ever tried creating an OpenGL context under DirectFB/EGLFS?

Oh, wait. Here it comes Qt:

class Window : public QWindow {
    QOpenGLContext *context;
public:
    Window() {
        QSurfaceFormat format;
        format.setVersion(3,3);
        format.setProfile(QSurfaceFormat::CoreProfile);

        setSurfaceType(OpenGLSurface);
        setFormat(format);
        create();

        context = new QOpenGLContext;
        context->setFormat(format);
        context->create();
    }
...

Yup, that's all. That creates a (toplevel) OpenGL window and a 3.3 Core Profile context. Combine it with a QTimer and you have a viable renderer. Which of course will work on all the above platforms: Win32, Mac, X11, Linux/EGLFS, QNX, iOS, Android.


Is there an overhead you have to pay for all of this? Yes, of course. But that's absolutely negligible; and you pay for it only once, i.e. when you create the window and the context.

The real heavy stuff comes from the OpenGL drawing itself, which is totally under your control: you make the context current on the window and start issuing raw OpenGL commands. Qt is not in the way there. The only moment when Qt and OpenGL will meet again will be at swap buffers time; but that's an operation that has virtually no cost.

So: Qt does not add any measurable overhead.

Window management

Of course, bundled with the above comes the fact that you can f.i. handle keyboard and mouse input with identical code across any of those platforms. Or resize the window. Or make it fullscreen. Or close it.

OpenGL helpers

Qt doesn't "just" offer a way to create an OpenGL surface and context (and the related operations: set as current, swap buffers, etc.). It goes (much) further, and offers a whole array of helper classes and functions:

  • QMatrix4x4 is a... 4x4 matrix. Which has all the nice functions you need in an OpenGL program: lookAt(), ortho(), perspective(), normalMatrix(), and so on.
  • QOpenGLContext::hasExtension and QOpenGLContext::getProcAddress are platform independent ways of resolving OpenGL entry points.
  • QOpenGLContext::versionFunctions returns an object containing all the OpenGL entry point for a given version/profile already resolved.
  • QOpenGLBuffer wraps a buffer object.
  • QOpenGLVertexArrayObject wraps a vertex array object (and has a RAII helper to bind and unbind the VAO).
  • QOpenGLTexture wraps a texture object.
  • QOpenGLFrameBufferObject wraps a frame buffer object.
  • QOpenGLShader and QOpenGLShaderProgram wrap shaders and shader programs, offering convenience methods for f.i. setting a QMatrix4x4 as a uniform variable. So, you can calculate the MVP for a given mesh on the CPU using the methods mentioned above, then set it as uniform.
  • QOpenGLDebugLogger wraps GL_KHR_debug for debugging your OpenGL applications.
  • and another bunch of stuff I don't remember right now.

Is there an overhead? Yes, but once again it is minimal, and it does not involve how you use those objects in your OpenGL code. If your OpenGL code is fast and well structured, you'll find those helpers useful to manage it, and they won't make it run any slower.

(Example of "useful to manage it": QOpenGLVertexArrayObject will let you use a VAO on OpenGL 3.0, or on any Desktop OpenGL version where the GL_ARB_vertex_array_object extension is present, or on OpenGL ES2 if GL_OES_vertex_array_object is present. You don't need to resolve the right set of functions depending on the runtime. Qt will do that for you and provide the same APIs for creating, binding, releasing and destroying a VAO).

Is everything that good? No. I must be honest here, there are bits and bolts which would benefit from some love.

For instance, QOpenGLFrameBufferObject has a limited API, not supporting f.i. any amount of color attachments. QOpenGLBuffer would need some work for supporting more buffer types / binding targets. There's still no support for program pipelines. There's still no support for uniform buffers.

On the other hand, you have things such as QOpenGLTexture, which supports quite recent features such as immutable storage and texture views.

Does that mean you can't use those features? Of course you can. Just go back to raw OpenGL code if you need features Qt doesn't give you right now. Or, consider contributing those features to Qt!

Qt

Of course, once you go the Qt path, you have Qt. Which means, in the QtCore and QtGui libraries alone:

  • event loops
  • timers
  • signals and slots
  • threads
  • Unicode strings + i18n
  • containers
  • regular expressions
  • file handling
  • plugin loading
  • settings
  • mimetypes
  • input handling
  • image I/O
  • 2d imperative painting using a raster engine
  • JSON
  • XML
  • and another bunch of stuff I don't remember right now.

Of course, all of the above is cross platform.

By the way, Qt also has:

  • QtWidgets for cross platform 2d widgets
  • QtSql for DB access
  • QtNetwork for TCP/UDP/SSL sockets, as well as a high level HTTP/FTP engine
  • QtTest for unit tests
  • QtWebkit for embedding webkit
  • and another bunch of stuff I don't remember right now

OpenGL in Qt 4 vs 5

Are there any huge differences between how OpenGL is handled in Qt 4 vs Qt 5? Not really...

In Qt 4 the class to use to do OpenGL rendering was QGLWidget. It lived in the QtOpenGL module (and not in QtGui -- remember that in Qt 4 widgets lived in QtGui too). Also, what's actually a subset of the Qt 5 OpenGL helpers I listed above was available there under a QGLFoo name (f.i. QGLBuffer instead of QOpenGLBuffer).

In Qt 5 the QtOpenGL module is still there to keep old applications work. But:

  • QtGui and QtWidgets were split. QtGui now contains the low level bits to handle WM, creating GL contexts and surfaces, 2d painting, and basically the stuff I listed above. QtWidgets instead contains the widgets themselves.

  • QtOpenGL still contains the QGL* classes, but now links to QtWidgets (as it contains QGLWidget). This means that using QGLWidget means you'll link to a somehow big library even if you're not using widgets at all (because f.i. your app is pure OpenGL).

  • As I've shown before, QtGui is enough for creating a toplevel OpenGL window. But what if you want to embed it in a widgets-based application? Then you can still use QGLWidget or embed the QWindow via QWidget::createWindowContainer. Apart from QGLWidget, you shouldn't be using any other QtOpenGL (i.e. QGL) class. Use the counterparts in QtGui (i.e. QOpenGL classes).

  • All the above QOpenGL* classes are in QtGui, not in QtOpenGL; and they are more than the QGL* counterparts (e.g. there's no QGLVertexArrayObject), they have more features (e.g. QOpenGLShader supports geometry and tessellation shaders, QGLShader doesn't), and in general the ones to use (as they will see bugfixes and improvements, the QGL* ones won't).

  • Given that now QtGui offers OpenGL support, it would be natural to expect a QGLWidget replacement appearing directly into QtWidgets. And indeed it will, hopefully in 5.4 (the preparatory work is going into 5.3; but unfortunately the feature itself will miss the feature freeze).


Is there any reason for expecting a huge performance difference between Qt 4 and Qt 5? No. I expect your GL code to perform exactly the same. In the end Qt is not really getting in your way.

Desktop GL / ES 2

You can compile Qt 5 with either "Desktop GL" or "ES 2" support via a configure time switch. It obviously will change which headers QtGui will use when compiling, and what libraries it will link to (libGL or libGLES2, etc.). It will also change the default surface format: the above QWindow code will create a nice OpenGL ES2 surface (and probably fail the context creation since there's no OpenGL ES 3.3, oh well).

But you get the point: with the same code you can also support ES2.

The problem (in my opinion) is that it will also change some other more subtle stuff: for instance QOpenGLShader will insert some macros such as

#define highp
#define mediump
#define lowp

before all your shaders if you're using Desktop GL. The reason is that it allows you to reuse the same shaders in ES2 and Desktop GL, which lacks the precision qualifiers; hence they get erased via macros that expand to nothing.

I think these small things aren't really a gain. Maybe they reduce maintainance for very small and simple shaders (and programs made by only a vertex and afragment shader). It would have been better if Qt hand't tried to be so smart.

But your Desktop GL code path might be using more shader stages; or just in general be using features not available on ES2. Ultimately, it will significantly diverge from your ES2 code path. (Just think that in 3.3 Core you must use VAOs, while ES2 on its own doesn't eve know what a VAO is.)

Personal rant: I hate, hate, hate the fact that ES2 is not like an OpenGL profile or so, and instead sits on its own. And one must basically have a diverged code base just to make ES2 happy. Bah bah bah.

Windows

Enter the World of Pain! also known as the OpenGL driver status under Windows.

Basically, anyone but NVIDIA ships broken OpenGL drivers on Windows.

At least, "out of the box". Upgrading the drivers usually works, but you aren't always in the position of asking the users to upgrade their drivers. They're end users, not pro-gamers. Maybe they don't even have administrator privileges.

This is a problem for OpenGL applications, and especially for one of Qt's strongest tools: Qt Quick 2. Qt tries to work around this problem by using ANGLE, which is a OpenGL ES2 -> Direct3D translation layer. So, under Windows, you have the choice between

  • a Desktop OpenGL build
  • an OpenGL ES2 build via ANGLE

The choices are not equal -- ES2 of course means forgetting about doing any serious Modern GL. But apart from that, reasons for going one way or the other are available here.

Qt Quick 2

This is important and I think deserves a point on its own.

But first let's clarify things: do you need to use Qt Quick 2 to build an OpenGL application under Qt? NO, NO, and NO. Qt Quick 2 is a totally independent technology which also leverages OpenGL for rendering. As such, you can ignore it and just build your OpenGL application.

But what's Qt Quick 2 exactly? It's a library built on top of the QML language, a declarative language born for creating dynamic UIs (and now used for build systems... oh well).

Keep in mind the distinction: QML is the language, Qt Quick 2 is a library with a set of visual items (and C++ APIs for creating your own) which you program in QML.

It happens that Qt Quick 2 uses OpenGL to draw those visual items. This guarantees nice 60 FPS tear-free results, very low CPU usage, all kind of shader-based eye-candy, and so on.

So what? Well, you might be interested at giving it a kick. For instance, the API allows it to be superimposed to any pure OpenGL content you draw. So you could think of using Qt Quick 2 for handing the more traditional UI bits -- buttons, sliders, etc., while you keep control of the rendering of the main content.

Or, you can just ignore the fact it exists and keep playing with OpenGL.

OTHER TIPS

I think that there is a lot of misunderstanding in your question and in the comments it received. The root of the problem is the very loose use of the term "Qt".

Qt is a big cross-platform application development framework. It combines features offered by many stand-alone frameworks. It offers a lot of functionality that is entirely non-gui-related. Namely cross-platform containers, threads, variants, meta object system with introspection, timers, networking, scripting using either qtscript or javascript (via qml), xml, json, state machines, and others. Qt is used for writing web services, for example, without a single line of UI code anywhere.

When it comes to user interface, Qt offers you four UI toolkits. It is entirely your choice which toolkit one you end up using. You can also mix-and-match all of them - you can have parts of your UI implemented in one toolkit, parts in another. Everything depends on your requirements.

I presume that by "Qt5" you mean Qt Quick 2, an implementation of a scene graph and UI toolkit using QML as the description/scripting platform. If all you need is a 2D, scenegraph-based toolkit, then Qt Quick 2 is a good choice. It does not offer any 3D functionality, so for 3D features you're on your own. Qt won't get in your way - in fact, it will help you, since it provides a portable wrapper API for OpenGL that hides some platform differences in getting access to OpenGL. It also provides ANGLE, a bundled implementation of OpenGL on top of Direct3D. This lets you develop in OpenGL while still targeting Direct3D on Windows.

For TCP/IP and general non-ui functionality, you should be using Qt - it makes life very easy. For 3D, you'll be using OpenGL directly via Qt-provided wrappers. You can then choose between OpenGL and ANGLE builds of Qt to decide whether you use the platform OpenGL driver directly, or whether you're using OpenGL implemented on top of DirectX (ANGLE). Since you use physx, you already have good nvidia drivers, and a decent implementation of OpenGL, so not using ANGLE is preferred. That's how I see it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top