我尝试在Qt5.3中做一些屏幕外渲染工作,我想用QOpenGLFramebufferObject::toImage
输出每张图片(我想在render()绘制不同的东西时输出几张图片。)
按照this的说明,我成功地在屏幕外渲染了我的第一张照片并输出了它。因此,对于将来,我将编写一个示例作为以下代码,这里是a package in Google。我可以得到第一个fbo内容(及其输出文件正确,但从第二次,fbo没有重新渲染(),它总是输出相同的图片)。
所以我想知道在完成一次屏幕外渲染后我该怎么办才能确保下一次在qt中正确?或者是否有人可以告诉我如何在QOffscreenSurface
中正确设置动画?
qtestofffscreen.h:
#ifndef QTESTOFFSCREEN_H
#define QTESTOFFSCREEN_H
#include <QOffscreenSurface>
#include <QWindow>
#include <QtGui/QOpenGLFunctions_3_3_Core>
#include <QImage>
#include <QGLFramebufferObject>
#include <QOpenGLPaintDevice>
#include <QOpenGLFunctions>
#include <QMutex>
#include <QMutexLocker>
class QTestOffScreen : public QOffscreenSurface,
protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit QTestOffScreen(
QScreen* targetScreen = nullptr,
const QSize& size = QSize (1, 1));
~QTestOffScreen();
virtual void render();
virtual void initialize();
void renderNow();
void setAnimating(bool animating);
bool event(QEvent *) override;
void renderLater();
int counts;
private:
QGLFramebufferObject *fbo;
bool m_animating;
bool m_update_pending;
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
QSize m_size;
QMutex mutex;
signals:
void doneImg(int index);
};
#endif // QTESTOFFSCREEN_H
qtestofffscreen.cpp:
#include "qtestoffscreen.h"
#include <QTime>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLFramebufferObject>
QTestOffScreen::QTestOffScreen(QScreen *targetScreen,
const QSize &size):
QOffscreenSurface(targetScreen),
m_size(size),
fbo(Q_NULLPTR),
m_context(Q_NULLPTR),
m_device(Q_NULLPTR),
counts(100)
{
requestedFormat().setVersion(3,3);
setFormat(requestedFormat());
create();
m_context = new QOpenGLContext(this);
m_context->setFormat(format());
if (m_context->create())
{
m_context->makeCurrent(this);
m_context->functions()->initializeOpenGLFunctions();
}else
{
delete m_context;
m_context = Q_NULLPTR;
throw ("Still wrong here");
}
//To make sure m_context was initialized
//in first time entering renderNow()
delete m_context;
m_context = Q_NULLPTR;
}
QTestOffScreen::~QTestOffScreen()
{
delete m_context;
delete m_device;
if (fbo)
delete fbo;
}
void QTestOffScreen::render()
{
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
| GL_TEXTURE_BIT);
glViewport(0,0,1920,1080);
glOrtho(0,1920,0,1080,0,1);
glColor3f(1.0,0.0,0.0);
float tmp = float(qrand()%1000);
float count = (float)counts * 10.0f;
glLineWidth(3.0f);
glBegin(GL_LINE_LOOP);
glVertex2f(count ,count );
glVertex2f(count + 100,count);
glVertex2f(count + 50,count + 100);
glEnd();
qDebug()<<QString("current tmp is %1").arg(count);
}
void QTestOffScreen::initialize()
{
if (!fbo)
{
fbo = new QGLFramebufferObject(1920,1080,GL_TEXTURE_2D);
}
fbo->bind();
}
void QTestOffScreen::renderNow()
{
bool needsInitialize = false;
if (!m_context)
{
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
if (m_context->isValid())
{
qDebug()<<"Right Here when creating m_context in renderNow";
}
needsInitialize = true;
}
if ( !m_context->makeCurrent(this) )
{
qDebug()<<"This fails in makeCurrent";
}
if (needsInitialize)
{
initializeOpenGLFunctions();
initialize();
}
render();
qDebug()<<counts;
counts--;
fbo->toImage().save(QString::number(counts) + QString(".png"));
m_context->doneCurrent();
if (counts >= 0)
{
m_update_pending = false;
emit doneImg(counts);
}
}
void QTestOffScreen::setAnimating(bool animating)
{
m_animating = animating;
m_update_pending = false;
if (m_animating)
renderLater();
}
bool QTestOffScreen::event(QEvent *event)
{
switch (event->type())
{
case QEvent::UpdateRequest:
m_update_pending = true;
renderNow();
return true;
default:
return QOffscreenSurface::event(event);
}
}
void QTestOffScreen::renderLater()
{
if (!m_update_pending)
{
m_update_pending = true;
QCoreApplication::postEvent(this,new QEvent(QEvent::UpdateRequest));
}
}
void QTestOffScreen::generateImg(QImage *tmp_img_pointer)
{
GLint viewPort[4]={0};
glGetIntegerv(GL_VIEWPORT,viewPort);
int win_width,win_height;
win_width = 1920;
win_height = 1080;
GLubyte *colorArr=new GLubyte[win_width*win_height*3];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadBuffer (GL_FRONT);
int tmp_x,tmp_y;
tmp_x = 0;
tmp_y = 0;
glReadPixels(tmp_x,tmp_y,win_width,win_height,
GL_RGB,GL_UNSIGNED_BYTE,colorArr);
int winrows = tmp_img_pointer->height();
int wincols = tmp_img_pointer->width ();
for(int ii=0; ii < winrows * wincols * 3; ii ++)
{
if((colorArr[ii] <0)|(colorArr[ii] >255))
{ colorArr[ii] = 255; }
}
for(int j=0;j<winrows;j++)
for(int i=0;i<wincols;i++)
{
int index=(j*wincols+i)*3;
QRgb value=qRgb(colorArr[index+2],
colorArr[index+1],
colorArr[index ]);
tmp_img_pointer->setPixel(i,winrows-j-1,value);
}
delete colorArr;
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qtestoffscreen.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QTestOffScreen *scr;
private slots:
void ReceiveCurrentIndex(int);
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSurfaceFormat format;
format.setSamples(1);
format.setRenderableType(QSurfaceFormat::OpenGL);
scr = new QTestOffScreen();
connect(scr,SIGNAL(doneImg(int)),this,SLOT(ReceiveCurrentIndex(int)));
scr->setFormat(format);
scr->setAnimating(true);//Start rendering animation here.
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ReceiveCurrentIndex(int)
{
Sleep(100);
scr->renderLater();
}