问题
In my application I take snapshots of a QGLWidget's contents for two purposes:
- Not redraw the scene all the time when only an overlay changes, using a cached pixmap instead
- Lat the user take screenshots of the particular plots (3D scene)
The first thing I tried is grabFrameBuffer()
. It is natural to use this function as for the first application, what is currently visible in the widget is exactly what I want to cache.
PROBLEM: On some hardware (e.g. Intel integrade graphics, Mac OS X with GeForce graphics), the image obtained does not contain the current screen content, but the content before that. So if the scene would be drawn two times, on the screen you see the second drawing, in the image you see the first drawing (which should be the content of the backbuffer?).
The second thing I tried is renderToPixmap()
. This renders using paintGL()
, but not using paint()
. I have all my stuff in paint()
, as I use Qt's painting functionality and only a small piece of the code uses native GL (beginNativePainting()
, endNativePainting()
).
I also tried the regular QWidget's snapshot capability (QPixmap::fromWidget(), or what it is called), but there the GL framebuffer is black.
Any ideas on how to resolve the issue and get a reliable depiction of the currently drawn scene?
回答1:
How to take reliable QGLWidget snapshot
Render current scene to framebuffer, save data from framebuffer to file. Or grab current backbuffer after glFlush. Anything else might include artifacts or incomplete scene.
回答2:
It seems that QGLWidget::grabFrameBuffer() internally calls glReadPixels() from OpenGL. On double-bufferd configurations the initial mode reads the back buffer (GL_BACK), switch with the OpenGL call glReadBuffer(GL_FRONT) to the front buffer before using QGLWidget::grabFrameBuffer() displaying an image on the screen.
回答3:
The result of QGLWidget::grabFrameBuffer()
, like every other OpenGL calls, depends on the video driver. Qt merely forwards your call to the driver and grabs the image it returns, but the content of the image is not under Qt's control. Other than making sure you have installed the latest driver for your video card, there is not much you can do except report a bug to your video card manufacturer and pray.
回答4:
I use paintGL();
and glFlush()
; before using grabFrameBuffer()
. The paintGL helps to draw current frame again before grab the frame buffer, which makes an exact copy of what is currently showing.
来源:https://stackoverflow.com/questions/10429452/how-to-take-reliable-qglwidget-snapshot