PDA

View Full Version : QGraphicsView + native opengl painting -> rendering to image



Stef
7th October 2011, 20:27
I have a QGraphicsView and on this view I place several subclassed QGraphicsItems which implement their own paint method. Now I want to render the graphicsview/scene to an image and save this to disk. I use the following method to render the scene to an image:



QPainter *pngPainter = new QPainter();
QImage *image = new QImage(QSize(width,height), QImage::Format_ARGB32_Premultiplied);

pngPainter->begin(image);
pngPainter->setRenderHint(QPainter::Antialiasing);
_ui->graphicsView->scene()->render(pngPainter);
pngPainter->end();
image->save(fileName);

delete pngPainter;
delete image;


This works perfectly when I use QPainter commands in the paint procedure of the QGraphicsItems, like so (block is a QRectF):



void CNodeGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// color setup
painter->setPen(Qt::red);
painter->setBrush(Qt::red);

painter->drawRect(block);
}


However, If (for performance reasons and in order to use shaders) I use native opengl commands, like so:



void CNodeGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->beginNativePainting();
glBegin(GL_QUADS);
setGLColor(Qt::red); // Own function to set glColor3f;
glTexCoord2f (0.0, 0.0);glVertex2d(block.left(),block.top());
glTexCoord2f (1.0, 0.0);glVertex2d(block.right(),block.top());
glTexCoord2f (1.0, 1.0);glVertex2d(block.right(),block.bottom());
glTexCoord2f (0.0, 1.0);glVertex2d(block.left(),block.bottom());
glEnd();
painter->endNativePainting();
}


It no longer works and the output is an entire black image. The rendering on the QGraphicsView gives the expected result though (a red rectangle). Any ideas on how to solve this / make it work with native opengl commands?

I know I can grab the framebuffer:


QImage img = ((QGLWidget*)_ui->graphicsView->viewport())->grabFrameBuffer(true);
img.save(fileName, "PNG", 100);


This works, however the output image is only the size of the graphicsView, I want to be able
to output high-res images.

wysota
7th October 2011, 20:33
Try rendering to a gl pixel (or frame) buffer and then converting the result to a QImage. By the way, never create QImage instances on the heap, it makes no sense.

Stef
8th October 2011, 13:50
Thank you for pointing me into the right direction. I now render to an offscreen framebuffer and convert that to QImage. For completeness here is my solution:



QGLFramebufferObjectFormat format;
format.setSamples(16);

QGLFramebufferObject renderFbo(4096, 4096);

QPainter fboPainter(&renderFbo);

fboPainter.setRenderHint(QPainter::Antialiasing);
fboPainter.setRenderHint(QPainter::HighQualityAnti aliasing);
_ui->graphicsView->scene()->render(&fboPainter);
fboPainter.end();

renderFbo.toImage().save(fileName, "PNG", 100);