For all you 3D and graphics hackers out there this will not be news: writing OpenGL code is a pain.
Well, the Qt Graphics team is coming to save your sanity with the a new project called Qt/3D.
We teased about Qt/3D by putting a few of the foundations for it in Qt 4.6, which will be released very shortly. See the Qt/3D 4.6 features blog post for more details.
At some point Qt/3D will be available as part of Qt itself – exactly what sort of module or library we are not sure just yet – but for now you can try it out via Qt Labs!
With this post we’re pleased to announce that Qt/3D will be available for experimental use via the new Qt/3D labs repo.
Old School OpenGL code gets the Qt Treatment
The trusty old QGLWidget got you past first base: a nice window set up with a OpenGL context ready to go.
But from there you’re on your own with the OpenGL reference book, tearing your hair out writing code like
void My3DWidget::paintGL()
{
QColor clearColor(palette().color(backgroundRole()));
glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QColor color(170, 202, 0, 255);
glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());
static float vertices[] = {
60.0f, 10.0f, 0.0f,
110.0f, 110.0f, 0.0f,
10.0f, 110.0f, 0.0f
};
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
}
just to paint a triangle on the screen.
But then if you want cross-platform code – something that you can try on your desktop, and then run on your device with OpenGL ES, it starts to look really horrible!
Macros everywhere to cope with the different function signatures and data types – not to mention shaders under ES 2.0 versus classic GL on the desktop, and a swath of other cross-platform difficulties.
With Qt/3D your code looks like this:
void My3DWidget::paintGL()
{
QGLPainter painter(this);
painter.setClearColor(palette().color(backgroundRole()));
painter.clear();
painter.setStandardEffect(QGL::FlatColor);
painter.setColor(QColor(170, 202, 0, 255));
QGLVertexArray vertices(QGL::Position, 3);
vertices.append(60.0f, 10.0f, 0.0f);
vertices.append(110.0f, 110.0f, 0.0f);
vertices.append(10.0f, 110.0f, 0.0f);
painter.setVertexArray(vertices);
painter.draw(QGL::Triangles, 3);
}
And what’s more it runs the same on your OpenGL/ES device and your desktop. (Note that I have elided the view and model transform setup code from both examples above for the sake of space).
As mentioned in the previous blog post Qt/3D has been in the wings for some time now, and the eagle-eyed might have notice math classes springing up in Qt’s GUI module.
These classes provide the basis for Qt/3D’s cross platform geometry abstraction: QGLVertexArray. This nifty class also dovetails into the QGLBuffer class to take care of uploading your geometry to VBO’s on the graphics adaptor, as well as coping with differences in platform on data member sizes.
Download the code from the labs repo and try out the examples – the code above comes from the tutorials directory, where you can find out more about writing your traditional OpenGL apps in the Qt cross-platform way.
Whats in Store with Qt/3D
There’s more to come from Qt/3D over and above the Portability tools mentioned in the example above.
With Enablers are included encapsulation classes like QGLMaterialParameters to encapsulate OpenGL materials in a cross platform and Qt’ish way.
One of the nicest enablers is the QGLView class and its friends. Doing your GL painting into a view looks pretty much exactly the same as with an OpenGL widget, but a few more things are taken care of for you – no need to set up tricky viewing and model transforms (which is one reason why I elided them from the code above). But even better as a bonus you get a pan-rotate-zoom view window for free. Its customizable using the QGLCamera class, and with QGLLightParameters you can quickly set up your own lights too.
Then there’s Real 3D bringing basic but powerful geometry management, and model file import functionality. With this stuff we’re just dipping our toes into the world of 3D to allow coding up of basic applications using Qt style containers, QObject based memory management, and the kinds of abstractions you’ve come to expect from Qt. If you’re an Ogre programmer, or used to using Coin3D or CrystalSpace or other powerful 3D and modelling libraries – well, you’ll still need them. We’re not planning to go into competition with those established 3D toolkits.
Instead our aim is to deliver on the promise of Qt: do more with less. It should be just as easy to use a 3D model file as it is to use a PNG file, and it should be just as easy to set up a cube with a texture on it as it is to create a Qt label. We call this component of Qt/3D Real 3D because it does start to provide functionality we’re used to seeing in 3D toolkits. But we’re working to be sure we do not go too far to go down this road, and thus to decide what will go in and what will left out – so please consider the stuff in our labs release as definite maybes.
QML and Qt/3D
There’s a lot of buzz around Declarative UI and its associated language QML.
Qt/3D will work with Declarative UI by providing QML bindings so 3D functionality can be easily used from Declarative UI programs. There’s a few demos of this in the source tree which can be tried out and you can see Henriks short video about QML and Qt/3D.
We’ll expand on the exciting possibilities of QML and Qt/3D in later posts.
We hope you like what we’re planning, and look forward to your feedback – keep tuned as there are more blog posts to follow, with some cool examples and things to try with Qt/3D.
No related posts.
24 comments
Looking good.
This is really good news, especially considering that starting with OpenGL 3.X, everything that’s old school is being deprecated. I hope your work will make the change more palatable.
Thank you.
Interesting. Have you thought this through though? There’s certainly more people who know GL than there is people who know Qt. There’s also more people who love the GL API more than there is people who love the Qt api. By introducing your spin on GL, you certainly make it more Qt like, but the question of whether you make it easier is very debatable.
People who already know GL will actually have to learn another API, so for them that doesn’t seem easier. The example you posted above also isn’t the best, the only reason the Qt one is “do more with less” is that you split the vertex array into three lines in the GL example, otherwise the GL example is really the one that does more with less. Also s/GL_TRIANGLES/QGL::Triangles/, really? I can’t say that I find static type checking for obvious parameters so important that replacing all GL enums with another set is justifiable.
On QGL::Triangles, it is actually easier to extend the enum to QGL::TrianglesAdjacency than to rely upon GL_TRIANGLES_ADJACENCY[_EXT] being defined, or the user having to define it. Similarly with a lot of other GL enums for extensions – it’s dumb luck as to whether they will be defined in the system GL headers. e.g. the following code will work everywhere with Qt, but will drive you nuts resolving the extensions with raw GL:
if (QGLShader::hasShaderType(QGLShader::Geometry)) {
draw(QGL::TrianglesAdjacency, …);
}
“will work everywhere” -> “will eventually work everywhere”
Geometry shaders are on our TODO for 4.7.
Oh, boy. On the one hand, I really like the intention behind this work, and hope that it can make it easier to mix OpenGL code with Qt without the one stepping on the toes of the other (getting OpenGL state machinery to play nice with libraries is a pain). On the other hand, I totally dislike having to learn totally new API names for every OpenGL call to use this. It will mean not being able to leverage the vast existing knowledge developers have of the OpenGL API namespace, and it will be harder to get those developers to work on code written with Qt/3D. Please reconsider this approach.
This is a good thing for Qt programmers that don’t want to learn the GL API, and like to stick to the Qt way. Programmers used to GL can still use this GL API I guess, so I don’t see any problem.
Just having watched Hendrik’s video, it reminds me of Open Inventor and it’s scripting/file format. You can do exactly the same, but of course not in the very unique Qt way…
Good news, but there’s something quite disturbing with Qt: despite all your efforts to develop 3D, Qt 4.6 RC1 still has the OpenGL 1.2/1.3 headers, not updated since 2002 ! So no extension past OpenGL 1.3 is registered in the Qt OpenGL header (gl.h/glext.h). How odd !
divide: the source packages use the GL headers that come with the user’s system – which we don’t change of course – are you referring to a specific binary SDK package?
“leverage the vast existing knowledge developers have of the OpenGL API namespace”
We recognize that many programmers just want raw OpenGL and we don’t plan to prevent that from being used – mix and match – you can write your own Qt/3D material effect that inherits from QGLAbstractEffect using raw GL calls to enable textures and rendering modes for example.
Part of the labs release process is to get feedback as to what will actually help people write portable GL applications quicker – because those are candidates for early inclusion into Qt.
I see one problem using the Qt API, it is because I have my own data structure, then I would be obliged to:
1. use the Qt objects instead of mine, but I am working on double type, that Qt is using float
2. continue with the raw API
I thought (one of) the goal of OpenGL was to be abstracted from the data structure.
However I don’t know much about the new version 3.x
what do you suggest?
For all those who say “Oh, need learn another API”: sometime C++ and OOP was «Oh, just another language and approach, while so many people already have strong experience…». Why don’t you use procedure-oriented languages?
>For all you 3D and graphics hackers out there this will not be news: writing OpenGL code is a pain.
Well, more correct would be: 3D is pain in general and Qt won’t help you.
I mean, just look at those examples (OpenGL vs Qt), do they differ much? I think it more looks like 1:1 wrapping, i.e. renaming… you still have to write same (except, maybe, that in OpenGL you won’t find “Q” prefix…).
Thanks.
Rhys Weatherley: yes I’m refering to files C:\qt\2009.05-rc1\mingw\include\GL\gl.h and C:\qt\2009.05-rc1\mingw\include\GL\glext.h
from the “Qt 4.6.0 + Qt Creator 1.3.0 RC SDK for Windows”
Theses files have not been updated since OpenGL 1.3, which is quite old. Therefore when I need a specific OpenGL extension in Qt, I have to define values myself, like:
#define LUMINANCE_ALPHA16F_ARB 0x881F
#define GL_CLAMP_TO_EDGE 0x812F
because they are not defined in the Qt bundled GL headers.
What I miss most are examples for using Qt3D or gl code in Qt.
I had the problem of painting 2D Images on a flat surface with opengl in a Qt Application, which from the problem is as easy as it can be.
The solution I was told to implement it was to get a openGL book and learn the insides of the language.
This way I skipped the whole problem and have left it as nonfixable (for me).
So what I need is a really good introduction of 3D Operations in Qt of the most simple things.
@Rhys Weatherley: Well, there are two issues there:
1) is that there is likely one codebase in the world where that is a problem and that is Qt, everyone else is using some extension wrangler library like GLEW (that even includes examples in Mesa3d nowadays),
2) Once the extension has been merged in GL, then obviously GL version check is enough – it simply won’t compile with earlier versions of GL. It’s exactly the same case for all Qt apps though. An app won’t compile if you use features from Qt 4.6 and try to compile it against Qt 3.2. So this only applies to extensions. But when merging those in Qt you’re effectively creating a whole new OpenGL. For you it’s the subset of GL ES + GL + whatever extensions you liked. Currently there are 381 GL extensions, do you really want to go through all of them and figure out which ones intersect your feature set? I think it’s going to be more than you bargained for. Especially nowadays where the dichotomy between ES and full is disappearing. Two maybe three years ago with ES 1.x and GL 2.x out there a compatibility layer between the two would be probably nice to have, but nowadays the hardware can do both just fine. It’s certainly the case for your n900 hardware that besides ES supports GL 3.x or even DX10 just fine.
I think this api is very nice for Qt internally, but at the same time I think you’re rushing to make it public. GL is evolving rapidly. You’re going to end up having to maintain this code forever. Which especially given that the differences between the mobile and desktop profiles are going away seems like time that could be spent more constructively. Then again personally I don’t like to maintain things anyway.
I’m curious how far along the roadmap you expect to be at the release of Qt 4.6, and ultimately what model file formats you plan to support out-of-the-box? I ask because in the next month or two I’ll actually be looking to add basic model viewing functionality to an existing project, and I’d like to plan ahead.
As someone who has programmed and used virtual reality, scene graph, and other visualization systems, I think there is merit to having an array of simple mid-level abstraction classes which wraps up some OpenGL functionality and delivers it in a QT-ish way. It offers some problem solving and viz capability to the non-purist geek crowd, ie. the engineer and science community who will program enough to do work in their fields without wanting to know the intricacies of OpenGL or its shader languages, or any of the scene graph node systems. Many geoscience and climate change modelers and programmers I know don’t want to know about GL display lists, want to deal with glut, or do anything except get their data to look good inside their widgets. So an xBase-like wrapper system for OpenGL function combinations might really help.
That said, keeping your new 3D classes current with the ever-evolving OpenGL standards and ARBs may prove to be something of a time commitment.
I don’t know what this means. Well I do, but I don’t know how I’d use it. At most, I would only need 2.5D, which is to say, perspective transformations of Widgets and GraphicsItems.
I also would *love* to see some code that takes a video transforms it (perspective skew) provides a mirrored image along the bottom with an alpha effect and blur. So it looks like it is playing above a glossy table. That to me, is the most 3D I’d get.
But, I do like that this would make GL easier fo em to learn. I wonder if your vertex array will be initialized by a QPolygon(defaulting to 0 zOffset, or taking a param)
Zack: “GL is evolving rapidly.”
This is sort of the point of Qt/3D. Everyone who writes an application with GL to solve a real-world problem has to deal with extensions, version differences, desktop vs GL, and so on. Qt/3D evolves to wrap the new GL’s to present a consistent interface with the old one’s and to make new GL features easier to access. Then other people can spend their time on their actual problem. This is the same problem Qt has always solved: make the platform differences go away and present a consistent interface.
Qt/3D is also about more than just making GL the same everywhere. GL is a drawing library, not a 3D toolkit, just as Xlib is not a widget toolkit. Application writers need more than just extension wrappers; they need viewing widgets, mesh importers, stereo output, head tracking, etc. GL enables those things, but doesn’t provide them. More on this in future labs posts.
Luke Downey: “I’m curious how far along the roadmap you expect to be at the release of Qt 4.6, and ultimately what model file formats you plan to support out-of-the-box?”
The Qt/3D features in 4.6 were outlined in last week’s post: http://labs.trolltech.com/blogs/2009/11/10/qt3d-features-in-qt-46/ The labs release contains an add-on for Qt 4.6 that provides additional wrapper classes, model file loaders, examples, and so on. Model file formats are supported via a plug-in mechanism, with obj and 3ds (using lib3ds v1) supported – try out the 3dscube example. We’d welcome contributions to improve these plug-ins and add more for other interesting formats (COLLADA? Blender? M3G?).
I am 100% positive about it: just go and the people will jump on it ! I can say I have touched many of the aforementioned 3d toolkits and they have all their own, sometimes bloated, style and are pain to port/compile/develop. Qt’s is just so clean, clever and !portable! of course… Having that also for 3d part would be just a big win: just great !
Thanks everyone for your thoughtful comments. We really are looking to you all for valuable input on where to take our focus with Qt/3D and OpenGL in general.
Its great to hear all of your interest and opinions.
To those that are saying “new API to learn” and “not doing more with less”, we hear your concerns. But: remember we are doing 3 main areas with Qt/3D – Portability API, Enablers and Real3D.
The example posted above is to demonstrate the Portability API.
My apologies for not posting more examples, but there’s only so much you can fit in a blog post and there are plenty of examples in the repo – check the link to the above. I’d encourage you to download what we have so far – but please be gentle, since its still experimental.
The fact that the Portability API doesn’t really save any lines of code over OpenGL is intentional – the Portability functionality tracks OpenGL in order to make sure existing knowledge of OpenGL transfers over.
If you say its a new API to learn above what you already know – which API are you talking about exactly? OpenGL ES 2.0, OpenGL ES 1.x or one of the desktop GL’s? glOrtho or glOrthof …? Not to mention all of the extensions. With the portability functions we tried to provide calls that OpenGL programmers would instantly recognize, but which would work on either fixed function or programmable (shader-based) pipelines.
Yes there is some new stuff to learn but mostly the OpenGL knowledge you have will work one-for-one in Qt/3D and then code will run on all these platforms.
To do more with less, look to the Real 3D and Enablers. Real 3D especially is intended to provide functionality to get lots done with a few powerful calls, while at the same time not trying to reimplement Ogre or other toolkits.
Keep the comments coming, and we’re particularly interested to hear your experiences with trying out the code from the repo.
Thanks again.
The single OpenGL related thing that I would want in Qt that is cross-platform creation of 3.x contexts with Core and Compatibility profiles (especially 3.2) and widgets to display those. Can that be sneaked into a minor release.
Comments on this entry are closed.