Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering custom opengl in qt5's qtquick 2.0

I'm looking for a way to render my custom opengl calls inside a qtquick 2.0 item. To give you some context: I have a C++ 3d engine that uses opengl for rendering. The goal is to have it rendering inside a qtquick 2.0 UI.

What I found out is that pre qt 5.0 (qtquick 2.0) you would use a QtGlWidget and embed that into the QDeclarativeView. Another way I found would be to use a QtDeclarativeItem and override the void QDeclarativeItem::paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w) method.

As I understand it this is not possible anymore as QtQuick 2.0 uses a new renderer which is based on OpenGl. It is therefore as it seems not as easy as overriding a paint method.

Does anybody know how I would go about implementing a QQuickItem that allows rendering of my opengl calls?

like image 973
wulfgeng Avatar asked Nov 28 '12 15:11

wulfgeng


2 Answers

You can do one of two things. Either render your content into a texture or render in the OpenGL context of the scene graph by hooking using the QQuickWindow::beforeRendering or QQuickWindow::afterRendering signals.

An example on how to use FBO and texture can be found here: http://doc.qt.io/qt-5/qtquick-scenegraph-textureinsgnode-example.html

An example on how to render directly to the OpenGL context of the scene graph can be found here: http://doc.qt.io/qt-5/qtquick-scenegraph-openglunderqml-example.html

like image 139
Gunnar Sletta Avatar answered Nov 04 '22 21:11

Gunnar Sletta


In your 3D engine, render into a texture and in your QQuickItem use QSGSimpleTextureNode to show the rendering results. QtQuick maintains it's own GL state, which you could otherwise mess up, that's why it is recommended to use only the QSG* classes to show custom content. Basically, plain QtQuick is a tool for rendering rectangles, not 3D content generally.

(Lame) example:

QScopedPointer<QSGTexture> texture_;

QSGNode* MyItem::updatePaintNode(QSGNode* node, UpdatePaintNodeData*)
{
  if (width() <= 0 || height() <= 0)
  {
    texture_.reset();

    delete node;
    return 0;
  }
  else
  {
    if (!node)
    {
      node = new QSGSimpleTextureNode;

      static_cast<QSGSimpleTextureNode*>(node)
        ->setFiltering(QSGTexture::Nearest);
    }
    // else do nothing

    static_cast<QSGSimpleTextureNode*>(node)->setRect(boundingRect());

    getTheTextureFrom3DEngine(texture_);

    Q_ASSERT(texture_);
    static_cast<QSGSimpleTextureNode*>(node)->setTexture(texture_.data());

    return node;
  }
}

You also need to instantiate a Timer to update the contents. You can do this from within the QQuickItem.

like image 33
user1095108 Avatar answered Nov 04 '22 20:11

user1095108