comparison pytouhou/ui/opengl/renderer.pyx @ 558:94725968dabb

Use vertex array objects, to be compatible with OpenGL 3.1+ core profile.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 12 Dec 2013 13:47:17 +0100
parents d6d9a711253d
children 1be60813f7cb
comparison
equal deleted inserted replaced
557:0f2af7552462 558:94725968dabb
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, GLuint, glDeleteTextures, 34 GL_DEPTH_BUFFER_BIT, GLuint, glDeleteTextures,
35 GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) 35 GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, glGenVertexArrays,
36 glDeleteVertexArrays, glBindVertexArray)
36 37
37 from pytouhou.lib.sdl import SDLError 38 from pytouhou.lib.sdl import SDLError
38 39
39 from pytouhou.game.element cimport Element 40 from pytouhou.game.element cimport Element
40 from .sprite cimport get_sprite_rendering_data 41 from .sprite cimport get_sprite_rendering_data
42 from .backend cimport use_vao
41 43
42 from pytouhou.utils.helpers import get_logger 44 from pytouhou.utils.helpers import get_logger
43 45
44 logger = get_logger(__name__) 46 logger = get_logger(__name__)
45 47
93 def __dealloc__(self): 95 def __dealloc__(self):
94 if not self.use_fixed_pipeline: 96 if not self.use_fixed_pipeline:
95 glDeleteBuffers(1, &self.framebuffer_vbo) 97 glDeleteBuffers(1, &self.framebuffer_vbo)
96 glDeleteBuffers(1, &self.vbo) 98 glDeleteBuffers(1, &self.vbo)
97 99
100 if use_vao:
101 glDeleteVertexArrays(1, &self.vao)
102 glDeleteVertexArrays(1, &self.framebuffer_vao)
103
98 104
99 def __init__(self, resource_loader): 105 def __init__(self, resource_loader):
100 # Only used in modern GL. 106 # Only used in modern GL.
101 cdef unsigned short framebuffer_indices[6] 107 cdef unsigned short framebuffer_indices[6]
102 108
116 glGenBuffers(1, &self.framebuffer_ibo) 122 glGenBuffers(1, &self.framebuffer_ibo)
117 123
118 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo) 124 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
119 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(framebuffer_indices), framebuffer_indices, GL_STATIC_DRAW) 125 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(framebuffer_indices), framebuffer_indices, GL_STATIC_DRAW)
120 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 126 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
127
128 if use_vao:
129 glGenVertexArrays(1, &self.vao)
130 glBindVertexArray(self.vao)
131 self.set_state()
132
133 glGenVertexArrays(1, &self.framebuffer_vao)
134 glBindVertexArray(self.framebuffer_vao)
135 self.set_framebuffer_state()
136 glBindVertexArray(0)
137
138
139 cdef void set_state(self) nogil:
140 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
141
142 #TODO: find a way to use offsetof() instead of those ugly substractions.
143 glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0)
144 glEnableVertexAttribArray(0)
145 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8)
146 glEnableVertexAttribArray(1)
147 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
148 glEnableVertexAttribArray(2)
149
150 glBindBuffer(GL_ARRAY_BUFFER, 0)
151
152
153 cdef void set_framebuffer_state(self) nogil:
154 glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
155 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
156
157 #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
158 glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
159 glEnableVertexAttribArray(0)
160 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
161 glEnableVertexAttribArray(1)
162
163 glBindBuffer(GL_ARRAY_BUFFER, 0)
121 164
122 165
123 cdef void render_elements(self, elements): 166 cdef void render_elements(self, elements):
124 cdef Element element 167 cdef Element element
125 168
166 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u) 209 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u)
167 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r) 210 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r)
168 else: 211 else:
169 glBindBuffer(GL_ARRAY_BUFFER, self.vbo) 212 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
170 glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_DYNAMIC_DRAW) 213 glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_DYNAMIC_DRAW)
171 214 glBindBuffer(GL_ARRAY_BUFFER, 0)
172 #TODO: find a way to use offsetof() instead of those ugly hardcoded values. 215
173 glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0) 216 if use_vao:
174 glEnableVertexAttribArray(0) 217 glBindVertexArray(self.vao)
175 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8) 218 else:
176 glEnableVertexAttribArray(1) 219 self.set_state()
177 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
178 glEnableVertexAttribArray(2)
179 220
180 # Don’t change the state when it’s not needed. 221 # Don’t change the state when it’s not needed.
181 previous_blendfunc = -1 222 previous_blendfunc = -1
182 previous_texture = -1 223 previous_texture = -1
183 224
198 previous_blendfunc = blendfunc 239 previous_blendfunc = blendfunc
199 previous_texture = texture 240 previous_texture = texture
200 241
201 glBindTexture(GL_TEXTURE_2D, 0) 242 glBindTexture(GL_TEXTURE_2D, 0)
202 243
203 if not self.use_fixed_pipeline: 244 if not self.use_fixed_pipeline and use_vao:
204 glBindBuffer(GL_ARRAY_BUFFER, 0) 245 glBindVertexArray(0)
205 246
206 247
207 cdef void render_quads(self, rects, colors, GLuint texture): 248 cdef void render_quads(self, rects, colors, GLuint texture):
208 # There is nothing that batch more than two quads on the same texture, currently. 249 # There is nothing that batch more than two quads on the same texture, currently.
209 cdef Vertex buf[8] 250 cdef Vertex buf[8]
226 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &buf[0].u) 267 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &buf[0].u)
227 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &buf[0].r) 268 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &buf[0].r)
228 else: 269 else:
229 glBindBuffer(GL_ARRAY_BUFFER, self.vbo) 270 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
230 glBufferData(GL_ARRAY_BUFFER, 4 * length * sizeof(Vertex), buf, GL_DYNAMIC_DRAW) 271 glBufferData(GL_ARRAY_BUFFER, 4 * length * sizeof(Vertex), buf, GL_DYNAMIC_DRAW)
231 272 glBindBuffer(GL_ARRAY_BUFFER, 0)
232 #TODO: find a way to use offsetof() instead of those ugly hardcoded values. 273
233 glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0) 274 if use_vao:
234 glEnableVertexAttribArray(0) 275 glBindVertexArray(self.vao)
235 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8) 276 else:
236 glEnableVertexAttribArray(1) 277 self.set_state()
237 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
238 glEnableVertexAttribArray(2)
239 278
240 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 279 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
241 glBindTexture(GL_TEXTURE_2D, texture) 280 glBindTexture(GL_TEXTURE_2D, texture)
242 glDrawElements(GL_TRIANGLES, 6 * length, GL_UNSIGNED_SHORT, indices) 281 glDrawElements(GL_TRIANGLES, 6 * length, GL_UNSIGNED_SHORT, indices)
243
244 if not self.use_fixed_pipeline:
245 glBindBuffer(GL_ARRAY_BUFFER, 0)
246 282
247 283
248 cdef void render_framebuffer(self, Framebuffer fb): 284 cdef void render_framebuffer(self, Framebuffer fb):
249 cdef PassthroughVertex[4] buf 285 cdef PassthroughVertex[4] buf
250 286
253 glBindFramebuffer(GL_FRAMEBUFFER, 0) 289 glBindFramebuffer(GL_FRAMEBUFFER, 0)
254 glViewport(self.x, self.y, self.width, self.height) 290 glViewport(self.x, self.y, self.width, self.height)
255 glBlendFunc(GL_ONE, GL_ZERO) 291 glBlendFunc(GL_ONE, GL_ZERO)
256 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 292 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
257 293
258 glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo) 294 if use_vao:
259 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo) 295 glBindVertexArray(self.framebuffer_vao)
260 296 else:
261 #TODO: find a way to use offsetof() instead of those ugly hardcoded values. 297 self.set_framebuffer_state()
262 glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
263 glEnableVertexAttribArray(0)
264 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
265 glEnableVertexAttribArray(1)
266 298
267 buf[0] = PassthroughVertex(fb.x, fb.y, 0, 1) 299 buf[0] = PassthroughVertex(fb.x, fb.y, 0, 1)
268 buf[1] = PassthroughVertex(fb.x + fb.width, fb.y, 1, 1) 300 buf[1] = PassthroughVertex(fb.x + fb.width, fb.y, 1, 1)
269 buf[2] = PassthroughVertex(fb.x + fb.width, fb.y + fb.height, 1, 0) 301 buf[2] = PassthroughVertex(fb.x + fb.width, fb.y + fb.height, 1, 0)
270 buf[3] = PassthroughVertex(fb.x, fb.y + fb.height, 0, 0) 302 buf[3] = PassthroughVertex(fb.x, fb.y + fb.height, 0, 0)
271 glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(PassthroughVertex), buf, GL_DYNAMIC_DRAW) 303
304 glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
305 glBufferData(GL_ARRAY_BUFFER, sizeof(buf), buf, GL_DYNAMIC_DRAW)
306 glBindBuffer(GL_ARRAY_BUFFER, 0)
272 307
273 glBindTexture(GL_TEXTURE_2D, fb.texture) 308 glBindTexture(GL_TEXTURE_2D, fb.texture)
274 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL) 309 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL)
275 glBindTexture(GL_TEXTURE_2D, 0) 310 glBindTexture(GL_TEXTURE_2D, 0)
276 311
277 glBindBuffer(GL_ARRAY_BUFFER, 0) 312 if use_vao:
278 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 313 glBindVertexArray(0)
314 else:
315 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
279 316
280 317
281 cdef class Framebuffer: 318 cdef class Framebuffer:
282 def __init__(self, int x, int y, int width, int height): 319 def __init__(self, int x, int y, int width, int height):
283 self.x = x 320 self.x = x