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++)
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.
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.
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.
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.
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:
lookAt()
, ortho()
, perspective()
, normalMatrix()
, and so on.GL_KHR_debug
for debugging your OpenGL applications.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!
Of course, once you go the Qt path, you have Qt. Which means, in the QtCore and QtGui libraries alone:
Of course, all of the above is cross platform.
By the way, Qt also has:
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.
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.
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
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.
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.