通过从Item中获取的纹理在QQuickFramebufferObject中绘图。除非我不断重新绘制/更新,否则它会失败

时间:2017-03-21 20:02:03

标签: qt opengl qml qtquick2 repaint

我的代码完成了什么,简而言之:

  • 使用Rectangle创建一个名为rect的简单layer.enabled: true
  • rect传递给名为QQuickFramebufferObject
  • itemSnapshotter子类的实例
  • synchronize中,获取指向rect
  • 提供的纹理的指针
  • render中,绘制一个用我拍摄的纹理纹理的矩形
  • main.qml完成加载后,请第一次也是唯一一次致电itemSnapshotter.update();

问题是QQFBO什么都没有,除非我在update结束时取消注释render()来电。 知道为什么吗?

我的代码:

的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <QSGTextureProvider>
#include <QObject>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QQuickWindow>
#include <QOpenGLFunctions>
// propertyhelper.h is from http://syncor.blogspot.bg/2014/11/qt-auto-property.html
#include "propertyhelper.h"

class ItemSnapshotter : public QQuickFramebufferObject {
    Q_OBJECT

    AUTO_PROPERTY(QQuickItem*, sourceItem)

public:
    Renderer *createRenderer() const;
};

class ItemSnapshotterRenderer
    : public QObject
    , public QQuickFramebufferObject::Renderer
    , protected QOpenGLFunctions
{
    Q_OBJECT

public:
    ItemSnapshotterRenderer() {
        initializeOpenGLFunctions();
        initShader();
        createGeometry();
    }

    void createGeometry() {
        m_vertices << QVector2D(0, 0) << QVector2D(0, 1) << QVector2D(1, 1);
        m_vertices << QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1);
    }

    void initShader() {
        m_shaderProgram.addShaderFromSourceFile(
            QOpenGLShader::Vertex, ":/PassThrough.vert.glsl");
        m_shaderProgram.addShaderFromSourceFile(
            QOpenGLShader::Fragment, ":/PassThrough.frag.glsl");
        m_shaderProgram.link();
        m_shaderProgram.bind();

        glActiveTexture(GL_TEXTURE0);
        m_shaderProgram.setUniformValue("uTex", 0);
    }

    void prepareShader() {
        m_shaderProgram.enableAttributeArray("aPos");
        m_shaderProgram.setAttributeArray("aPos", m_vertices.constData());
        m_shaderProgram.bind();
    }

    void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        prepareShader();
        m_tex->bind();
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

        glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());

        m_window->resetOpenGLState();
        //update();
    }

    void synchronize(QQuickFramebufferObject* qqfbo){
        auto parentItem = (ItemSnapshotter*)qqfbo;

        m_window = parentItem->window();
        copyTexture(*parentItem);
    }

    void copyTexture(const ItemSnapshotter &srcItem) {
        QQuickItem* sourceItem = srcItem.sourceItem();
        QSGTextureProvider* sourceTexProvider = sourceItem->textureProvider();
        m_tex = sourceTexProvider->texture();
        GLenum err;
        while ((err = glGetError()) != GL_NO_ERROR) {
            qDebug("\tgl error: 0x%x", err, 0, 16);
        }
    }

    QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) {
        QOpenGLFramebufferObjectFormat format;
        format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); // TODO simpler format
        return new QOpenGLFramebufferObject(size, format);
    }

private:
    QOpenGLShaderProgram m_shaderProgram;
    QQuickWindow* m_window;
    QSGTexture* m_tex;
    QVector<QVector2D> m_vertices;
};

QQuickFramebufferObject::Renderer *ItemSnapshotter::createRenderer() const {
    return new ItemSnapshotterRenderer();
}

int main(int argc, char *argv[]) {
    qmlRegisterType<ItemSnapshotter>("ItemSnapshotter", 1, 0, "ItemSnapshotter");
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

#include "main.moc"

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import ItemSnapshotter 1.0

Window {
    visible: true
    width: 640
    height: 480

    Row {
        Rectangle {
            layer.enabled: true
            id: rect
            width: 100
            height: 100
            color: "red"
            border.color: "black"
        }

        ItemSnapshotter {
            id: itemSnapshotter
            sourceItem: rect
            width: sourceItem.width
            height: sourceItem.height
        }
    }

    Component.onCompleted: {
        itemSnapshotter.update();
    }
}

PassThrough.frag.glsl

varying highp vec2 vTexCoord;
uniform sampler2D uTex;

void main() {
    gl_FragColor = texture2D(uTex, vTexCoord);
}

PassThrough.vert.glsl

attribute highp vec2 aPos;
varying highp vec2 vTexCoord;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    vTexCoord = aPos;
}

0 个答案:

没有答案