Hey,

I'm having another attempt at a problem I failed to solve about a year ago.
The rough sketch is:
I have an external application which is using Qt and renders some content using 
the OpenSource graphics engine OGRE. (I can't / don’t want to change the 
application's source. My current approach is a plugin) I want to overlay a 
QWidget or a QML Scene on top of the rendered 3D scene.
Now, there are different ways to achieve this.
1) My currently working one is to create a texture that is overlaid on top of 
the 3D scene by OGRE.
I simply have to lock the texture's memory, create a QImage on top of the 
memory and draw into the image.
This works for QWidgets, however, I can't display a QML scene that way (at 
least not as far as I know).
2) Whenever the scene has rendered, I switch to a QOpenGLContext, 
QOffscreenSurface, QOpenGLPaintDevice and QOpenGLFramebufferObject. Render the 
QWidget or QML scene into the FBO, retrieve the rendered content as a QImage, 
switch back to OGRE's OpenGL context and copy the image's content to the 
texture.
This works for both QWidgets and QML but the copy operation takes quite a 
performance penalty making it inviable (around an order of magnitude longer 
than the first approach).

Today I've found another way to use native OpenGL to draw on top of the scene 
in OGRE after the render queue ended but couldn't work out how to paint on it 
using Qt without getting stuck at the getting the content on screen without the 
QImage copy workaround in Approach 2.
Unfortunately, 3D graphics and OpenGL is pretty far from my fields of expertise 
which is why I'm hoping someone who is more competent than me regarding OpenGL 
and QOpenGL can help me figure this out.
I'll attach code parts that I deem important below, if you require a working 
example I can send you the code (it's not opensource yet but I'm planning on 
releasing it in the near future) but it requires a Linux distribution (only 
tested with Ubuntu) and a ROS installation.

To summarize: I'm trying to find a way to either render directly to the 
texture, use a quicker method to copy the content from the FBO to the texture 
than getting a QImage and memcpy or, alternatively, render directly on top of 
the scene using the access to native OpenGL I've found today (here the problem 
is that I don't really know how to continue using OGRE's context when rendering 
Qt/QML).

Best regards and thank you for taking your time to read until here, Stefan


Texture generation: 
//////////////////////////////////////////////////////////////////////
Ogre::OverlayManager &overlay_manager = Ogre::OverlayManager::getSingleton();
ogre_overlay_ = overlay_manager.create( "overlay" );
material_ = Ogre::MaterialManager::getSingleton().create( 
"overlay_OverlayMaterial", 
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
overlay_panel_ = dynamic_cast<Ogre::OverlayContainer *>( 
overlay_manager.createOverlayElement( "Panel", "overlay_Panel" ));
overlay_panel_->setPosition( 0.0, 0.0 );
overlay_panel_->setDimensions( 1.0, 1.0 );
overlay_panel_->setMaterialName( "overlay_OverlayMaterial" );

ogre_overlay_->add2D( overlay_panel_ );

texture_ = Ogre::TextureManager::getSingleton().createManual(
      "overlay_OverlayTexture",
      Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
      Ogre::TEX_TYPE_2D,
      texture_width,
      texture_height,
      0,
      Ogre::PF_A8R8G8B8,
      Ogre::TU_DEFAULT
    );
material_->getTechnique( 0 )->getPass( 0 )->createTextureUnitState( 
texture_->getName());
material_->getTechnique( 0 )->getPass( 0 )->setSceneBlending( 
Ogre::SBT_TRANSPARENT_ALPHA );
material_->getTechnique( 0 )->getPass( 0 )->setSceneBlending( Ogre::SBF_ONE, 
Ogre::SBF_ONE_MINUS_SOURCE_ALPHA );

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

Approach 1: 
//////////////////////////////////////////////////////////////////////
buffer_ = texture_->getBuffer();
buffer_->lock( Ogre::HardwareBuffer::HBL_DISCARD );
auto width = (unsigned int) geometry_.width();
auto height = (unsigned int) geometry_.height();
const Ogre::PixelBox &pixel_box = buffer_->getCurrentLock();

auto data = static_cast<Ogre::uint8 *>(pixel_box.data);
int bytes_per_line = pixel_box.getWidth() * 4;
// Empties the texture by overwriting all ARGB data with 0.
Ogre::uint8 *offset = data;
for (int i = 0; i < height; ++i)
{
  memset(offset, 0, width * 4);
  offset += bytes_per_line;
}
paint_device_image_ = QImage(data, width, height, bytes_per_line, 
QImage::Format_ARGB32_Premultiplied);
// Rendering stuff
// ...
  buffer_->unlock();
  buffer_.setNull();
//////////////////////////////////////////////////////////////////////

Approach 2: 
//////////////////////////////////////////////////////////////////////
// Initialization
QSurfaceFormat format;
format.setDepthBufferSize( 16 );
format.setStencilBufferSize( 8 );

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

if ( !context_->create())
{
  LOG_ERROR( "OverlayManager: Fatal! Failed to create context!" );
}
surface_ = new QOffscreenSurface;
surface_->setFormat( format );
surface_->create();

makeCurrent();

paint_device_ = new QOpenGLPaintDevice( geometry_.size());

if ( geometry_.width() == 0 || geometry_.height() == 0 ) {
  doneCurrent();
  return;
}
QOpenGLFramebufferObjectFormat format;
format.setSamples( 16 );
format.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
fbo_ = new QOpenGLFramebufferObject( texture_->getWidth(), 
texture_->getHeight(), format );
doneCurrent();

// Rendering part
makeCurrent();
fbo_->bind();
context_->functions()->glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Rendering stuff
// ...
fbo_->release();
QImage image = fbo_->toImage().convertToFormat( QImage::Format_ARGB32 );
doneCurrent();

Ogre::HardwarePixelBufferSharedPtr buffer = texture_->getBuffer();
buffer->lock( Ogre::HardwareBuffer::HBL_DISCARD );
const Ogre::PixelBox &pixel_box = buffer->getCurrentLock();

auto data = static_cast<Ogre::uint8 *>(pixel_box.data);
memcpy( data, image.bits(), image.byteCount());

buffer->unlock();
_______________________________________________
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest

Reply via email to