reckless
reckless

Reputation: 933

How to transfrom a QRect to OpenGL coordinates?

I have an app where a several QOpenGLFramebufferObject needs to be blitted onto a larger QOpenGLFramebufferObject. In order to do so, I thought I could simply "paste" the fbos onto the large fbo using the standard coordinates in Qt. The QOpenGLFramebufferObject::blitFramebuffer requires a "source" rect and a "target" rect. So for example, if my large fbo is 1000x1000 and my smaller fbos are 500x500. Then I would simply need to do the following:

auto sourceRect = QRect(0,0,500,500);
// i here would be the row of my grid of fbos
// j would be the column
for(int i =0; i < 2; i++){
    for(int j= 0; j < 2; j++){
            auto targetRect = QRect(i*500,j*500, 500, 500);
            // tileFbo are the small fbos
            QOpenGLFramebufferObject::blitFramebuffer(largeFbo,targetRect, tileFbo,sourceRect)
    }
}

However, this doesn't work as it seems that QOpenGLFramebufferObject uses OpenGL coordinates. So how I can convert my QRect to use OpenGL coordinates?

Here is an example where I draw a line a small fbo (500x500) and then blit the small fbo on a large fbo (1000x1000). The line on the large fbo appears to be at the bottom-left instead of the top-left.

#include <QGuiApplication>
#include <QOffscreenSurface>
#include <QOpenGLFramebufferObject>
#include <QOpenGLContext>
#include <QPainter>
#include <QOpenGLPaintDevice>
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);
    QSurfaceFormat format;
    format.setSamples(8);
    QOffscreenSurface* surface = new QOffscreenSurface;
    surface->setFormat(format);
    surface->create();

    QOpenGLContext* context = new QOpenGLContext;
    if(!context->create()){
        qDebug() << "Failed to create context";
    }
    context->makeCurrent(surface);

    auto smallFbo = new QOpenGLFramebufferObject(QSize(500,500));
    auto largeFbo = new QOpenGLFramebufferObject(QSize(1000,1000));
    smallFbo->bind();
    QOpenGLPaintDevice paintDevice(smallFbo->size());
    QPainter painter(&paintDevice);
    painter.drawLine(QLine(0,0,400,400));
    smallFbo->release();
    // save small fbo to disk
    smallFbo->toImage().save("/home/Desktop/smallfbo.png");

    // blit the frame buffers
    QOpenGLFramebufferObject::blitFramebuffer(largeFbo, QRect(0,0,500,500), smallFbo, QRect(0,0,500,500));
    // save large fbo to disk
    largeFbo->toImage().save("/home/Desktop/largefbo.png");
    return 0;
}

Upvotes: 1

Views: 237

Answers (1)

Robert.K
Robert.K

Reputation: 126

As far as i understand, this function is everything you need

QRect to_OpenGL_coordinates(const QRect& qt_coordinateRect, const QOpenGLFramebufferObject& fbo){
    return QRect(qt_coordinateRect.x(), fbo.height() - qt_coordinateRect.y(),
                 qt_coordinateRect.width(), qt_coordinateRect.height() * -1);
}

and use it like this

// blit the frame buffers
    QOpenGLFramebufferObject::blitFramebuffer(largeFbo, to_OpenGL_coordinates(QRect(0,0,500,500), *largeFbo),
                                              smallFbo, to_OpenGL_coordinates(QRect(0,0,500,500), *smallFbo));

as a result.

enter image description here

Upvotes: 1

Related Questions