使用Python优化数百万点渲染

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

我正在尝试使用 pygame 和(也许)openGL 在 2D 中显示一百万个点。

问题是,我的代码尚未优化以使其以高帧速率运行,即使我有一个非常好的 GPU。

这是我使用的第一种方法,它以大约 2 FPS 的速度运行 100 万个点,这还不错,但我希望它至少为 60 FPS :

for i in range(len(positions)): 
        pygame.draw.circle(screen, white, positions[i], circle_radius)

这是第二种方法,使用 OpenGL,效果更差(1 FPS):

for i in range(len(positions)): 
        glVertex2f(positions[i][0], positions[i][1])

我认为 OpenGL 会比 pygame 更优化,但事实似乎并非如此。

显示这些点的更好方式是什么?这是一个库问题还是我可以使用 OpenGL 以更好的方式做到这一点?

python optimization opengl pygame 2d
1个回答
0
投票

我并不是真正的 OpenGL 专家,因此应谨慎使用此代码。 当需要频繁更改点时,此代码可能不合适。

在我的机器上,使用 iGPU 时它已经以大约 120FPS 的速度运行。

import pygame
from OpenGL.GL import *
import random

# Initialize Pygame
pygame.init()

# Initialize the pygame screen
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.OPENGL | pygame.DOUBLEBUF)

# setup extra stuff
font = pygame.font.Font(None, 30)
clock = pygame.time.Clock()

# setup open gl
glClearColor(0.0, 0.0, 0.0, 1.0)  # clear with black
glViewport(0, 0, WIDTH, HEIGHT)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, WIDTH, HEIGHT, 0, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()


def draw_text(x_pos, y_pos, text):
    # based on https://stackoverflow.com/a/67639147/7380827
    text_surface = font.render(text, True, (255, 255, 66, 255), (0, 66, 0, 255))
    text_data = pygame.image.tostring(text_surface, "RGBA", True)
    glWindowPos2d(x_pos, y_pos)
    glDrawPixels(text_surface.get_width(), text_surface.get_height(), GL_RGBA, GL_UNSIGNED_BYTE, text_data)


def main():
    # Generate random points
    num_points = 1_000_000
    points = [(random.randint(0, WIDTH), random.randint(0, HEIGHT)) for _ in range(num_points)]

    # Flatten the point data
    flattened_points = [p for point in points for p in point]

    # Create a VBO
    vbo = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, vbo)  # bind
    glBufferData(GL_ARRAY_BUFFER, len(flattened_points) * 4,
                 (ctypes.c_float * len(flattened_points))(*flattened_points), GL_STATIC_DRAW)
    glBindBuffer(GL_ARRAY_BUFFER, 0)  # unbind

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        glClear(GL_COLOR_BUFFER_BIT)
        # Bind the VBO and draw points using OpenGL
        glPointSize(1.1)  # set the size of the points here
        glBindBuffer(GL_ARRAY_BUFFER, vbo)  # bind
        glEnableClientState(GL_VERTEX_ARRAY)
        glVertexPointer(2, GL_FLOAT, 0, None)
        glColor3f(1.0, 0.0, 0.0)  # point color
        glDrawArrays(GL_POINTS, 0, len(points))
        glDisableClientState(GL_VERTEX_ARRAY)
        glBindBuffer(GL_ARRAY_BUFFER, 0)  # unbind

        draw_text(0, 0, 'FPS: {}'.format(int(clock.get_fps())))
        pygame.display.flip()
        clock.tick()

    pygame.quit()


if __name__ == "__main__":
    main()
© www.soinside.com 2019 - 2024. All rights reserved.