沙子模拟在 Pyglet 中渲染缓慢

问题描述 投票:0回答:1

我正在关注 The Coding Train 的最新编码挑战。在他的视频中,他使用 p5.js 构建了一个落沙模拟器,我决定使用 pyglet 尝试挑战。

我做了一些测试,但我注意到与his相比,我的程序渲染速度非常慢。我知道我在每一帧都重新绘制网格,但我的代码逻辑与编码火车的逻辑类似,并且他没有遇到同样的问题。

我确信有更好的方法来处理沙子掉落,但由于我刚刚开始学习 pyglet,我不知道如何继续。

这是代码:

import random
import math
# pyglet libraries
import pyglet
from pyglet import shapes
from pyglet.window import mouse

SCREEN_WIDTH = 400
SCREEN_HEIGHT = 400
SAND_SIZE = 10

def make2DArray(rows, cols):
    arr = [[0 for y in range(cols)] for x in range(rows)]
    for row in range(rows):
        for col in range(cols):
            arr[row][col] = 0
    return arr


window = pyglet.window.Window(SCREEN_WIDTH, SCREEN_HEIGHT)

rows = int(SCREEN_WIDTH / SAND_SIZE)
cols = int(SCREEN_HEIGHT / SAND_SIZE)
grid = make2DArray(rows, cols)
grid[30][20] = 1


@window.event
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
    row = math.floor(x / SAND_SIZE)
    col = math.floor(y / SAND_SIZE)
    grid[row][col] = 1


@window.event
def on_draw():
    global grid

    for row in range(rows):
        for col in range(cols):
            if grid[row][col] == 0:
                rectangle = shapes.Rectangle(row*10, col*10, 10, 10, color=(0, 0, 0))
            else:
                rectangle = shapes.Rectangle(row*10, col*10, 10, 10, color=(255, 255, 255))
            rectangle.draw()
    # Generating New State
    next_state_grid = make2DArray(rows, cols)
    for row in range(rows):
        for col in range(cols):
            current_state = grid[row][col]
            if current_state == 1:
                below = grid[row][col - 1]
                if below == 0 and col != 0:
                    next_state_grid[row][col - 1] = 1
                else:
                    next_state_grid[row][col] = 1
    grid = next_state_grid


pyglet.app.run()

python pyglet
1个回答
2
投票

Pyglet 使用硬件加速(OpenGL)来绘制图像。当您调用

rectangle.draw()
时,您正在对 GPU 进行绘制调用,速度非常慢。您应该尽可能减少绘制调用,因为 CPU 和 GPU 之间的通信通常需要时间。

文档

明确劝阻您不要使用此函数,而是建议使用batches 批次将收集您想要绘制的所有内容,然后优化绘制调用的数量。这是文档中的示例,其中他们将所有形状添加到

batch

并使用 batch.draw():

import pyglet
from pyglet import shapes

window = pyglet.window.Window(960, 540)
batch = pyglet.graphics.Batch()

circle = shapes.Circle(700, 150, 100, color=(50, 225, 30), batch=batch)
square = shapes.Rectangle(200, 200, 200, 200, color=(55, 55, 255), batch=batch)
rectangle = shapes.Rectangle(250, 300, 400, 200, color=(255, 22, 20), batch=batch)
rectangle.opacity = 128
rectangle.rotation = 33
line = shapes.Line(100, 100, 100, 200, width=19, batch=batch)
line2 = shapes.Line(150, 150, 444, 111, width=4, color=(200, 20, 20), batch=batch)
star = shapes.Star(800, 400, 60, 40, num_spikes=20, color=(255, 255, 0), batch=batch)

@window.event
def on_draw():
    window.clear()
    batch.draw()

pyglet.app.run()

© www.soinside.com 2019 - 2024. All rights reserved.