2014-02-05 58 views
0

我有一个PyQt应用程序,其中QtOpenGL.QGLWidget显示一个风力涡轮机。从高分辨率的opengl(pyqt)保存图像:

我想涡轮保存为高resulution的图像,但到目前为止,我只能够保存渲染的屏幕图像,也就是在我的情况下1680×1050减去边框,工具栏等

glPixelStorei(GL_PACK_ALIGNMENT, 1) 
data = glReadPixels(0, 0, self.width, self.height, GL_RGBA, GL_UNSIGNED_BYTE) 

我怎样才能解决这个限制?

编辑

我一直在使用一个帧缓冲区试过,

from __future__ import division 
import OpenGL 
from OpenGL.GL import * 
from OpenGL.GLU import * 
from OpenGL.GLUT import * 
from PIL import Image 
import time, sys 
import numpy as np 


WIDTH = 400 
HEIGHT = 300 

def InitGL(): 
    glMatrixMode(GL_PROJECTION) 
    gluPerspective(45.0, float(WIDTH)/float(HEIGHT), 0.1, 100.0) 
    glMatrixMode(GL_MODELVIEW) 


def DrawGLScene(): 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
    glLoadIdentity() 
    glTranslatef(0, 0., -3) 
    glutWireTeapot(1) 
    glFlush() 

def capture_screen(): 
    DrawGLScene() 
    glPixelStorei(GL_PACK_ALIGNMENT, 1) 
    data = glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE) 
    image = Image.fromstring("RGBA", (WIDTH, HEIGHT), data) 
    image.transpose(Image.FLIP_TOP_BOTTOM).show() 

def capture_fbo(width=800, height=600): 

    fbo = glGenFramebuffers(1) 
    render_buf = glGenRenderbuffers(1) 

    glBindRenderbuffer(GL_RENDERBUFFER, render_buf) 

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo) 
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf); 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
    glMatrixMode(GL_MODELVIEW) 
    glLoadIdentity() 
    glTranslatef(1, 1., -3) 
    glScale(width/WIDTH, height/HEIGHT, 1) 
    glutWireTeapot(1.0) 
    glFlush() 
    glReadBuffer(GL_COLOR_ATTACHMENT0); 
    data = glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE) 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 
    image = Image.fromstring("RGBA", (width, height), data) 
    image.transpose(Image.FLIP_TOP_BOTTOM).show() 

    glDeleteFramebuffers(1, [fbo]); 
    glDeleteRenderbuffers(1, [render_buf]); 


glutInit(sys.argv) 
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH) 
glutInitWindowSize(WIDTH, HEIGHT) 
window = glutCreateWindow("") 
glutDisplayFunc(DrawGLScene) 
InitGL() 
DrawGLScene() 
capture_screen() 
capture_fbo() 

glutMainLoop() 

,但没有在该地区被描绘的常态屏幕窗口区域外 enter image description here

+0

创建一个更高分辨率的FBO渲染到它并保存 –

+0

我已经尝试过,但我没有成功看到有问题的编辑 –

回答

0

方式glReadPixels的工作原理是它从当前选择的帧缓冲区中读取像素。

不确定帧缓冲是什么?这里是维基页面:http://www.opengl.org/wiki/Framebuffer_Object

一个简单的解释是,您可以将帧缓冲区视为您的图形卡所用的“画布”。您可以拥有任意数量的帧缓冲区(sorta ...大多数驱动程序在某处定义了一个限制),但只会显示一个限制。这是所选的帧缓冲区,并且只能与您在屏幕上显示的窗口一样大。

这里有上作出的framebuffer教程:http://www.lighthouse3d.com/tutorials/opengl-short-tutorials/opengl_framebuffer_objects/

修改它,这样你所创建的帧缓冲区是要采取从截图的分辨率。

一旦帧缓冲区设置,您可以绘制它像这样:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer); 
/* drawing code */ 
glReadPixels(); 

如果你希望能够仍然在屏幕上看到的东西,你将需要画到默认的帧缓冲绘制到新的帧缓冲区后:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //"0" means return to default framebuffer 
/* same drawing code */ 

请注意,这意味着您将绘制整个场景两次!确保你的帧率可以处理它。