问题描述
我正在用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转换。