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