为什么我的pyglet程序在渲染128个粒子时速度很慢?

2024-04-19 05:51:33 发布

您现在位置:Python中文网/ 问答频道 /正文

为什么我的程序在渲染128个粒子时速度慢?我认为这不足以达到每秒30帧。在

我所做的就是渲染128个粒子并给它们一些基本的引力

论绘制函数

 def on_draw(self, time=None):
    glClearColor(0.0, 0.0, 0.0, 1.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()

    self.particles.append(Particle())
    for particle in self.particles:
        particle.draw()

        if particle.is_dead:
            self.particles.remove(particle)

粒子类别

^{pr2}$

Tags: 函数self程序ondefbuffer引力bit
1条回答
网友
1楼 · 发布于 2024-04-19 05:51:33

我对使用GL_TRIANGLE_FAN不太满意,因为它在使用批处理渲染时会产生很多奇怪的形状。所以考虑转移到GL_TRIANGLES,只需将所有点添加到对象中,而不是依靠GL来关闭形状。在

这样,您就可以轻松地转到进行批处理渲染:

import pyglet
from pyglet.gl import *
from collections import OrderedDict
from time import time, sleep
from math import *
from random import randint

key = pyglet.window.key

class CustomGroup(pyglet.graphics.Group):
    def set_state(self):
        #pyglet.gl.glLineWidth(5)
        #glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
        #glColor4f(1, 0, 0, 1) #FFFFFF
        #glLineWidth(1)
        #glEnable(texture.target)
        #glBindTexture(texture.target, texture.id)
        pass

    def unset_state(self):
        glLineWidth(1)
        #glDisable(texture.target)

class Particle():
    def __init__(self, x, y, batch, particles):
        self.batch = batch
        self.particles = particles
        self.group = CustomGroup()

        self.add_point(x, y)

    def add_point(self, x, y):

        colors = ()#255,0,0

        sides = 50
        radius = 25

        deg = 360/sides
        points = ()#x, y # Starting point is x, y?

        prev = None
        for i in range(sides):

            n = ((deg*i)/180)*pi # Convert degrees to radians
            point = int(radius * cos(n)) + x, int(radius * sin(n)) + y

            if prev:
                points += x, y
                points += prev
                points += point
                colors += (255, i*int(255/sides), 0)*3 # Add a color pair for each point (r,g,b) * points[3 points added]

            prev = point

        points += x, y
        points += prev
        points += points[2:4]
        colors += (255, 0, 255)*3

        self.particles[len(self.particles)] = self.batch.add(int(len(points)/2), pyglet.gl.GL_TRIANGLES, self.group, ('v2i/stream', points), ('c3B', colors))

class main(pyglet.window.Window):
    def __init__ (self, demo=False):
        super(main, self).__init__(800, 600, fullscreen = False, vsync = True)
        #print(self.context.config.sample_buffers)
        self.x, self.y = 0, 0

        self.sprites = OrderedDict()
        self.batches = OrderedDict()
        self.batches['default'] = pyglet.graphics.Batch()
        self.active_batch = 'default'

        for i in range(1000):
            self.sprites[len(self.sprites)] = Particle(randint(0, 800), randint(0, 600), self.batches[self.active_batch], self.sprites)

        self.alive = True

        self.fps = 0
        self.last_fps = time()
        self.fps_label = pyglet.text.Label(str(self.fps) + ' fps', font_size=12, x=3, y=self.height-15)

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0

    def render(self):
        self.clear()
        #self.bg.draw()

        self.batches[self.active_batch].draw()

        self.fps += 1
        if time()-self.last_fps > 1:
            self.fps_label.text = str(self.fps) + ' fps'
            self.fps = 0
            self.last_fps = time()

        self.fps_label.draw()
        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            #      -> This is key <     
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

if __name__ == '__main__':
    x = main(demo=True)
    x.run()

简单地说,在我的nvidia1070上,我成功地从这段代码中获得了大约35fps的速度,这并不令人兴奋。但它是1000个物体*边,给或取。在

我改变的本质是:

^{pr2}$

在绘制循环中,将执行以下操作:

self.batch.draw()

而不是为每个粒子对象调用Particle.draw()
这样做的是,它会将所有对象在一个巨大的批处理中发送到图形卡,而不是告诉显卡要逐个对象渲染什么。在

正如@thokra所指出的,您的代码比GPU更需要CPU。
希望这能修复它或者给你一些提示。在

这段代码大部分来自我和我的一个好朋友不久前做的一个局域网项目:

因为我没有你所有的代码,主要是主循环。我将您的问题应用到我自己的代码中,并通过稍微调整来“解决”它。再次,如果需要的话,希望它能帮助你,从github项目中窃取想法。新年快乐!在

相关问题 更多 >