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



我目前正在开发一个使用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(。。。

所以,如果我想有两个绘图层,其中一个始终保持不变,我应该如何操作缓冲区来做到这一点,最大限度地提高程序的性能?

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

是的,你可以做到。然而,除非您的渲染非常复杂,否则这种缓存通常不值得花时间来实现它

它主要用于大屏幕分辨率和相对较慢的计算机,因此,虽然一切都很好,但它可以通过优化图形来提高一些性能。

我敢肯定,通过切换到现代OpenGL编程技术,您可以极大地提高性能。例如,查找任何出现的glBegin(…); … glEnd();块:去掉它们,它们是性能杀手顶点缓冲区对象中使用的顶点数组(如果不想使用现代OpenGL,也可以使用display lists,但我建议不要使用它们)。

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

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

好吧,我一直在研究用于存储静态背景的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重新绘制…)

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

最新更新