comparison pytouhou/opengl/gamerenderer.py @ 125:0313ca2c50e9

Small refactoring and massive performance improvements
author Thibaut Girka <thib@sitedethib.com>
date Sat, 10 Sep 2011 15:04:47 +0200
parents d1c82d43bbf3
children 9d7129ee2c4f
comparison
equal deleted inserted replaced
124:f06e96dbed4e 125:0313ca2c50e9
12 ## GNU General Public License for more details. 12 ## GNU General Public License for more details.
13 ## 13 ##
14 14
15 import struct 15 import struct
16 from itertools import chain 16 from itertools import chain
17 import ctypes
17 18
18 import pyglet 19 import pyglet
19 from pyglet.gl import * 20 from pyglet.gl import *
20 21
21 from pytouhou.opengl.texture import TextureManager 22 from pytouhou.opengl.texture import TextureManager
22 from pytouhou.opengl.sprite import get_sprite_rendering_data 23 from pytouhou.opengl.sprite import get_sprite_rendering_data
23 from pytouhou.opengl.background import get_background_rendering_data 24 from pytouhou.opengl.background import get_background_rendering_data
25
26
27 MAX_ELEMENTS = 10000
24 28
25 29
26 class GameRenderer(pyglet.window.Window): 30 class GameRenderer(pyglet.window.Window):
27 def __init__(self, resource_loader, game=None, background=None): 31 def __init__(self, resource_loader, game=None, background=None):
28 pyglet.window.Window.__init__(self, caption='PyTouhou', resizable=False) 32 pyglet.window.Window.__init__(self, caption='PyTouhou', resizable=False)
53 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) 57 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
54 glEnableClientState(GL_COLOR_ARRAY) 58 glEnableClientState(GL_COLOR_ARRAY)
55 glEnableClientState(GL_VERTEX_ARRAY) 59 glEnableClientState(GL_VERTEX_ARRAY)
56 glEnableClientState(GL_TEXTURE_COORD_ARRAY) 60 glEnableClientState(GL_TEXTURE_COORD_ARRAY)
57 61
58 pyglet.clock.schedule_interval(self.update, 1./120) 62 # Allocate buffers
63 buff = ctypes.c_buffer(MAX_ELEMENTS * 4 * (3 * 4 + 2 * 4 + 4))
64 self.buffers = (buff,
65 ctypes.byref(buff, 3 * 4),
66 ctypes.byref(buff, 3 * 4 + 2 * 4))
67
68 pyglet.clock.schedule_interval(self.update, 1./120.)
59 pyglet.app.run() 69 pyglet.app.run()
60 70
61 71
62 def on_resize(self, width, height): 72 def on_resize(self, width, height):
63 glViewport(0, 0, width, height) 73 glViewport(0, 0, width, height)
78 self.set_fullscreen(not self.fullscreen) 88 self.set_fullscreen(not self.fullscreen)
79 89
80 90
81 def render_elements(self, elements): 91 def render_elements(self, elements):
82 texture_manager = self.texture_manager 92 texture_manager = self.texture_manager
83 objects_by_texture = {} 93
94 pack_data = struct.Struct('fff ff BBBB' * 4).pack_into
95 _vertices, _uvs, _colors = self.buffers
96
97 nb_vertices = 0
98 indices_by_texture = {}
99
84 for element in elements: 100 for element in elements:
85 sprite = element._sprite 101 sprite = element._sprite
86 if sprite: 102 if sprite:
87 ox, oy = element.x, element.y 103 ox, oy = element.x, element.y
88 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) 104 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite)
89 rec = objects_by_texture.setdefault(key, ([], [], [])) 105 rec = indices_by_texture.setdefault(key, [0, []])
90 vertices = ((x + ox, y + oy, z) for x, y, z in vertices) 106 index = rec[0]
91 rec[0].extend(vertices) 107
92 rec[1].extend(uvs) 108 # Pack data in buffer
93 rec[2].extend(colors) 109 (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices
94 110 r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3, r4, g4, b4, a4 = colors
95 for (texture_key, blendfunc), (vertices, uvs, colors) in objects_by_texture.items(): 111 u1, v1, u2, v2, u3, v3, u4, v4 = uvs
96 nb_vertices = len(vertices) 112 pack_data(_vertices, nb_vertices * (3 * 4 + 2 * 4 + 4),
97 vertices = struct.pack(str(3 * nb_vertices) + 'f', *chain(*vertices)) 113 x1 + ox, y1 + oy, z1,
98 uvs = struct.pack(str(2 * nb_vertices) + 'f', *chain(*uvs)) 114 u1, v1,
99 colors = struct.pack(str(4 * nb_vertices) + 'B', *chain(*colors)) 115 r1, g1, b1, a1,
116
117 x2 + ox, y2 + oy, z2,
118 u2, v2,
119 r2, g2, b2, a2,
120
121 x3 + ox, y3 + oy, z3,
122 u3, v3,
123 r3, g3, b3, a3,
124
125 x4 + ox, y4 + oy, z4,
126 u4, v4,
127 r4, g4, b4, a4)
128
129 # Add indices
130 rec[0] += 4
131 rec[1].extend((index, index + 1, index + 2, index + 3))
132
133 nb_vertices += 4
134
135 glVertexPointer(3, GL_FLOAT, 24, _vertices)
136 glTexCoordPointer(2, GL_FLOAT, 24, _uvs)
137 glColorPointer(4, GL_UNSIGNED_BYTE, 24, _colors)
138
139 for (texture_key, blendfunc), (nb_indices, indices) in indices_by_texture.items():
140 indices = struct.pack(str(nb_indices) + 'H', *indices)
100 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) 141 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
101 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key].id) 142 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key].id)
102 glVertexPointer(3, GL_FLOAT, 0, vertices) 143 glDrawElements(GL_QUADS, nb_indices, GL_UNSIGNED_SHORT, indices)
103 glTexCoordPointer(2, GL_FLOAT, 0, uvs)
104 glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors)
105 glDrawArrays(GL_QUADS, 0, nb_vertices)
106 144
107 145
108 def on_draw(self): 146 def on_draw(self):
109 glClear(GL_DEPTH_BUFFER_BIT) 147 glClear(GL_DEPTH_BUFFER_BIT)
110 148