我的代码完成了什么,简而言之:
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;
}