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 in main.qml, the QQFBO stops displaying anything. Why is that, and what is a proper solution?

    I've tried setting opacity: 0 instead of visible: false but this causes the same problem.

    I tried replacing layer: true with a separate ShaderEffectSource element with hideSource: true, but then I have to set visible: false on the ShaderEffectSource, and that causes the same problem.

    I've also tried setting x: -10000; y: -10000 instead of visible: false and that works fine but is a hack.


  • Moderators

    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 in ShaderEffectSource, but neglected this use case in the QQFBO case.


  • Moderators

    It's a bug/ missing feature then, maybe? Have you checked the bugtracker? https://bugreports.qt.io


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.