2017-12-25 6 views
2

128 개의 입자를 렌더링하는 동안 프로그램이 느려지는 이유는 무엇입니까? 30fps 미만이면 충분하지 않다고 생각합니다.128 입자를 렌더링하는 동안 내 pyglet 프로그램이 느려지는 이유는 무엇입니까?

내가

on_draw 기능 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) 

입자 클래스 내가이기 때문에 GL_TRIANGLE_FAN 사용에 대한 지나치게 행복하지 않다

class Particle: 

    def __init__(self, **kwargs): 
     self.acceleration = Vector2(0, 0.05) 
     self.velocity = Vector2(random.uniform(-1, 1), random.uniform(-1, 0)) 
     self.position = Vector2() 
     self.time_to_live = 255 

     self.numpoints = 50 

     self._vertices = [] 

     for i in range(self.numpoints): 
      angle = math.radians(float(i)/self.numpoints * 360.0) 
      x = 10 * math.cos(angle) + self.velocity[0] + 300 
      y = 10 * math.sin(angle) + self.velocity[1] + 400 
      self._vertices += [x, y] 

    def update(self, time=None): 
     self.velocity += self.acceleration 
     self.position -= self.velocity 
     self.time_to_live -= 2 

    def draw(self): 
     glEnable(GL_BLEND) 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
     glPushMatrix() 
     glTranslatef(self.position[0], self.position[1], 0) 
     pyglet.graphics.draw(self.numpoints, GL_TRIANGLE_FAN, ('v2f', self._vertices), ('c4B', self.color)) 
     glPopMatrix() 

     self.update() 

    @property 
    def is_dead(self): 
     if self.time_to_live <= 0: 
      return True 
     return False 

    @property 
    def color(self): 
     return tuple(color for i in range(self.numpoints) for color in (255, 255, 255, self.time_to_live)) 
+2

몇 가지 : OpenGL의 종류가 잘못되었습니다. "modern OpenGL"을 검색하고 다시 시작하십시오. 현재 코드는 모든 종류의 기존 OpenGL 헛소리로 흩어져 있습니다. 'Particle' 인스턴스에서'draw'를 호출 할 때마다 GL 상태를 중복 갱신합니다. 블렌드 상태 - 외부 렌더링 루프로 그 물건을 꺼내십시오. 그 외에도 문제의 원인이 무엇인지는 분명하지 않지만 1995 년부터 GPU를 사용하지 않는 한 CPU가 완전히 바운드되었을 가능성이 큽니다 (몇 가지 색상 포인트는 GL 구현이나 GPU에 스트레스를주지 않습니다. 일). – thokra

답변

2

배치 렌더링을 사용할 때 이상한 모양이 많이 발생했습니다. 그러므로 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() 

베어를 염두에두고, 내 엔비디아 1070에 난 상관하지 않습니다이 코드에서 약 35fps를 얻을 수 있었다 취주. 그러나 그것은 1000 개체 * 쪽, 줄 또는 줄입니다. 내가 변경 한 무엇

은 기본적으로 이것이다 :

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

와 무승부 루프에서

, 당신은 할 수 있습니다 : 대신 각 입자 개체에 대한 Particle.draw()를 호출

self.batch.draw() 

.
그래픽 카드에 객체별로 무엇을 렌더링할지 알려주지 않고 모든 객체를 하나의 거대한 배치로 그래픽 카드에 보냅니다.

@thokra가 지적했듯이 코드는 GPU 집약보다 CPU 집약적입니다.
바라건대이 방법으로 해결할 수 있습니다. 주로

내가 모든 코드를 가지고 있지 않았기 때문에이 코드의 대부분

내가 잠시 뒤로 나의 좋은 친구와 함께했던 LAN 프로젝트에서 복용 메인 루프. 나는 당신의 문제를 내 자신의 코드에 적용하고 그것을 약간 조정함으로써 "해결했다". 다시 말하지만, 필요할 경우 github 프로젝트의 아이디어를 도우려는 것입니다. 새해 복 많이 받으세요!

+0

아, 입자 위치를 업데이트해야하는 경우 'self.particles [index] .vertices'의 각 좌표를 변경하면됩니다. 거기에서 업데이트하면 위치가 실시간으로 업데이트됩니다. – Torxed

+1

그것은 훌륭합니다! OpenGL을 좀 더 자세히 이해해야합니다. 감사합니다. 그리고 새해 복 많이 받으세요! –

관련 문제