0

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.

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120
  • Yes, I remember that thing. Ended up hacking around it with `layer.effect: OpacityMask { maskSource: Item {} }`. Should look into Qt source code to find out if the hack is really necessary. – Velkan Jan 20 '17 at 12:17
  • I always recommend using "pure" OpenGL API to those who try to work with Qt OpenGL wrappers.The API design is pretty bad. – Michael IV Jan 20 '17 at 12:26
  • If only Qt could work "as expected" without requiring hacks. The numerous bugs aside, its great flaw is its design limitations. Still, there is no better tool in its category, so we are stuck with it for the time being. – dtech Jan 20 '17 at 14:44

0 Answers0