QtQuick 自定义 OpenGL 渲染

QtQuick custom OpenGL rendering

我将 QtQuick 与自定义 OpenGL 渲染器一起使用(从 QtQuick 的角度来看是自定义的,因为它只是 OpenSceneGraph)。为此,我创建了一个继承自 QQuickFramebufferObject 的自定义 QQuickItem,然后又创建了一个继承自 QQuickFramebufferObject 的自定义渲染器: QQuickFramebufferObject::createRenderer() 中的渲染器。这是有据可查的,这些步骤没有问题。

现在发生的事情是,为了以后访问,在QQuickFramebufferObject::createRenderer()中创建的渲染器实际上被缓存了(它实际上在[=23=中被实例化) ]QQuickFramebufferObject 构造函数并简单地在 QQuickFramebufferObject::createRenderer() 中返回。这工作正常,我看不出有其他直接的编码方式,因为稍后使用创建的渲染器对 geometryChangedmousePressEvent 等事件作出反应,例如

////////////////////////////////////////////////////////////////////////////////
void OsgItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
{
    if (m_renderer)
        m_renderer->m_window->getEventQueue()->windowResize(newGeometry.x(), newGeometry.y(), newGeometry.width(), newGeometry.height());


    QQuickFramebufferObject::geometryChanged(newGeometry, oldGeometry);
}

////////////////////////////////////////////////////////////////////////////////
void OsgItem::mousePressEvent(QMouseEvent *event)
{
    m_renderer->m_window->getEventQueue()->mouseButtonPress(event->x(), event->y(), button(*event));

    update();
}

,其中 OsgItem 是我的自定义 QQuickFramebufferObjectm_renderer 是我的自定义 QQuickFramebufferObject::Renderer .

问题是 createRenderer() 是常量(这并不是真正的缓存东西的邀请),并且 this paper 明确指出渲染器不应该是缓存 -(虽然官方文档中没有说明)。

这里有什么问题?我错过了什么吗?你能看到另一种干净的编码方式吗?

好吧,渲染器在 synchronize(QQuickFramebufferObject *item).

中得到一个非常量 QQuickFramebufferObject

发生这种情况是因为您不应该使用 mousePressEvent 之类的东西在 GUI 线程中触及 RendererRenderer 没有任何可以在GUI 线程,如我所见)。 Renderer::synchronize() 在渲染线程中执行,而 GUI 线程被阻塞:因此它是进行数据传输的地方。

一般来说,GUI 线程必须在输入发生变化时要求同步。这会导致它停止,然后在渲染线程中调用场景图的 synchronize()。有一个同步图(没有提到Renderer,但必须遵守相同的原则):http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html

Renderer::render() 发生在渲染线程中,而我记得 GUI 线程是 运行 自由的。所以,那里不能传递数据。

QQuickItem::geometryChanged 在 GUI 线程中(可能与调试器核实),所以不要混合渲染。

Velkan 提供了 Raw/Custom OpenGL 与 QQuickFramebufferObject 集成的原理。由于我们刚刚完成了一个同时集成了OSG和QtQuick的项目,我想分享一些我们的经验。

是的,当然,您永远不应该缓存渲染器。 createRenderer 是 const 是有原因的,这就是 Qt 团队设计 类 的方式。根据我们的实验,createRenderer函数可能会被调用多次。

为了在 QQuickFramebufferObject 和它的渲染器之间同步,我们在 QQuickFramebufferObject 中添加了一个 QQueue,当我们感兴趣的任何事件发生时,我们将它们放入队列中。而在渲染器中,当synchronize被调用时,我们将队列从fbo复制到渲染器,并在render函数中执行某些操作。