OpenGL / QT : Need help in Converting from QImage to Opengl format and render the pixels

Viewed 130

We are migrating from Old OpenGl to Modern OpenGL. I am trying to port two functions which uses QT/OpenGL and want to convert to Modern OpenGL. QImage content should be converted to OpenGL Format. Then I want to read the pixels of QImage and render in OpenGL. How to do this in Modern OpenGL. I know glcopypixels() / glDrawPixels() is deprecated. Any pointers? I have the following code but it is in old OpenGL. Basically the whole idea is writing to back buffer and restoring the back buffer and render pixels to avoid redraw. I am using QOpenglWidget Class given by QT Framework (QT 5.1). I have tried many things converting to OpenGL format from QImage. But it did not work. Need your help. Thanks in Advance.

QImage _savedBackBuffer;

void SaveBackBuffer() 
{
     glReadBuffer(GL_BACK); 
     QImage buf = this->grabFramebuffer();
    _savedBackBuffer = convertToGLFormat(buf);    // convertToGLFormat is not available in 

QOpenGLWidget class
}

void restoreBackBuffer()
{
    
    glDrawBuffer(GL_BACK);
    **glDrawPixels**( _savedBackBuffer.width(), _savedBackBuffer.height(), 
                  GL_RGBA, GL_UNSIGNED_BYTE, _savedBackBuffer.bits() );   ---> glDrawPixels is Deprecated. How to handle this call. 
    
}
     
flush () {
        glReadBuffer (GL_BACK);
        glDrawBuffer(GL_FRONT);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        **glCopyPixels**(0, 0, _scrWidth, _scrHeight, GL_COLOR);  // glCopyPixels Deprecated
        ...
        glflush();
}

I have added below code to grab the Framebuffer. But still I am getting an Empty QImage. Anything wrong with my code.

saveBackBuffer()
{
    _bSavingBackBuffer = true;
    
     QString fileName("C:\\Users\\ey617e\\Desktop\\yourFile.png");
     QFile file(fileName);
     file.open(QIODevice::WriteOnly);

     glReadBuffer(GL_BACK);
      
      makeCurrent();
      QOpenGLFramebufferObjectFormat format;
      format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
      QOpenGLFramebufferObject * fbo = new 
      QOpenGLFramebufferObject(_scrWidth, _scrHeight, format);
      fbo->bind();
      paintGL();

     _savedBackBuffer = fbo->toImage();
     _savedBackBuffer.save(file.fileName(), "PNG");
      fbo->release();
}

paintGL() 
{
QOpenGLPaintDevice fboPaintDev(_scrWidth, _scrHeight);
QPainter painter(&fboPaintDev);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    painter.beginNativePainting();

    drawDisplayLists(_underIllusDisplayLists);
    drawDisplayLists(_illusDisplayLists);

    painter.endNativePainting();
    painter.drawText(20, 40, "Foo");
    painter.end();

}
1 Answers

You can create a QOpenGLTexture object directly from a QImage: https://doc.qt.io/qt-5/qopengltexture.html#QOpenGLTexture-1

You can then use that texture directly for any image related OpenGL operations.

Basically the whole idea is writing to back buffer and restoring the back buffer and render pixels to avoid redraw.

Don't do that! It will actually impair performance, since drawing on top of previously rendered content introduces implicit synchronization points, thereby eliminating options to render new contents in parallel to advancing the presentation swap chain.

As "counterintuitive" as it may sound, just redraw the whole thing, each and every frame. If your codebase is that old, then the complexity of what you're drawing very likely is going to be so low, that you could easily render thousands of frames per second.

On the other hand retaining the contents of the backbuffer constitutes a cache and thus introduces the complexity of deciding upon cache invalidation.

I bet, that just redrawing using modern methods (geometry in buffer objects, index buffers, untangling of sync points) and simplifying the rendering code path by mere elimination the code that's responsible for determining when to actually redraw portions of the picture will actually vastly outperform anything what you had before.

Related