Mercurial > touhou
comparison pytouhou/ui/renderer.pyx @ 505:bfea9e9a6845
Manage the texture-specific indices in the Texture, and some more renderer optimisations.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 01 Nov 2013 14:45:53 +0100 |
parents | c622eaf64428 |
children |
comparison
equal
deleted
inserted
replaced
504:69c73023f7a0 | 505:bfea9e9a6845 |
---|---|
29 glFramebufferTexture2D, glFramebufferRenderbuffer, | 29 glFramebufferTexture2D, glFramebufferRenderbuffer, |
30 glCheckFramebufferStatus, GL_FRAMEBUFFER, GL_TEXTURE_MIN_FILTER, | 30 glCheckFramebufferStatus, GL_FRAMEBUFFER, GL_TEXTURE_MIN_FILTER, |
31 GL_LINEAR, GL_TEXTURE_MAG_FILTER, GL_RGBA, GL_RENDERBUFFER, | 31 GL_LINEAR, GL_TEXTURE_MAG_FILTER, GL_RGBA, GL_RENDERBUFFER, |
32 GL_DEPTH_COMPONENT, GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, | 32 GL_DEPTH_COMPONENT, GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, |
33 GL_FRAMEBUFFER_COMPLETE, glClear, GL_COLOR_BUFFER_BIT, | 33 GL_FRAMEBUFFER_COMPLETE, glClear, GL_COLOR_BUFFER_BIT, |
34 GL_DEPTH_BUFFER_BIT) | 34 GL_DEPTH_BUFFER_BIT, GLuint, glDeleteTextures) |
35 | 35 |
36 from pytouhou.lib.sdl import SDLError | 36 from pytouhou.lib.sdl import SDLError |
37 | 37 |
38 from pytouhou.game.element cimport Element | 38 from pytouhou.game.element cimport Element |
39 from .sprite cimport get_sprite_rendering_data | 39 from .sprite cimport get_sprite_rendering_data |
40 from .texture import TextureManager, FontManager | |
41 | 40 |
42 from pytouhou.utils.helpers import get_logger | 41 from pytouhou.utils.helpers import get_logger |
43 | 42 |
44 logger = get_logger(__name__) | 43 logger = get_logger(__name__) |
45 | 44 |
46 | 45 |
47 DEF MAX_ELEMENTS = 640*4*3 | 46 cdef class Texture: |
47 def __cinit__(self, GLuint texture, Renderer renderer): | |
48 self.texture = texture | |
49 for i in xrange(2): | |
50 renderer.indices[texture][i] = self.indices[i] | |
51 | |
52 def __dealloc__(self): | |
53 glDeleteTextures(1, &self.texture) | |
48 | 54 |
49 | 55 |
50 cdef long find_objects(Renderer self, object elements) except -1: | 56 cdef long find_objects(Renderer self, object elements) except -1: |
51 # Don’t type element as Element, or else the overriding of objects won’t work. | 57 # Don’t type element as Element, or else the overriding of objects won’t work. |
52 cdef Element obj | 58 cdef Element obj |
62 return i | 68 return i |
63 return i | 69 return i |
64 | 70 |
65 | 71 |
66 cdef class Renderer: | 72 cdef class Renderer: |
67 def __cinit__(self): | |
68 self.vertex_buffer = <Vertex*> malloc(MAX_ELEMENTS * sizeof(Vertex)) | |
69 | |
70 | |
71 def __dealloc__(self): | 73 def __dealloc__(self): |
72 free(self.vertex_buffer) | |
73 | |
74 if not self.use_fixed_pipeline: | 74 if not self.use_fixed_pipeline: |
75 glDeleteBuffers(1, &self.framebuffer_vbo) | 75 glDeleteBuffers(1, &self.framebuffer_vbo) |
76 glDeleteBuffers(1, &self.vbo) | 76 glDeleteBuffers(1, &self.vbo) |
77 | 77 |
78 | 78 |
79 def __init__(self, resource_loader): | 79 def __init__(self, resource_loader): |
80 self.texture_manager = TextureManager(resource_loader, self) | 80 self.texture_manager = TextureManager(resource_loader, self, Texture) |
81 font_name = join(resource_loader.game_dir, 'font.ttf') | 81 font_name = join(resource_loader.game_dir, 'font.ttf') |
82 try: | 82 try: |
83 self.font_manager = FontManager(font_name, 16, self) | 83 self.font_manager = FontManager(font_name, 16, self, Texture) |
84 except SDLError: | 84 except SDLError: |
85 self.font_manager = None | 85 self.font_manager = None |
86 logger.error('Font file “%s” not found, disabling text rendering altogether.', font_name) | 86 logger.error('Font file “%s” not found, disabling text rendering altogether.', font_name) |
87 | 87 |
88 if not self.use_fixed_pipeline: | 88 if not self.use_fixed_pipeline: |
89 glGenBuffers(1, &self.vbo) | 89 glGenBuffers(1, &self.vbo) |
90 glGenBuffers(1, &self.framebuffer_vbo) | 90 glGenBuffers(1, &self.framebuffer_vbo) |
91 | |
92 | |
93 def add_texture(self, int texture): | |
94 for i in xrange(2): | |
95 self.indices[i][texture] = <unsigned short*> malloc(65536 * sizeof(unsigned short)) | |
96 | |
97 | |
98 def remove_texture(self, int texture): | |
99 for i in xrange(2): | |
100 free(self.indices[i][texture]) | |
101 | 91 |
102 | 92 |
103 cdef void render_elements(self, elements): | 93 cdef void render_elements(self, elements): |
104 cdef int key | 94 cdef int key |
105 cdef int x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, ox, oy | 95 cdef int x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, ox, oy |
106 cdef float left, right, bottom, top | 96 cdef float left, right, bottom, top |
107 cdef unsigned char r, g, b, a | 97 cdef unsigned char r, g, b, a |
108 | 98 |
99 nb_elements = find_objects(self, elements) | |
100 if not nb_elements: | |
101 return | |
102 | |
109 nb_vertices = 0 | 103 nb_vertices = 0 |
110 memset(self.last_indices, 0, sizeof(self.last_indices)) | 104 memset(self.last_indices, 0, sizeof(self.last_indices)) |
111 | 105 |
112 nb_elements = find_objects(self, elements) | |
113 for element_idx in xrange(nb_elements): | 106 for element_idx in xrange(nb_elements): |
114 element = <object>self.elements[element_idx] | 107 element = <object>self.elements[element_idx] |
115 sprite = element.sprite | 108 sprite = element.sprite |
116 ox, oy = element.x, element.y | 109 ox, oy = element.x, element.y |
117 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) | 110 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) |
118 | 111 |
119 blendfunc = key // MAX_TEXTURES | 112 blendfunc = key & 1 |
120 texture = key % MAX_TEXTURES | 113 texture = key >> 1 |
121 | 114 |
122 rec = self.indices[blendfunc][texture] | 115 rec = self.indices[texture][blendfunc] |
123 next_indice = self.last_indices[key] | 116 next_indice = self.last_indices[key] |
124 | 117 |
125 # Pack data in buffer | 118 # Pack data in buffer |
126 x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4 = vertices | 119 x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4 = vertices |
127 left, right, bottom, top = uvs | 120 left, right, bottom, top = uvs |
140 rec[next_indice+5] = nb_vertices | 133 rec[next_indice+5] = nb_vertices |
141 self.last_indices[key] += 6 | 134 self.last_indices[key] += 6 |
142 | 135 |
143 nb_vertices += 4 | 136 nb_vertices += 4 |
144 | 137 |
145 if nb_vertices == 0: | |
146 return | |
147 | |
148 if self.use_fixed_pipeline: | 138 if self.use_fixed_pipeline: |
149 glVertexPointer(3, GL_INT, sizeof(Vertex), &self.vertex_buffer[0].x) | 139 glVertexPointer(3, GL_INT, sizeof(Vertex), &self.vertex_buffer[0].x) |
150 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u) | 140 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u) |
151 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r) | 141 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r) |
152 else: | 142 else: |
159 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>12) | 149 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>12) |
160 glEnableVertexAttribArray(1) | 150 glEnableVertexAttribArray(1) |
161 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>20) | 151 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>20) |
162 glEnableVertexAttribArray(2) | 152 glEnableVertexAttribArray(2) |
163 | 153 |
154 # Don’t change the state when it’s not needed. | |
155 previous_blendfunc = -1 | |
156 previous_texture = -1 | |
157 | |
164 for key in xrange(2 * MAX_TEXTURES): | 158 for key in xrange(2 * MAX_TEXTURES): |
165 nb_indices = self.last_indices[key] | 159 nb_indices = self.last_indices[key] |
166 if not nb_indices: | 160 if not nb_indices: |
167 continue | 161 continue |
168 | 162 |
169 blendfunc = key // MAX_TEXTURES | 163 blendfunc = key & 1 |
170 texture = key % MAX_TEXTURES | 164 texture = key >> 1 |
171 | 165 |
172 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) | 166 if blendfunc != previous_blendfunc: |
173 glBindTexture(GL_TEXTURE_2D, texture) | 167 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) |
174 glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, self.indices[blendfunc][texture]) | 168 if texture != previous_texture: |
169 glBindTexture(GL_TEXTURE_2D, texture) | |
170 glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, self.indices[texture][blendfunc]) | |
171 | |
172 previous_blendfunc = blendfunc | |
173 previous_texture = texture | |
174 | |
175 glBindTexture(GL_TEXTURE_2D, 0) | |
175 | 176 |
176 if not self.use_fixed_pipeline: | 177 if not self.use_fixed_pipeline: |
177 glBindBuffer(GL_ARRAY_BUFFER, 0) | 178 glBindBuffer(GL_ARRAY_BUFFER, 0) |
178 | 179 |
179 | 180 |
180 cdef void render_quads(self, rects, colors, texture): | 181 cdef void render_quads(self, rects, colors, GLuint texture): |
181 # There is nothing that batch more than two quads on the same texture, currently. | 182 # There is nothing that batch more than two quads on the same texture, currently. |
182 cdef Vertex buf[8] | 183 cdef Vertex buf[8] |
183 cdef unsigned short indices[12] | 184 cdef unsigned short indices[12] |
184 indices[:] = [0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4] | 185 indices[:] = [0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4] |
185 | 186 |