我正在使用QtQuick和一个自定义的OpenGL渲染器(从QtQuick的角度来看是自定义的,因为它只是OpenSceneGraph)。为此,我创建了一个继承自 QQuickFramebufferObject 的自定义 QQuickItem ,然后依次创建一个继承自 QQuickFramebufferObject :: Renderer 的自定义渲染器强> QQuickFramebufferObject :: createRenderer()即可。这是有据可查的,这些步骤没有问题。
现在发生的事情是,为了以后访问,在 QQuickFramebufferObject :: createRenderer()中创建的渲染器实际上是缓存的(它实际上是在 QQuickFramebufferObject 构造函数中实例化的并简单地返回 QQuickFramebufferObject :: createRenderer()。这很好用,我可以看到没有直接的其他方式来编码它,因为创建的渲染器后来用于响应事件,如 geometryChanged < / strong>或 mousePressEvent ,例如
////////////////////////////////////////////////////////////////////////////////
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是我的自定义 QQuickFramebufferObject 而 m_renderer 是我的自定义 QQuickFramebufferObject :: Renderer 。
问题是 createRenderer()是const(实际上并不是缓存内容的邀请),而this paper明确指出不应缓存渲染器 - (尽管它官方文件中没有说明。
这里有什么收获?有没有我错过的东西?你能看到另一种干净的方式来编码吗?
答案 0 :(得分:2)
嗯,渲染器在QQuickFramebufferObject
中获得非常量synchronize(QQuickFramebufferObject *item)
。
这是因为您不应该使用Renderer
之类的内容触摸GUI线程中的mousePressEvent
(Renderer
没有任何可以在GUI线程中执行的函数,正如我所见)。当GUI线程被阻塞时,Renderer::synchronize()
在渲染线程中执行:所以它就是进行数据传输的地方。
通常,当由于输入而有变化时,GUI线程必须要求同步。这导致它停止,然后在渲染线程中调用场景图的synchronize()
。有一个同步图(没有提到渲染器,但它必须遵循相同的原则):http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html
Renderer::render()
发生在渲染线程中。因此,没有数据可以传递到那里。
QQuickItem::geometryChanged
在GUI线程中(可能需要调试器),所以不要混合渲染。
答案 1 :(得分:2)
Velkan提供了将Raw / Custom OpenGL与QQuickFramebufferObject
集成的原则。由于我们刚刚完成了一个也集成了OSG和QtQuick的项目,我想分享一些我们的经验。
是的,当然,您永远不应该缓存渲染器。 createRenderer
是const的原因,这就是Qt团队如何设计类的原因。根据我们的实验,可以多次调用createRenderer
函数。
要在QQuickFramebufferObject和它的渲染器之间进行同步,我们在QQuickFramebufferObject中添加QQueue
,当我们感兴趣的任何事件发生时,我们将它们放入队列中。在渲染器中,当调用synchronize
时,我们将队列从fbo复制到渲染器,并在render
函数中执行某些操作。