首页 > 解决方案 > 优化 pyglet 脚本可以渲染更多对象

问题描述

我构建了一个简单的脚本来将像素渲染到屏幕上。脚本所做的只是随机获取 0 和 1 的 4 个字符串(这 4 个字符构成一个对象),然后将对象作为像素重复绘制在屏幕上。

import random
from pyglet.gl import *
from pyglet import clock
from pyglet.window import key


W = 1280
H = 720
NUM_OBJECTS = 200
CELL_SIZE = 4
BACKGROUND_COLOR = [1.0, 1.0, 1.0, 1.0]
OBJECT_COLOR = [241, 148, 138]


class GameWindow(pyglet.window.Window):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        glClearColor(*BACKGROUND_COLOR)

        self.positions = []
        self.render_objects = []
        self.main_batch = None
        self.init_objects()

    def init_objects(self):
        self.main_batch = pyglet.graphics.Batch()
        self.render_objects = [''.join(random.choice("01") for _ in range(4)) for _ in range(4)]
        self.positions = []

        # Init positions
        current_x = 1
        current_y = 1
        for i in range(NUM_OBJECTS):
            if current_x * CELL_SIZE >= W - 4*CELL_SIZE:
                current_x = 1
                current_y += CELL_SIZE + 1

            self.positions.append((current_x, current_y))
            current_x += CELL_SIZE + 1

    def draw_object(self, position):

        row_count = position[0]
        for row in self.render_objects:
            col_count = position[1]
            for i in row:
                st_x = row_count * CELL_SIZE
                st_y = col_count * CELL_SIZE
                nd_x = st_x + CELL_SIZE
                nd_y = st_y + CELL_SIZE
                self.draw_pixel(st_x, st_y, nd_x, nd_y,
                                int(i) == 1)
                col_count += 1
            row_count += 1

    def on_draw(self):
        self.clear()
        self.main_batch.draw()
        print(clock.get_fps())

    def reset(self):
        self.init_objects()

    def draw_pixel(self, x, y, x1, y1, is_draw, color=None):
        if not is_draw:
            return

        self.main_batch.add(4, pyglet.gl.GL_QUADS, None,
                            ('v2f', [x, y, x1, y, x1, y1, x, y1]),
                            ('c3B', (OBJECT_COLOR if color is None else color) * 4))

    def update(self, dt):
        [self.draw_object(p)
         for p in self.positions]

    def on_key_press(self, symbol, modifiers):
        if symbol == key.R: self.reset()

    def on_mouse_press(self, x, y, button, modifiers):
        pass


if __name__ == "__main__":
    game = GameWindow(W, H)
    pyglet.clock.schedule_interval(game.update, 1 / 60)
    pyglet.app.run()

在上面的脚本中,NUM_OBJECTS每帧(批量)渲染了200 个对象(变量update名为未来我希望能够每帧更改所有这些对象的位置。

opengl我的目标是能够在屏幕上渲染更多对象(比如 1k-2k 个对象),而且我很确定我在 wrt或 wrt脚本中做错了什么pyglet。还有一种方法可以将opengl绘图保存在对象中,然后每帧将其添加到批处理中吗?

标签: pythonopenglpyglet

解决方案


在您的代码中,您不断地在每一帧添加顶点,这就是它降低性能的原因。

draw_pixel 顶点添加到批处理中,每帧都在执行此操作。

您需要做的是将对象创建与更新分开。batch.add 返回一个可以更新的顶点列表。

每个对象只执行一次并将其存储在某处:vertex_list = batch.add(..)

然后更新你要做的顶点的位置。 vertex_list.vertices[:] = new_list_of_vertices


推荐阅读