在python中将像素渲染到屏幕的最佳方法?

问题描述

我正在用python编写交互式(缩放/平移)mandelbrot集查看器,并且遇到了一些性能问题。我目前正在使用pyglet和PyOpenGL渲染像素,因为我喜欢它处理鼠标事件的方式。我使用numpy生成像素值,并且在堆栈交换/文档/其他地方进行了一些搜索之后,当前正在使用glDrawPixels绘制像素。该应用程序非常慢,大约需要1.5秒钟才能绘制完毕。我听说使用纹理的速度要快得多,但是我没有使用它们的经验,因此了解很多OpenGL似乎是不必要的。我考虑过的另一种方法是使用顶点列表和pyglet批处理渲染,但是在屏幕上的每个像素处创建新的GL_POINT似乎是错误的。我要解决所有这些错误吗?当像素变化如此频繁时,是否有更好的方法在屏幕上呈现某些内容?下面的代码

# this code all is in a class that subclasses pyglet.window.Window
# called every 1/10.0 seconds,update 10 frames
def update_region(self):
    # this code just computes new mandelbrot detail
    if self.i < self.NUM_IT:
        for _ in range(10): # do 10 iterations every update,can be customizable
            self.z = np.where(np.absolute(self.z) < self.THRESHOLD,self.z ** 2 + self.reg,self.z)
            self.pixels = np.where(
                            (self.pixels == self.NUM_IT) & (np.absolute(self.z) > 
                             self.THRESHOLD),self.i,self.pixels)
            self.i = self.i + 1


def update_frame(self,x,y):
    self.update_region()
    # color_pixels is what will actually be rendered
    self.color_pixels = self.cmap.to_rgba(self.pixels).flatten()


def on_draw(self): # draw method called every update (set to .1s)
    
        start = time.time()
        glClear(GL_COLOR_BUFFER_BIT)
        glDrawPixels(2 * self.W,2 * self.H,GL_RGBA,GL_FLOAT,(GLfloat * len(self.color_pixels))(*self.color_pixels))
        glutSwapBuffers()
        print('on_draw took {0} seconds'.format(time.time() - start))

解决方法

您确定是glDrawPixels拖慢了您的速度吗?在您的update_frame代码中,有一个cmap.to_rgba(),我认为是将Mandelbrot计算出的单个值映射到RGB三元组,然后执行.flatten()。复制整个图像两次将无济于事。

对于绘制不需要3D缩放的光栅图像,pyglet具有图像模块和.blit()

您是对的,点的顶点列表将无济于事。

将图像加载到纹理中将需要更多的OpenGL代码,但不会太多。然后,您可以放大OpenGL,并在片段着色器中绘制图形时在GPU上进行Mandelbrot-> RGB转换。