Displaying widgets on top of Opengl widget (Ogre engine)
-
Hello!
First post here so let me know if I messed up in any way!
My question is regarding showing widgets on top of an opengl widget.
I have created a widget which inherits QWidget and uses Ogre (graphics engine) to render onto the widget, by simply passing the QWidget window id. This part works great and it renders without any issues. Ill refer to it as the Ogre widget. Ogre renders using Opengl only.The problems arises when I try to place any kind of widget "on top" of the Ogre widget. The parts of an overlaying widget which should be transparent makes a "hole" in the Ogre widget.
For example a QLabel, which by default has a transparent background and only the text should show, will make a hole the size of its bounding box and show the color of the main window behind the Ogre widget.
I really have no idea what is causing this issue but I'm leaning toward it being a Qt thing, which is why I am posting here instead of the Ogre forums. Really looking for any hints or tips on what to try to find a fix for this, because I barely know where to begin when it comes to the interaction between Qt and "external" Opengl.
Here is a picture which hopefully explains whats going on.
Two labels are used, the one on top has a transparent background the other a blue background. Just to show that it is in fact a "hole". In the top-right is an example of a QListWidget which I use to show selected meshes.
Again; any help is appreciated. The desired solution will simply let me have a label (or any other widget) on top of the Ogre widget without creating a hole.
Ubuntu 18
Intel Graphics 520
Ogre 2.1
Qt 5.5.1Edit: Some incorrect statements were removed.
Edit2: Probably not the proper way but rather than create a new post ill add to this.Alternatively I could use the Ogre widgets Qpainter to paint things on top of the actual renderwindow from Ogre. This works but the renderwindow is always on top. Is there a way to let the QPainter draw on top of the renderwindow?
Example:
The grayscale colorbar is drawn in the paintEvent of the Ogre widget. The renderwindow is not resized with the widget just to show that the colorbar is being drawn behind (the widgets size goes to the border).
-
Hi and welcome to devnet,
Not a direct answer but did you already saw the Ogre Wiki entry about Qt 5 integration ?
-
Yes and it was a great help when I started!
My implementation is very similar, I use a QWidget instead of a QWindow because otherwise the "renderwindow" wont allow any widgets to be on top of it, no matter if they are raised and so on. I really have no clue what causes this layering issue. Nor how Ogre "sends" the rendered window to Qt (other than it using the window ID). This is sort of mentioned under reasons to use a QWindow in the post you linked (where I want the undesired effect of having a QWidget surface to draw on, it just seems its always behind Ogre).
I will admit since I based my implementation on it I have changed many things so I'll go back and tweak stuff to see if there might have been something I missed which could solve the issue.
-
After some more searching i have found this old thread:
https://stackoverflow.com/questions/13339963/transparent-qt-widget-and-ogreHopefully I can find a way to make the openglContexts work together, which seems to be the problem.
Ill write my solution if i find one! In the meantime if anyone has any other input please let me know!
-
I ended up solving this problem by relying more on Ogre.
In short I bridge Qt and Ogre by using a HardwarePixelBuffer (an Ogre class) from which I get the raw pixeldata and render into that using a QImage. That way Qt can "draw" onto an Ogre texture, which I then render using Ogres Overlay system.
I hope that descripton is detailed enough.
// overlayTexture is a Ogre::Texture Ogre::v1::HardwarePixelBufferSharedPtr hwBuffer = overlayTexture_->getBuffer(0, 0); hwBuffer->lock(Ogre::v1::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox &pb = hwBuffer->getCurrentLock(); // render into texture buffer QImage textureImg(static_cast<Ogre::uint8*>(pb.data), pb.getWidth(), pb.getHeight(), QImage::Format_ARGB32); textureImg.fill(qRgba(0, 0, 0, 0)); // My own overlay object which draws itself onto a paintdevice, in this case QImage colorbarOverlay_->draw(&textureImg, true); hwBuffer->unlock();
Edit:
Just to be clear the solution is a workaround, the original problem still persists, Qt is not able to work with Ogre "naturally". However I believe the solution I found is general enough to replace the method I was trying to use originally (just having widgets on top of Ogre).
-
Thanks for the feedback !
If you have the time, it would be nice to have a small example of your integration. Maybe even get it into the Ogre documentation :)
Or otherwise as a Qt Wiki entry
-
My solution is heavily inspired by: this old ogre wiki post (should have linked it as well, forgot about it until now).
I mostly slimmed it down to what I posted as my solution, but I agree if I have time I'll try to make an example/entry.
There are some things that need to be updated from the linked post to fit Ogre 2.1 since the post is old.