QtQuick 自定义 OpenGL 渲染
QtQuick custom OpenGL rendering
我将 QtQuick 与自定义 OpenGL 渲染器一起使用(从 QtQuick 的角度来看是自定义的,因为它只是 OpenSceneGraph)。为此,我创建了一个继承自 QQuickFramebufferObject 的自定义 QQuickItem,然后又创建了一个继承自 QQuickFramebufferObject 的自定义渲染器: QQuickFramebufferObject::createRenderer() 中的渲染器。这是有据可查的,这些步骤没有问题。
现在发生的事情是,为了以后访问,在QQuickFramebufferObject::createRenderer()中创建的渲染器实际上被缓存了(它实际上在[=23=中被实例化) ]QQuickFramebufferObject 构造函数并简单地在 QQuickFramebufferObject::createRenderer() 中返回。这工作正常,我看不出有其他直接的编码方式,因为稍后使用创建的渲染器对 geometryChanged 或 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() 是常量(这并不是真正的缓存东西的邀请),并且 this paper 明确指出渲染器不应该是缓存 -(虽然官方文档中没有说明)。
这里有什么问题?我错过了什么吗?你能看到另一种干净的编码方式吗?
好吧,渲染器在 synchronize(QQuickFramebufferObject *item)
.
中得到一个非常量 QQuickFramebufferObject
发生这种情况是因为您不应该使用 mousePressEvent
之类的东西在 GUI 线程中触及 Renderer
(Renderer
没有任何可以在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
函数中执行某些操作。
我将 QtQuick 与自定义 OpenGL 渲染器一起使用(从 QtQuick 的角度来看是自定义的,因为它只是 OpenSceneGraph)。为此,我创建了一个继承自 QQuickFramebufferObject 的自定义 QQuickItem,然后又创建了一个继承自 QQuickFramebufferObject 的自定义渲染器: QQuickFramebufferObject::createRenderer() 中的渲染器。这是有据可查的,这些步骤没有问题。
现在发生的事情是,为了以后访问,在QQuickFramebufferObject::createRenderer()中创建的渲染器实际上被缓存了(它实际上在[=23=中被实例化) ]QQuickFramebufferObject 构造函数并简单地在 QQuickFramebufferObject::createRenderer() 中返回。这工作正常,我看不出有其他直接的编码方式,因为稍后使用创建的渲染器对 geometryChanged 或 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() 是常量(这并不是真正的缓存东西的邀请),并且 this paper 明确指出渲染器不应该是缓存 -(虽然官方文档中没有说明)。
这里有什么问题?我错过了什么吗?你能看到另一种干净的编码方式吗?
好吧,渲染器在 synchronize(QQuickFramebufferObject *item)
.
QQuickFramebufferObject
发生这种情况是因为您不应该使用 mousePressEvent
之类的东西在 GUI 线程中触及 Renderer
(Renderer
没有任何可以在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
函数中执行某些操作。