comparison pytouhou/ui/renderer.pyx @ 423:d8630c086926

Replace Pyglet with our own Cython OpenGL wrapper.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 16 Jul 2013 21:07:15 +0200
parents 5fe6cd6ceb48
children 5d7bb2fd74f7
comparison
equal deleted inserted replaced
422:52829ebe2561 423:d8630c086926
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details. 12 ## GNU General Public License for more details.
13 ## 13 ##
14 14
15 from libc.stdlib cimport malloc, free, realloc 15 from libc.stdlib cimport malloc, free
16 from itertools import chain 16 from itertools import chain
17
18 import ctypes
19 17
20 from struct import pack 18 from struct import pack
21 19
22 from pyglet.gl import (glVertexPointer, glTexCoordPointer, glColorPointer, 20 from pytouhou.lib.opengl cimport \
23 glVertexAttribPointer, glEnableVertexAttribArray, 21 (glVertexPointer, glTexCoordPointer, glColorPointer,
24 glBlendFunc, glBindTexture, glDrawElements, 22 glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc,
25 glBindBuffer, glBufferData, GL_ARRAY_BUFFER, 23 glBindTexture, glDrawElements, glBindBuffer, glBufferData,
26 GL_DYNAMIC_DRAW, GL_STATIC_DRAW, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, 24 GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, GL_UNSIGNED_BYTE,
27 GL_INT, GL_FLOAT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 25 GL_UNSIGNED_SHORT, GL_INT, GL_FLOAT, GL_SRC_ALPHA,
28 GL_ONE, GL_TEXTURE_2D, GL_TRIANGLES, 26 GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_TEXTURE_2D, GL_TRIANGLES,
29 glEnable, glDisable, GL_DEPTH_TEST, glDrawArrays, GL_QUADS) 27 glGenBuffers)
30 28
31 from .sprite cimport get_sprite_rendering_data 29 from .sprite cimport get_sprite_rendering_data
32 from .texture cimport TextureManager 30 from .texture cimport TextureManager
33 31
34 32
37 35
38 cdef class Renderer: 36 cdef class Renderer:
39 def __cinit__(self): 37 def __cinit__(self):
40 # Allocate buffers 38 # Allocate buffers
41 self.vertex_buffer = <Vertex*> malloc(MAX_ELEMENTS * sizeof(Vertex)) 39 self.vertex_buffer = <Vertex*> malloc(MAX_ELEMENTS * sizeof(Vertex))
42 self.background_vertex_buffer = <VertexFloat*> malloc(65536 * sizeof(Vertex))
43 40
44 41
45 def __dealloc__(self): 42 def __dealloc__(self):
46 free(self.vertex_buffer) 43 free(self.vertex_buffer)
47 free(self.background_vertex_buffer)
48 44
49 45
50 def __init__(self, resource_loader): 46 def __init__(self, resource_loader):
51 self.texture_manager = TextureManager(resource_loader) 47 self.texture_manager = TextureManager(resource_loader)
52 48
49 if not self.use_fixed_pipeline:
50 glGenBuffers(1, &self.vbo)
51
53 52
54 cpdef render_elements(self, elements): 53 cpdef render_elements(self, elements):
55 cdef unsigned short nb_vertices = 0 54 cdef unsigned short nb_vertices = 0, nb_indices, *new_indices
56 55
57 indices_by_texture = {} 56 indices_by_texture = {}
58 57
59 objects = chain(*[element.objects for element in elements]) 58 objects = chain(*[element.objects for element in elements])
60 for element in objects: 59 for element in objects:
84 83
85 if nb_vertices == 0: 84 if nb_vertices == 0:
86 return 85 return
87 86
88 if self.use_fixed_pipeline: 87 if self.use_fixed_pipeline:
89 glVertexPointer(3, GL_INT, sizeof(Vertex), <long> &self.vertex_buffer[0].x) 88 glVertexPointer(3, GL_INT, sizeof(Vertex), &self.vertex_buffer[0].x)
90 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), <long> &self.vertex_buffer[0].u) 89 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u)
91 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), <long> &self.vertex_buffer[0].r) 90 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r)
92 else: 91 else:
93 glBindBuffer(GL_ARRAY_BUFFER, self.vbo) 92 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
94 glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), <long> &self.vertex_buffer[0], GL_DYNAMIC_DRAW) 93 glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_DYNAMIC_DRAW)
95 94
96 #TODO: find a way to use offsetof() instead of those ugly hardcoded values. 95 #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
97 glVertexAttribPointer(0, 3, GL_INT, False, sizeof(Vertex), 0) 96 glVertexAttribPointer(0, 3, GL_INT, False, sizeof(Vertex), <void*>0)
98 glEnableVertexAttribArray(0) 97 glEnableVertexAttribArray(0)
99 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), 12) 98 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>12)
100 glEnableVertexAttribArray(1) 99 glEnableVertexAttribArray(1)
101 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), 20) 100 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>20)
102 glEnableVertexAttribArray(2) 101 glEnableVertexAttribArray(2)
103 102
104 for (texture_key, blendfunc), indices in indices_by_texture.items(): 103 for (texture_key, blendfunc), indices in indices_by_texture.items():
104
105 #TODO: find a more elegent way.
105 nb_indices = len(indices) 106 nb_indices = len(indices)
106 indices = pack(str(nb_indices) + 'H', *indices) 107 new_indices = <unsigned short*> malloc(nb_indices * sizeof(unsigned short))
108 for i in xrange(nb_indices):
109 new_indices[i] = indices[i]
110
107 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) 111 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
108 glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key]) 112 glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key])
109 glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, indices) 113 glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, new_indices)
114 free(new_indices)
110 115
111 if not self.use_fixed_pipeline: 116 if not self.use_fixed_pipeline:
112 glBindBuffer(GL_ARRAY_BUFFER, 0) 117 glBindBuffer(GL_ARRAY_BUFFER, 0)
113
114
115 cpdef render_background(self):
116 if self.use_fixed_pipeline:
117 glVertexPointer(3, GL_FLOAT, sizeof(VertexFloat), <long> &self.background_vertex_buffer[0].x)
118 glTexCoordPointer(2, GL_FLOAT, sizeof(VertexFloat), <long> &self.background_vertex_buffer[0].u)
119 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexFloat), <long> &self.background_vertex_buffer[0].r)
120 else:
121 glBindBuffer(GL_ARRAY_BUFFER, self.back_vbo)
122
123 #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
124 glVertexAttribPointer(0, 3, GL_FLOAT, False, sizeof(VertexFloat), 0)
125 glEnableVertexAttribArray(0)
126 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(VertexFloat), 12)
127 glEnableVertexAttribArray(1)
128 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(VertexFloat), 20)
129 glEnableVertexAttribArray(2)
130
131 glEnable(GL_DEPTH_TEST)
132 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[self.blendfunc])
133 glBindTexture(GL_TEXTURE_2D, self.texture_manager[self.texture_key])
134 glDrawArrays(GL_QUADS, 0, self.nb_vertices)
135 glDisable(GL_DEPTH_TEST)
136
137 if not self.use_fixed_pipeline:
138 glBindBuffer(GL_ARRAY_BUFFER, 0)
139
140
141 cpdef prerender_background(self, background):
142 cdef float ox, oy, oz, ox2, oy2, oz2
143 cdef unsigned short nb_vertices = 0
144 cdef VertexFloat* vertex_buffer
145
146 vertex_buffer = self.background_vertex_buffer
147
148 for ox, oy, oz, model_id, model in background.object_instances:
149 for ox2, oy2, oz2, width_override, height_override, sprite in model:
150 #TODO: view frustum culling
151 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite)
152 (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices
153 left, right, bottom, top = uvs
154 r, g, b, a = colors
155
156 vertex_buffer[nb_vertices] = VertexFloat(x1 + ox + ox2, y1 + oy + oy2, z1 + oz + oz2, left, bottom, r, g, b, a)
157 vertex_buffer[nb_vertices+1] = VertexFloat(x2 + ox + ox2, y2 + oy + oy2, z2 + oz + oz2, right, bottom, r, g, b, a)
158 vertex_buffer[nb_vertices+2] = VertexFloat(x3 + ox + ox2, y3 + oy + oy2, z3 + oz + oz2, right, top, r, g, b, a)
159 vertex_buffer[nb_vertices+3] = VertexFloat(x4 + ox + ox2, y4 + oy + oy2, z4 + oz + oz2, left, top, r, g, b, a)
160
161 nb_vertices += 4
162
163 self.texture_key, self.blendfunc = key
164 self.nb_vertices = nb_vertices
165 self.background_vertex_buffer = <VertexFloat*> realloc(vertex_buffer, nb_vertices * sizeof(VertexFloat))
166
167 if not self.use_fixed_pipeline:
168 glBindBuffer(GL_ARRAY_BUFFER, self.back_vbo)
169 glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(VertexFloat), <long> &self.background_vertex_buffer[0], GL_STATIC_DRAW)
170 glBindBuffer(GL_ARRAY_BUFFER, 0)