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.
QPaint onto QGLFramebufferObject texture?
Вопрос
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();
}
Решение
Другие советы
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();
}
Не связан с StackOverflow