[Interest] Rendering Qt/QML within native OpenGL or to texture

Stefan Fabian stefan.fabian.dev at hotmail.com
Fri Mar 8 15:56:23 CET 2019


Hey Giuseppe,

> See my talk at QtWS17 about how to integrate Qt Quick 2 with OpenGL. You
> basically need the third method (QQuickRenderControl) as you don't have
> control over the GL context creation.

> You can wrap a foreign OpenGL context in a QOpenGLContext using its
> setNativeHandle function. Then you can use QQuickRenderControl as
> illustrated in my talks, the accompanying code and the examples in Qt.

Thank you, I've watched your talk and I think I can use some of that further on.
However, unfortunately I'm stuck again at a probably pretty dumb mistake.
I almost don't want to ask given how basic this should be but I've been googling for a few hours straight and couldn't find anything working.
I'm just testing QPainter for now and it works to paint into a texture. I've saved the FBO content to my disk and it looks  okay.
Drawing the texture using OpenGL doesn't seem to work, though. I've checked multiple tutorials but I can't get it to work.
Drawing a simple polygon works but the texture is nowhere to be seen.
Here's just the code for the texture drawing, the code for the texture generation is attached at the end just in case it is relevant.

///////////////////////////////////////////////////////////
  glDisable(GL_LIGHTING);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glOrtho(0, 1920, 0, 1080, -1, 1);

  // do some OpenGL drawing here. This works.
  const float x = 960, y = 540, r = 540;
  glBegin(GL_POLYGON);
  glVertex2f(x + r, y);
  glVertex2f(x, y + r);
  glVertex2f(x - r, y);
  glVertex2f(x, y - r);
  glClear(GL_DEPTH_BUFFER_BIT);
  glEnd();

// The following doesn't work
  glEnable(GL_TEXTURE_2D);
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texture_fbo_->texture());

  glBegin(GL_POLYGON);
// I have tried using GL_TEXTURE_RECTANGLE and the width and height for texture coords as well
  glTexCoord2f(0, 0); glVertex2f(-960, -540);
  glTexCoord2f(0, 1); glVertex2f(-960, 540);
  glTexCoord2f(1, 1); glVertex2f(960, 540);
  glTexCoord2f(1, 0); glVertex2f(960, -540);
  glClear(GL_DEPTH_BUFFER_BIT);
  glEnd();

  glDisable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, 0);


  glPopMatrix();

///////////////////////////////////////////////////////////


> An alternative of the above: create yourself a new OpenGL context that
> shares with the one used by Ogre. Then use this new context (again
> together with QQRC) to render Qt Quick content into a FBO (see
> QQuickWindow::setRenderTarget). Now, since your OpenGL context and
> OGRE's are sharing, the textures that you use inside your FBO are also
> visible from the OGRE context -- you just need to paint with them, no
> copies or CPU roundtrips are involved. Just beware of the headaches that
> go together with sharing OpenGL objects: there's no implicit command
> synchronization amongst contexts, you must be sure that all your drawing
> on the texture is fully realized by the GL before reading from it from
> the other context. Sync objects (or the very crude glFinish) can be used
> for this.

That would be a nice solution. Unfortunately, OGRE also does framework abstraction, hence, it isn't easy to access the OpenGL stuff and I couldn't find a way to create an OGRE Texture from a native OpenGL texture.
The alternative might be to create a QOpenGLFramebufferObject on OGRE's underlying OpenGL texture (I can get the GLID) and blit the FBO's but I couldn't see any way of attaching a QOpenGLFramebufferObject to an existing texture if that's even possible.

Best,
Stefan

Code for generating the texture:
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  glMatrixMode(GL_TEXTURE);
  glPushMatrix();
  glLoadIdentity(); //Texture addressing should start out as direct.
  glPushAttrib(GL_ALL_ATTRIB_BITS);

  if (context_ == nullptr)
  {
    QSurfaceFormat format;

    format.setDepthBufferSize( 16 );
    format.setStencilBufferSize( 8 );

    native_context_ = new QOpenGLContext;
    native_context_->setNativeHandle( QVariant::fromValue(QGLXNativeContext( native_context_information_->context, native_context_information_->display )));

    if ( !native_context_->create())
    {
      LOG_ERROR( "OverlayManager: Fatal! Failed to create context!" );
    }

    context_ = new QOpenGLContext;
    context_->setFormat( format );
    context_->setShareContext( native_context_ );

    if ( !context_->create())
    {
     LOG_ERROR( "OverlayManager: Fatal! Failed to create context!" );
    }

    surface_ = new QOffscreenSurface;
    surface_->setFormat( format );
    surface_->create();

    context_->makeCurrent( surface_ );

    paint_device_ = new QOpenGLPaintDevice( 1920, 1080 );

    {
      QOpenGLFramebufferObjectFormat format;
      format.setSamples(16);
      format.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
      fbo_ = new QOpenGLFramebufferObject( 1920, 1080, format );
      texture_fbo_ = new QOpenGLFramebufferObject( 1920, 1080 );
    }
    fbo_->bind();
  }
  else
  {
    context_->makeCurrent( surface_ );
    fbo_->bind();
  }

  QPainter painter(paint_device_);
  painter.setRenderHint(QPainter::RenderHint::Antialiasing);
  painter.setBrush(QBrush(Qt::green));
  painter.drawRect(0, 0, 1920, 1080);
  painter.setPen(QPen(QBrush(Qt::red), 4));
  painter.setFont(QFont("Arial", 20));
  painter.drawText(100, 100, "Hello");
  painter.end();
  fbo_->release();
  context_->functions()->glFinish();
  QOpenGLFramebufferObject::blitFramebuffer(texture_fbo_, fbo_);
//  texture_fbo_->toImage().save("/home/stefan/test.png", "png");
  context_->doneCurrent();
  glXMakeCurrent( native_context_information_->display, native_context_information_->drawable,
                  native_context_information_->context );


  // restore original state
  glPopAttrib();

  // restore matrices
  glMatrixMode(GL_TEXTURE);
  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20190308/09abb709/attachment.html>


More information about the Interest mailing list