[PARTIALLY SOLVED] QML / ShadersEffectItem / Transparency
-
I have several questions around the QML / shaderEffectItem and transparency.
Shall I begin with the first one: I am developping under Windows XP; using the mingw compilation toolchain, and Qt 4.7.4.I just want to first create a QmlApplicationViewer of size 1024*768, with trransparency.
Then I want to display a png of size 968*640 (containing transparency parts) inside this QmlApplicationViewer at position 50,50. So I expect to have transparency around the image, and inside the image itself.
->My application gives me the following result: i have the opaque part of the image displayed correctly, but all transparent parts I was expecting, (around the image, and in the image itself) are full of dirty stuff probably coming from a buffer that was not cleared before.
Any idea how I could have a clean result?
Here is my code:
main.cpp
@#include <QtGui/QApplication>
#include <QtOpenGL>
#include "qmlapplicationviewer.h"Q_DECL_EXPORT int main(int argc, char *argv[])
{
#ifdef OPENGL_GRAPHICSSYSTEM
QApplication::setGraphicsSystem("opengl");
#endifQScopedPointer<QApplication> app(createApplication(argc, argv)); QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
#ifndef OPENGL_GRAPHICSSYSTEM
QGLFormat format = QGLFormat::defaultFormat();
format.setSampleBuffers(false);
format.setSwapInterval(1);
QGLWidget* glWidget = new QGLWidget(format);
glWidget->setAutoFillBackground(false);
viewer->setViewport(glWidget);
#endifviewer->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); viewer->setAttribute(Qt::WA_TranslucentBackground); viewer->setAttribute(Qt::WA_NoSystemBackground); viewer->setStyleSheet("background:transparent;"); viewer->setWindowFlags(Qt::FramelessWindowHint); viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer->setMainQmlFile(QLatin1String("qml/maskproject/main.qml")); viewer->showExpanded(); return app->exec();
}
@main.qml
@
import QtQuick 1.0
import Qt.labs.shaders 1.0Rectangle {
width: 1024
height: 768
color: "transparent"Image {
id:source
x:50
y:50
width:968
height:645
source: "../../../_DSC5401.jpg"
}
}
@Any idea what is wrong here?
Thank you,
Bill -
Here is the illustration of what I would like to get on the left side of the image, and the result I am getting with my current code on the right side of the image. Anyone knows why?
-
Generally OpenGL windows (namely QGLWidget) don't support window transparency.
-
Hopefully I will get a more encouraging answer than this one! I hope so, since generally does not mean always, right?
-
No, not always. I've seen solutions that use offscreen OpenGL rendering with bliting into a transparent window, or enabling a platform specific extension. I haven't seen a solution that is implementable with the Qt APIs or one that is generally cross-platform. If someone knows one, I'd love to hear about it.
-
I think we have such an implementation on our embedded device. I tried this code:
@#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QtOpenGL>Q_DECL_EXPORT int main(int argc, char *argv[])
{
#ifdef OPENGL_GRAPHICSSYSTEM
QApplication::setGraphicsSystem("opengl");
#endifQScopedPointer<QApplication> app(createApplication(argc, argv)); QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
#ifndef OPENGL_GRAPHICSSYSTEM
QGLFormat format = QGLFormat::defaultFormat();
format.setSampleBuffers(false);
format.setSwapInterval(1);QGLWidget* glWidget = new QGLWidget(format); glWidget->setAutoFillBackground(false); viewer->setViewport(glWidget);
#endif
viewer->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); // viewer.setAttribute(Qt::WA_OpaquePaintEvent); //viewer->setWindowFlags(Qt::FramelessWindowHint|Qt::SplashScreen); //viewer->setAttribute(Qt::WA_TranslucentBackground); viewer->setAttribute(Qt::WA_NoSystemBackground); viewer->setStyleSheet("background: transparent;"); viewer->setFrameStyle(QFrame::NoFrame); viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer->setMainQmlFile(QLatin1String("qml/SimpleOpenGLWithTransparency/main.qml")); viewer->showExpanded(); return app->exec();
}
@
And on our target it displays white color instead of transparent. We have two different hardware framebuffers, my app is running in the FB on top, and i can not see through. If I remove the openGL initialization, I can see through the image without any problem.
Do you think it can improve if I set the :
format.setAlpha(true);
instruction, or it has nothing to do with this?Regards,
Bill -
I think all you need to do is setting TranslucentBackground on the viewport(!!!):
glWidget->setAttribute(Qt::WA_TranslucentBackground);... this should do magic
(before and/or after setViewport ... there is something going on when setting the viewport .. moving this line around in the code can improve things a lot ;) )... if this doesn't help, try to add:
glWidget->qglClearColor(Qt::transparent);I got no MS-Windows machine here, but it should be ... somewhat similar on linux and window ;)
-
Hey Thomas, do you think a
format.setAlpha(true);could also improve things?
Bill -
Hello Thomas, I have tried both solutions, both on PC WindowsXP, and on our Target iMX53 linux/Wayland based, with no success in either case :(
I am still getting dirty data all over the place in the transparent areas...
I am doomed!
Bill -
Another guy from another working with us, told me he found a workaround by modifying the qmlApplicationViewer and replacing/adding the following:
"The only way i found to circumvent this issue is to overwrite QGraphicsView::drawBackground() in the QMLApplicationViewer:
void QmlApplicationViewer::drawBackground(QPainter* painter, const QRectF&)
{
painter->beginNativePainting();
glClearDepthf(1.f);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);painter->endNativePainting();
}Maybe there is another way.
"
Do you know if it's a good solution? or if there is something else I could try without changing the qmlApplicationViewer itself?
Thank you,
Bill -
I tested all solution, apparently none is working for me, neither on PC XP, nor on Target/embedded system Device.
-
Finally got something working:
1 - add the workaround in the qmlViewerApplication as follows:
@void QmlApplicationViewer::drawBackground(QPainter* painter, const QRectF&)
{
painter->beginNativePainting();
glClearDepthf(1.f);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
painter->endNativePainting();
}@2- initialise your qmlApplicationViewer as follows:
@#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QtOpenGL>int main(int argc, char *argv[])
{QScopedPointer<QApplication> app(createApplication(argc, argv)); QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create()); viewer->setWindowFlags(Qt::FramelessWindowHint); viewer->setAttribute(Qt::WA_NoSystemBackground); viewer->setStyleSheet("background: transparent;"); QPalette palette; palette.setColor(QPalette::Base, Qt::transparent); viewer->setPalette(palette); viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer->setMainQmlFile(QLatin1String("qml/SimpleOpenGLWithTransparency/main.qml")); QGLFormat format = QGLFormat::defaultFormat(); format.setSampleBuffers(false); format.setSwapInterval(1); format.setAlpha(true); QGLWidget *glWidget = new QGLWidget(format); glWidget->setAutoFillBackground(false); viewer->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); viewer->setViewport(glWidget); viewer->showExpanded(); return app->exec();
}
@Thank you Mathias for your suggestions, thank you Thomas also, even if your tricks did not work for me.
Best of luck for all!
Bill[Edited for code syntax highlighting. -Bradley]
-
I think it's ok ... if "he" isn't clearing it's ok if you do. :)
Performance-vice it shouldn't be a big deal do clear the color-buffer... but maybe someone with more opengl-performance-experience has an opinion?@
glWidget->setAutoFillBackground(false);
@
I think this is the problem.
You have disabled any background painting on the viewport (which is then overwritten by you via reimplementing the drawBackground of the DeclarativeView).
What he's then doing is painting transparent ... which is then composed with the "background".
If you try a half-transparent red as your Rectangle color, I would guess you would see red garbage :)... the only thing which is strange is that:
@
viewer->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
@
should clear the color buffer for every frame ...