Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QOpenGLFramebufferObject not working when it is larger than viewport?

QOpenGLFramebufferObject not working when it is larger than viewport?

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 1.8k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    drwho
    wrote on last edited by
    #1

    I'm using QOpenGLFramebufferObject as a QPaint device, then drawing a texture from the fbo in the QGLWidget. A QOpenGLFramebufferObject and QPainter are created and destroyed each time make_text() is called. The example below creates a 600x600 fbo with a 300x300 viewport. The first call to make_text() is fine, all calls after the first mess up the projection. If I limit the fbo to the viewport size there is no issue. The corruption seams to happen at the first use of the QPainter eraseRect(). I have no idea why this is breaking.

    main.h
    @
    #include <QGLWidget>
    #include <QGLFunctions>
    #include <QGLFramebufferObject>
    #include <QFont>
    #include <QGLShader>

    class glview : public QGLWidget, protected QGLFunctions
    {
    Q_OBJECT

    public:
    explicit glview(QWidget *parent = 0);
    ~glview();
    QSize sizeHint() const;

    protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();

    private:
    void make_text(void);
    QGLFramebufferObject *fbo;
    QFont font;
    quint32 vbo_id[1], texture_id;
    QGLShaderProgram *txtovlp;
    QTimer *delay;

    private slots:
    void refresh(void);
    };
    @

    main.cpp
    @
    #include <QApplication>
    #include <QPainter>
    #include <QTimer>
    #include "main.h"

    struct txtr_vrtx {
    GLfloat x;
    GLfloat y;
    GLfloat z;
    GLfloat tx;
    GLfloat ty;
    }attribute((packed)) txtr_geo[] = {
    // x, y, z, tx,ty
    {0, 0, 0, 0, 0},
    {0, 6, 0, 0, 1},
    {6, 6, 0, 1, 1},
    {6, 0, 0, 1, 0},
    };

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);
    glview widget;
    widget.show();
    return app.exec();
    }

    glview::glview(QWidget *parent) : QGLWidget(parent)
    {
    fbo = NULL;
    font.setFamily("Helvetica");
    delay = new QTimer;
    delay->start(2000);
    connect(delay, SIGNAL(timeout()), this, SLOT(refresh()));
    }

    glview::~glview()
    {
    delete fbo;
    }

    void glview::refresh(void)
    {
    delay->stop();
    qDebug() << "refresh fired";
    make_text();
    updateGL();
    }

    void glview::make_text(void)
    {
    glBindBuffer(GL_ARRAY_BUFFER, 0); // must unbind for QPainter

    glEnable(GL_TEXTURE_2D);
    if (fbo)
    delete fbo;
    fbo = new QGLFramebufferObject(600, 600, GL_TEXTURE_2D);
    fbo->bind();
    texture_id = fbo->texture();

    QPainter painter(fbo);
    font.setPointSize(20);
    painter.setFont(font);
    painter.eraseRect(0,0,600,600);
    painter.setPen(Qt::blue);
    painter.drawText(250, 310, "FBO");
    painter.setPen(Qt::red);
    painter.drawText(100, 310, "FBO");
    painter.setPen(Qt::green);
    painter.drawText(250, 510, "FBO");
    painter.end();

    fbo->release();
    }

    QSize glview::sizeHint() const
    {
    return QSize(300, 300);
    }

    void glview::initializeGL()
    {
    initializeGLFunctions();
    qglClearColor(Qt::white);

    QGLShader *txtovlp_vshader = new QGLShader(QGLShader::Vertex, this);
    const char *txtovlp_vsrc =
    "attribute highp vec4 vertex;\n"
    "attribute mediump vec2 texCoord;\n"
    "varying mediump vec2 texc;\n"
    "uniform mediump mat4 matrix;\n"
    "void main(void)\n"
    "{\n"
    " gl_Position = matrix * vertex;\n"
    " texc = texCoord;\n"
    "}\n";
    txtovlp_vshader->compileSourceCode(txtovlp_vsrc);

    QGLShader *txtovlp_fshader = new QGLShader(QGLShader::Fragment, this);
    const char *txtovlp_fsrc =
    "uniform sampler2D texture;\n"
    "varying mediump vec2 texc;\n"
    "void main(void)\n"
    "{\n"
    " gl_FragColor = texture2D(texture, texc.st);\n"
    "}\n";
    txtovlp_fshader->compileSourceCode(txtovlp_fsrc);

    txtovlp = new QGLShaderProgram(this);
    txtovlp->addShader(txtovlp_vshader);
    txtovlp->addShader(txtovlp_fshader);
    txtovlp->link();

    glGenBuffers(1, vbo_id);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(txtr_geo), txtr_geo, GL_STATIC_DRAW);

    make_text();

    glEnable(GL_DEPTH_TEST);
    }

    void glview::resizeGL(int w, int h)
    {
    glViewport(0, 0, w, h);
    }

    void glview::paintGL()
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 matrix;
    matrix.ortho(1.5, 4.5, 1.5, 4.5, -1, 1);
    //matrix.translate(1,1,0);

    txtovlp->bind();
    txtovlp->setUniformValue("matrix", matrix);
    //txtovlp->setUniformValue("texture", 0);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);

    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glBindTexture(GL_TEXTURE_2D, texture_id);

    int txtr_vertexLocation = txtovlp->attributeLocation("vertex");
    txtovlp->enableAttributeArray(txtr_vertexLocation);
    glVertexAttribPointer(txtr_vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(struct txtr_vrtx), 0);

    int texCoordLocation = txtovlp->attributeLocation("texCoord");
    txtovlp->enableAttributeArray(texCoordLocation);
    glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(struct txtr_vrtx), ((char*)NULL + 12));

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glFlush();
    }

    @

    1 Reply Last reply
    0
    • A Offline
      A Offline
      agocs
      wrote on last edited by
      #2

      Is the correct context current when calling make_text from refresh? Try doing a makeCurrent in refresh() before calling make_text.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        drwho
        wrote on last edited by
        #3

        I tried calling makeCurrent() before make_text(), no change. Also tried putting a makeCurrent() in the beginning of the paintGL(). Also tried both places at the same time. It feels like the matrix is getting messed up but qDebug() << matrix in paintGL() shows it is the same the first and last paint event. Maybe there is a bug in my shader programs?

        1 Reply Last reply
        0
        • D Offline
          D Offline
          drwho
          wrote on last edited by
          #4

          QPainter trashes the GL context and I've learned that also includes the viewport. By adding glViewport(0, 0, width(), height()); at the end of make_text() (after QPainter is finished) restores the viewport for the next paint event.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved