有没有更快的方法使用 pyglet 和线程在屏幕上绘图?
Is there a faster way to draw on screen using pyglet and threading?
下面的三个函数展示了我如何使用 pyglet 库在屏幕上绘制正方形。该代码工作正常。但我想让它 运行 更快。
以我对线程的新手理解,我认为 draw_grid()
中的 for 循环可以通过使用线程变得更快,因为它等待使用 pos
绘制一个正方形,然后绘制一个新广场。既然已经提供了all_positions
,有没有办法同时画出所有的方块呢?
def draw_square(single_location):
# draws a single square
pyglet.graphics.draw_indexed(4, pyglet.graphics.gl.GL_TRIANGLES,
[0,1,2,1,2,3],
('v2i', single_location))
def position_array():
# returns an 2D array with each row representing the coordinates of the rectangle to draw
...relevant code...
return all_positions
def draw_grid(all_positions):
# uses draw_square function and all_positions to draw multiple squares at the specified locations.
for pos in all_positions:
draw_square(pos)
在查看了一些关于线程的视频后,我找到了 concurrent.futures
库。所以我试图实现它,但它给了我错误。所以现在我卡住了。
这是我在 draw_grid()
中使用 concurrent.futures.ThreadPoolExecutor()
的方式
def draw_grid(all_positions):
# uses draw_square function and all_positions to draw multiple squares at the specified locations.
with concurrent.futures.ThreadPoolExecutor as executor:
for pos in all_positions:
f1 = executor.submit(draw_square, pos)
f1.result()
作为一般规则,永远不要混合线程和图形渲染。它是灾难的接收者。可以结合渲染 (GL) 使用线程。但同样,不推荐。
相反,您可能想要查看的是批处理渲染。
documentation on Batched rendering 很棒,您可能会发现它很容易理解。
请记住,如果要在将顶点添加到面片后对其进行修改,则需要存储它们并从批处理中修改 return,不要尝试直接操作批处理。
vertex_list = batch.add(2, pyglet.gl.GL_POINTS, None,
('v2i', (10, 15, 30, 35)),
('c3B', (0, 0, 255, 0, 255, 0))
)
# vertex_list.vertices <-- Modify here
您不想使用线程的原因是几乎有 99.9% 的保证您最终会因竞争条件而出现分段错误。当您渲染您试图操纵的东西时,某些东西试图更新屏幕。
更多信息在评论中:Update and On_Draw Pyglet in Thread
因此,改为将所有方块添加到一批中,然后执行 batch.draw()
,它会一次同时绘制所有方块。而不是浪费 CPU 循环调用函数并每次都重新创建正方形,然后一个一个地渲染它们。
batch = pyglet.graphics.Batch()
batch.add(2, pyglet.gl.GL_TRIANGLES, None,
('v2i', [0,1,2,1,2,3])
)
def on_draw():
batch.draw()
类似的东西。但很明显你想在不同的位置等创建正方形。但作为指导,在渲染逻辑之外创建批次和正方形,然后在渲染周期中对批次调用 .draw()
。
下面的三个函数展示了我如何使用 pyglet 库在屏幕上绘制正方形。该代码工作正常。但我想让它 运行 更快。
以我对线程的新手理解,我认为 draw_grid()
中的 for 循环可以通过使用线程变得更快,因为它等待使用 pos
绘制一个正方形,然后绘制一个新广场。既然已经提供了all_positions
,有没有办法同时画出所有的方块呢?
def draw_square(single_location):
# draws a single square
pyglet.graphics.draw_indexed(4, pyglet.graphics.gl.GL_TRIANGLES,
[0,1,2,1,2,3],
('v2i', single_location))
def position_array():
# returns an 2D array with each row representing the coordinates of the rectangle to draw
...relevant code...
return all_positions
def draw_grid(all_positions):
# uses draw_square function and all_positions to draw multiple squares at the specified locations.
for pos in all_positions:
draw_square(pos)
在查看了一些关于线程的视频后,我找到了 concurrent.futures
库。所以我试图实现它,但它给了我错误。所以现在我卡住了。
这是我在 draw_grid()
concurrent.futures.ThreadPoolExecutor()
的方式
def draw_grid(all_positions):
# uses draw_square function and all_positions to draw multiple squares at the specified locations.
with concurrent.futures.ThreadPoolExecutor as executor:
for pos in all_positions:
f1 = executor.submit(draw_square, pos)
f1.result()
作为一般规则,永远不要混合线程和图形渲染。它是灾难的接收者。可以结合渲染 (GL) 使用线程。但同样,不推荐。
相反,您可能想要查看的是批处理渲染。
documentation on Batched rendering 很棒,您可能会发现它很容易理解。
请记住,如果要在将顶点添加到面片后对其进行修改,则需要存储它们并从批处理中修改 return,不要尝试直接操作批处理。
vertex_list = batch.add(2, pyglet.gl.GL_POINTS, None,
('v2i', (10, 15, 30, 35)),
('c3B', (0, 0, 255, 0, 255, 0))
)
# vertex_list.vertices <-- Modify here
您不想使用线程的原因是几乎有 99.9% 的保证您最终会因竞争条件而出现分段错误。当您渲染您试图操纵的东西时,某些东西试图更新屏幕。
更多信息在评论中:Update and On_Draw Pyglet in Thread
因此,改为将所有方块添加到一批中,然后执行 batch.draw()
,它会一次同时绘制所有方块。而不是浪费 CPU 循环调用函数并每次都重新创建正方形,然后一个一个地渲染它们。
batch = pyglet.graphics.Batch()
batch.add(2, pyglet.gl.GL_TRIANGLES, None,
('v2i', [0,1,2,1,2,3])
)
def on_draw():
batch.draw()
类似的东西。但很明显你想在不同的位置等创建正方形。但作为指导,在渲染逻辑之外创建批次和正方形,然后在渲染周期中对批次调用 .draw()
。