在OpenGL中使用持久屏幕缓冲区来优化性能

时间:2014-02-08 13:36:02

标签: python performance opengl buffer glut

我目前正在开发一个使用2D OpenGL图形的Python程序。它主要用于大屏幕分辨率和相对较慢的计算机,因此,虽然它都可以正常工作,但它可以通过优化图形来获得一些性能提升。

所以这就是我所拥有的:屏幕背景是在程序启动时由多个图像组成的,之后永远不会改变。所以,我想知道是否可以将生成的屏幕数据写入缓冲区,然后在主绘图循环中不断使用,以绕过绘制背景所涉及的所有功能。

所以这就是我想做的事情:

def drawBackground(self):  #Called once on startup
    for item in BackObjects:
        item.draw()
    # [CODE HERE] Writing the screen pixel data to a buffer (a lower layer?)

def drawObjects(self):  #Called in the main drawing loop
    # [CODE HERE] Clear the buffer (possibly only the top layer?)
    glLoadIdentity()
    glPushMatrix()
    # [CODE HERE] Read the previously defined background buffer to the screen?
    for item in FrontObjects:
        item.draw()
    glPopMatrix()
    glutSwapBuffers()

我已阅读有关缓冲区的不同GL函数的手册,并尝试使用glDrawBuffer()和glReadBuffer()之类的函数,但还没有弄清楚如何使其工作...... < / p>

所以,如果我想要有2个绘图层,其中一个始终保持不变,我应该如何操作缓冲区来实现这一点,最大化程序的性能?

如果您能根据我上面发布的内容提供示例代码,我将不胜感激!

2 个答案:

答案 0 :(得分:0)

是的,你可以这样做。但是,除非您的呈现非常非常非常复杂,否则这种缓存通常不值得花时间来实现它。

  

它主要用于大屏幕分辨率和相对较慢的计算机,因此,虽然它都可以正常工作,但它可以通过优化图形来获得一些性能提升。

我很确定,通过切换到现代OpenGL编程技术,您可以大大提高性能。例如,查找glBegin(…); … glEnd();块的任何出现:摆脱那些,那些是性能杀手!顶点缓冲区对象中使用顶点数组 相反(或者你可以使用显示列表如果你不想使用现代OpenGL,但我建议不要使用它们。)

如果你真的想在现代OpenGL中使用后台缓存,那么使用framebuffer对象非常容易。创建一个“背景”FBO,您可以在其上附加颜色和深度模板渲染缓冲区。然后使用glBlitFramebuffer从背景图像帧缓冲区复制到主帧缓冲区。

从技术上讲,您可以通过此blitting操作替换glClear,但我建议您在每帧之前仍然清除窗口帧缓冲;许多驱动程序使用它作为提示,即将绘制新帧,这可以提高性能。然而,glClear的填充费用也可能使事情变得更糟。

答案 1 :(得分:0)

好的,我一直在研究FrameBuffers存储静态背景,我似乎迷失在这里...... 这是我的背景生成和主绘图循环函数到目前为止的样子:

def MakeBackground(self):
    self.BufferBack = glGenFramebuffers(1)
    self.BufferRender = glGenRenderbuffers(1)
    glBindRenderbuffer(GL_RENDERBUFFER, self.BufferRender)
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, self.ScreenWidth, self.ScreenHeight)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glPushMatrix()      
    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT)
    for obj in BackObjects:
        obj.drawBack()  
    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT)
    glPopMatrix()
    glBindFramebuffer(GL_FRAMEBUFFER, self.BufferBack)
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.BufferRender)
    glutSwapBuffers()
    glBindRenderbuffer(GL_RENDERBUFFER, 0)
    glBindFramebuffer(GL_FRAMEBUFFER, 0)

def DrawCycle(self):
    self.UpdatePositions()
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glPushMatrix()

    glBindFramebuffer(GL_FRAMEBUFFER, self.BufferBack)
    glBlitFramebuffer(0,0,1920,1080,0,0,1920,1080,GL_COLOR_BUFFER_BIT,GL_LINEAR)
    glBindFramebuffer(GL_FRAMEBUFFER, 0)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT)
    for obj in FrontObjects:
        obj.draw()
    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT)
    glPopMatrix()
    glutPostRedisplay()
    glutSwapBuffers()

我正在尝试在主绘图循环中绘制存储在“self.BufferBack”帧缓冲区中的背景。背景只是在第一帧中绘制(执行MakeBackground函数时),然后消失。也许是因为当执行glClear时帧缓冲被清除了?或者也许渲染的背景甚至没有存储在那里? (基于我在编辑glClear时看到的内容,背景不会被glBlitFramebuffer重新绘制...)

我希望有使用缓冲区的人可以在这里指出一些错误...... :)我很确定它们必须是显而易见的。我在这里没有想出所有正确的动作,可能只是完全滥用了所有的帧缓冲函数......