سؤال

I am trying to learn how to use QPainter with a QGLFramebufferObject. When I try to display the texture in a QGLWidget, it is not visible. (complete code below)

The end goal is to use QPainter to draw text onto textures and then alpha blend the texture overtop of the 2D line geometry.

texture.pro

QT += core gui widgets opengl

TARGET = test
TEMPLATE = app

SOURCES = main.cpp
HEADERS = main.h

main.h

#include <QGLWidget>
#include <QGLFunctions>

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:
    quint32 vbo_id[2], texture_id;
};

main.cpp

#include <QApplication>
#include <QGLFramebufferObject>
#include <QPainter>
#include "main.h"

struct vrtx {
    GLint   x;
    GLint   y;
    GLubyte r;
    GLubyte g;
    GLubyte b;
}__attribute__((packed)) line_geo[] = {
//   x, y,   r, g, b
    {1, 1, 255, 0, 0},
    {1, 2, 0, 255, 0},
    {1, 2, 0, 255, 0},
    {2, 2, 255, 0, 0},
    {2, 2, 255, 0, 0},
    {2, 1, 0, 255, 0},
    {2, 1, 0, 255, 0},
    {1, 1, 255, 0, 0},
};

struct txtr_vrtx {
    GLint   x;
    GLint   y;
    GLint   tx;
    GLint   ty;
}__attribute__((packed)) txtr_geo[] = {
//   x, y, tx,ty
    {3, 1, 0, 0},
    {3, 2, 0, 1},
    {4, 2, 1, 1},
    {4, 1, 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)
{

}

glview::~glview()
{

}

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

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

    glGenBuffers(2, vbo_id);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(line_geo), line_geo, GL_STATIC_DRAW);

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

    QGLFramebufferObject fbo(100, 100, QGLFramebufferObject::CombinedDepthStencil/*GL_TEXTURE_2D*/);
    fbo.bind();
    texture_id = fbo.texture();

    QPainter painter(&fbo);
    painter.fillRect(0, 0, 100, 100, Qt::blue);
    painter.end();

    fbo.release();
}

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

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

    glLoadIdentity();
    glOrtho(0, 5, 0, 3, -1, 1);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glVertexPointer(2, GL_INT, sizeof(struct vrtx), 0);
    glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(struct vrtx), ((char*)NULL + 8));
    glDrawArrays(GL_LINES, 0, sizeof(line_geo) / sizeof(struct vrtx));

    //glColor4ub(0, 0, 255, 255);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D);

    glDisableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

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

    glVertexPointer(2, GL_INT, sizeof(struct txtr_vrtx), 0);
    glTexCoordPointer(2, GL_INT, sizeof(struct txtr_vrtx), ((char*)NULL + 8));
    glDrawArrays(GL_QUADS, 0, 4);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    glDisable(GL_TEXTURE_2D);
    //glDisable(GL_BLEND);

    glFlush();
}
هل كانت مفيدة؟

المحلول

The QGLFramebufferObject instance is destroyed when leaving initializeGL(). This results in deleting the texture too. You need to keep the QGLFramebufferObject alive until the texture is no longer needed.

نصائح أخرى

Here is the corrected code. Also with alpha bending.

main.h

#include <QGLWidget>
#include <QGLFunctions>
#include <QGLFramebufferObject>
#include <QFont>

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:
    QGLFramebufferObject *fbo;
    QFont font;
    quint32 vbo_id[2], texture_id;
};

main.cpp

#include <QApplication>
#include <QPainter>
#include "main.h"

struct vrtx {
    GLint   x;
    GLint   y;
    GLubyte r;
    GLubyte g;
    GLubyte b;
}__attribute__((packed)) line_geo[] = {
//   x, y,   r, g, b
    {1, 1, 255, 0, 0},
    {1, 2, 0, 255, 0},
    {1, 2, 0, 255, 0},
    {2, 2, 255, 0, 0},
    {2, 2, 255, 0, 0},
    {2, 1, 0, 255, 0},
    {2, 1, 0, 255, 0},
    {1, 1, 255, 0, 0},
};

struct txtr_vrtx {
    GLint   x;
    GLint   y;
    GLint   tx;
    GLint   ty;
}__attribute__((packed)) txtr_geo[] = {
//   x, y, tx,ty
    {3, 1, 0, 0},
    {3, 2, 0, 1},
    {4, 2, 1, 1},
    {4, 1, 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)
{
    font.setFamily("Helvetica");
}

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

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

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

    glGenBuffers(2, vbo_id);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(line_geo), line_geo, GL_STATIC_DRAW);

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

    glBindBuffer(GL_ARRAY_BUFFER, 0);       // must unbind for QPainter

    fbo =  new QGLFramebufferObject(100, 100, GL_TEXTURE_2D);
    fbo->bind();
    texture_id = fbo->texture();

    QPainter painter(fbo);
    painter.setPen(Qt::blue);
    font.setPointSize(20);
    painter.setFont(font);
    painter.drawText(0, 60, "FBO");
    painter.end();

    fbo->release();
}

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

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

    glLoadIdentity();
    glOrtho(0, 5, 0, 3, -1, 1);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
    glVertexPointer(2, GL_INT, sizeof(struct vrtx), 0);
    glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(struct vrtx), ((char*)NULL + 8));
    glDrawArrays(GL_LINES, 0, sizeof(line_geo) / sizeof(struct vrtx));

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

    glDisableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

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

    glVertexPointer(2, GL_INT, sizeof(struct txtr_vrtx), 0);
    glTexCoordPointer(2, GL_INT, sizeof(struct txtr_vrtx), ((char*)NULL + 8));
    glDrawArrays(GL_QUADS, 0, 4);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glFlush();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top