Unsolved QQuickFramebufferObject: When using an Item, whose parent has "visible: false", as texture source, nothing is displayed
-
This works fine in Canvas3D, but not in QQuickFramebufferObject.
My code
I've based my testcase on the textureinsgnode sample app bundled with Qt. Since mine is a derived work, I have to first post the license terms here:
/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/
And now for the actual source.
main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QOpenGLFramebufferObject> #include <QSGTextureProvider> #include <QQuickFramebufferObject> #include <QOpenGLShaderProgram> #include <QOpenGLFunctions> #include <QQuickWindow> // propertyhelper.h is taken from http://syncor.blogspot.bg/2014/11/qt-auto-property.html #include "propertyhelper.h" class MyItem : public QQuickFramebufferObject { Q_OBJECT AUTO_PROPERTY(QQuickItem*, sourceItem) public: Renderer *createRenderer() const; }; class MyItemRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions { public: MyItemRenderer() { initializeOpenGLFunctions(); m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute highp vec4 aPos;" "attribute highp vec2 aTexCoord;" "varying mediump vec2 vTexCoord;" "" "void main() {" " gl_Position = aPos;" " vTexCoord = aTexCoord;" "}"); m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, "varying mediump vec2 vTexCoord;" "uniform sampler2D uTex;" "" "void main() {" " gl_FragColor = texture2D(uTex, vTexCoord);" "}"); m_program.link(); m_program.bind(); // Setup texture sampler uniform glActiveTexture(GL_TEXTURE0); m_program.setUniformValue("uTex", 0); createGeometry(); } void render() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); m_program.bind(); m_tex->bind(); paintGeometry(); m_window->resetOpenGLState(); update(); } void paintGeometry() { m_program.enableAttributeArray("aPos"); m_program.enableAttributeArray("aTexCoord"); m_program.setAttributeArray("aPos", m_vertices.constData()); m_program.setAttributeArray("vTexCoord", m_texCoords.constData()); glDrawArrays(GL_TRIANGLES, 0, m_vertices.size()); m_program.disableAttributeArray("aPos"); m_program.disableAttributeArray("aTexCoord"); } QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) { QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); return new QOpenGLFramebufferObject(size, format); } protected: void synchronize(QQuickFramebufferObject* qqfbo) { MyItem* parentItem = (MyItem*)qqfbo; QQuickItem* sourceItem = parentItem->sourceItem(); QQuickItem* texSource = sourceItem->childItems()[0]; QSGTextureProvider* texProvider = texSource->textureProvider(); m_tex = texProvider->texture(); m_window = parentItem->window(); } private: QVector<QVector3D> m_vertices; QVector<QVector2D> m_texCoords; QOpenGLShaderProgram m_program; QSGTexture* m_tex; QQuickWindow* m_window; void createGeometry() { m_vertices << QVector3D(0, 0, 0.0f); m_vertices << QVector3D(1, 0, 0.0f); m_vertices << QVector3D(0, 1, 0.0f); m_texCoords << QVector2D(0, 0); m_texCoords << QVector2D(1, 0); m_texCoords << QVector2D(0, 1); } }; QQuickFramebufferObject::Renderer *MyItem::createRenderer() const { return new MyItemRenderer(); } int main(int argc, char **argv) { QGuiApplication app(argc, argv); qmlRegisterType<MyItem>("MyItem", 1, 0, "MyItem"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } #include "main.moc"
main.qml:
import QtQuick 2.0 import MyItem 1.0 import QtQuick.Window 2.2 Window { visible: true width: 400 height: 400 Rectangle { anchors.fill: parent color: "lightblue" } Item { id: test // visible: false Text { layer.enabled: true font.pointSize: 30 text: "hello\nhello\nhello" } } MyItem { anchors.fill: parent sourceItem: test } }
If you uncomment the
visible: false
inmain.qml
, the QQFBO stops displaying anything. Why is that, and what is a proper solution?I've tried setting
opacity: 0
instead ofvisible: false
but this causes the same problem.I tried replacing
layer: true
with a separateShaderEffectSource
element withhideSource: true
, but then I have to setvisible: false
on theShaderEffectSource
, and that causes the same problem.I've also tried setting
x: -10000; y: -10000
instead ofvisible: false
and that works fine but is a hack. -
Both in QtWidgets and QtQuick "visible" property is propagated to children. So if you make "test" invisible, all it's children will become invisible as well - so your text will cease showing up. And since your MyItem uses that as source, it will paint invisible item == nothing is displayed.
-
@sierdzio: Sure, the text will cease to be rendered to the window by Qt Quick, and that's ok. But I want it to keep being rendered to the texture. Surely that's a common use case - they even included a
hideSource
option inShaderEffectSource
, but neglected this use case in the QQFBO case. -
It's a bug/ missing feature then, maybe? Have you checked the bugtracker? https://bugreports.qt.io