Mercurial > touhou
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 |