Qt 通过从项目中获取的纹理在QQuickFramebufferObject中绘制。除非我不断地重新绘制/更新,否则它将失败
简而言之,我的代码的作用是:Qt 通过从项目中获取的纹理在QQuickFramebufferObject中绘制。除非我不断地重新绘制/更新,否则它将失败,qt,opengl,qml,qtquick2,repaint,Qt,Opengl,Qml,Qtquick2,Repaint,简而言之,我的代码的作用是: 创建一个名为rect的简单矩形,图层为启用:true 将rect传递给名为itemSnapshotter 在synchronize中,将指针指向rect 在渲染中,绘制一个带有我所用纹理的矩形 当main.qml完成加载时,调用itemSnapshotter.update()这是第一次也是唯一一次 问题是QQFBO不会绘制任何内容,除非我取消注释render()末尾的update调用知道为什么吗? 我的代码: main.cpp: PassThrough.frag
- 创建一个名为
的简单rect
,图层为矩形
启用:true
- 将
传递给名为rect
itemSnapshotter
- 在
中,将指针指向synchronize
rect
- 在渲染中,绘制一个带有我所用纹理的矩形
- 当
完成加载时,调用main.qml
itemSnapshotter.update()代码>这是第一次也是唯一一次
render()
末尾的update
调用知道为什么吗?
我的代码:
main.cpp:
PassThrough.frag.glsl:
PassThrough.vert.glsl:
它正在保存指针。它也可能改变。另一件事:
synchronize()
和该矩形的类似回调之间的顺序不清楚。这可能就是为什么要使用QSGTextureProvider::textureChanged()
@Velkan:是的,它正在保存一个指针,编辑文章以反映这一点。回复:“它也可能改变。”-什么也可能改变?回复:“订单”-您注意到我在onCompleted
中调用update()
(调用synchronize
)了吗?我不仅仅依靠QML的主动调用update
textureChanged
看起来它可能会帮助我解决问题,谢谢。矩形的纹理可能会改变(我认为它甚至可能在不可见时消失)。在GUI线程中的onCompleted
中调用update()
。但是在渲染线程中调用了synchronize()
。因此,中间存在某种队列,或者可能QuickItems被标记为要更新,以便在渲染线程和GUI线程之间进行下一次同步时对其进行处理。@Velkan:当然,矩形的纹理可能会更改。对我来说没问题。至于你的消息的其余部分,我不会发表评论,因为这只是猜测,似乎不会导致解决方案(除了“使用textureChanged”之外,我已经在努力了),这不是猜测。qt文档中有明确的说明,甚至有这两个线程的奇特图表,每个线程都有自己的颜色。
#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"
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();
}
}
varying highp vec2 vTexCoord;
uniform sampler2D uTex;
void main() {
gl_FragColor = texture2D(uTex, vTexCoord);
}
attribute highp vec2 aPos;
varying highp vec2 vTexCoord;
void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
vTexCoord = aPos;
}