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