我正在尝试使用 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 以更好的方式做到这一点?
我并不是真正的 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()