comparison pytouhou/ui/opengl/renderer.pyx @ 586:4b0593da29d5

Simplify framebuffer rendering with glDrawArrays, and move it all to its own file.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Wed, 08 Oct 2014 16:34:24 +0200
parents e0166cda75d5
children 6c9d8a3d853f
comparison
equal deleted inserted replaced
585:e0166cda75d5 586:4b0593da29d5
21 glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc, 21 glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc,
22 glBindTexture, glDrawElements, glBindBuffer, glBufferData, 22 glBindTexture, glDrawElements, glBindBuffer, glBufferData,
23 GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, GL_UNSIGNED_BYTE, 23 GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, GL_UNSIGNED_BYTE,
24 GL_UNSIGNED_SHORT, GL_SHORT, GL_FLOAT, GL_SRC_ALPHA, 24 GL_UNSIGNED_SHORT, GL_SHORT, GL_FLOAT, GL_SRC_ALPHA,
25 GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO, GL_TEXTURE_2D, GL_TRIANGLES, 25 GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO, GL_TEXTURE_2D, GL_TRIANGLES,
26 glGenBuffers, glBindFramebuffer, glViewport, glDeleteBuffers, 26 GL_TRIANGLE_STRIP, glGenBuffers, glBindFramebuffer, glViewport,
27 glGenTextures, glTexParameteri, glTexImage2D, glGenRenderbuffers, 27 glDeleteBuffers, GL_FRAMEBUFFER, glClear, GL_COLOR_BUFFER_BIT,
28 glBindRenderbuffer, glRenderbufferStorage, glGenFramebuffers, 28 GL_DEPTH_BUFFER_BIT, GLuint, glDeleteTextures, glGenVertexArrays,
29 glFramebufferTexture2D, glFramebufferRenderbuffer,
30 glCheckFramebufferStatus, GL_FRAMEBUFFER, GL_TEXTURE_MIN_FILTER,
31 GL_LINEAR, GL_TEXTURE_MAG_FILTER, GL_RGBA, GL_RENDERBUFFER,
32 GL_DEPTH_COMPONENT16, GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
33 GL_FRAMEBUFFER_COMPLETE, glClear, GL_COLOR_BUFFER_BIT,
34 GL_DEPTH_BUFFER_BIT, GLuint, glDeleteTextures,
35 GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, glGenVertexArrays,
36 glDeleteVertexArrays, glBindVertexArray, glPushDebugGroup, 29 glDeleteVertexArrays, glBindVertexArray, glPushDebugGroup,
37 GL_DEBUG_SOURCE_APPLICATION, glPopDebugGroup, GL_TRIANGLE_STRIP) 30 GL_DEBUG_SOURCE_APPLICATION, glPopDebugGroup)
38 31
39 from pytouhou.lib.sdl import SDLError 32 from pytouhou.lib.sdl import SDLError
40 33
41 from pytouhou.game.element cimport Element 34 from pytouhou.game.element cimport Element
42 from .sprite cimport get_sprite_rendering_data 35 from .sprite cimport get_sprite_rendering_data
93 86
94 87
95 cdef class Renderer: 88 cdef class Renderer:
96 def __dealloc__(self): 89 def __dealloc__(self):
97 if not is_legacy: 90 if not is_legacy:
98 glDeleteBuffers(1, &self.framebuffer_vbo)
99 glDeleteBuffers(1, &self.vbo) 91 glDeleteBuffers(1, &self.vbo)
100 92
101 if use_vao: 93 if use_vao:
102 glDeleteVertexArrays(1, &self.vao) 94 glDeleteVertexArrays(1, &self.vao)
103 glDeleteVertexArrays(1, &self.framebuffer_vao)
104 95
105 96
106 def __init__(self, resource_loader): 97 def __init__(self, resource_loader):
107 # Only used in modern GL.
108 cdef unsigned short framebuffer_indices[6]
109
110 self.texture_manager = TextureManager(resource_loader, self, Texture) 98 self.texture_manager = TextureManager(resource_loader, self, Texture)
111 font_name = join(resource_loader.game_dir, 'font.ttf') 99 font_name = join(resource_loader.game_dir, 'font.ttf')
112 try: 100 try:
113 self.font_manager = FontManager(font_name, 16, self, Texture) 101 self.font_manager = FontManager(font_name, 16, self, Texture)
114 except SDLError: 102 except SDLError:
115 self.font_manager = None 103 self.font_manager = None
116 logger.error('Font file ā€œ%sā€ not found, disabling text rendering altogether.', font_name) 104 logger.error('Font file ā€œ%sā€ not found, disabling text rendering altogether.', font_name)
117 105
118 if not is_legacy: 106 if not is_legacy:
119 framebuffer_indices[:] = [0, 1, 2, 2, 3, 0]
120
121 if use_debug_group: 107 if use_debug_group:
122 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Renderer creation") 108 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Renderer creation")
123 109
124 glGenBuffers(1, &self.vbo) 110 glGenBuffers(1, &self.vbo)
125 glGenBuffers(1, &self.framebuffer_vbo)
126 glGenBuffers(1, &self.framebuffer_ibo)
127
128 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
129 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(framebuffer_indices), framebuffer_indices, GL_STATIC_DRAW)
130 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
131 111
132 if use_vao: 112 if use_vao:
133 glGenVertexArrays(1, &self.vao) 113 glGenVertexArrays(1, &self.vao)
134 glBindVertexArray(self.vao) 114 glBindVertexArray(self.vao)
135 self.set_state() 115 self.set_state()
136
137 glGenVertexArrays(1, &self.framebuffer_vao)
138 glBindVertexArray(self.framebuffer_vao)
139 self.set_framebuffer_state()
140 glBindVertexArray(0)
141 116
142 if use_debug_group: 117 if use_debug_group:
143 glPopDebugGroup() 118 glPopDebugGroup()
144 119
145 120
151 glEnableVertexAttribArray(0) 126 glEnableVertexAttribArray(0)
152 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8) 127 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8)
153 glEnableVertexAttribArray(1) 128 glEnableVertexAttribArray(1)
154 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16) 129 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
155 glEnableVertexAttribArray(2) 130 glEnableVertexAttribArray(2)
156
157 glBindBuffer(GL_ARRAY_BUFFER, 0)
158
159
160 cdef void set_framebuffer_state(self) nogil:
161 glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
162 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
163
164 #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
165 glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
166 glEnableVertexAttribArray(0)
167 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
168 glEnableVertexAttribArray(1)
169 131
170 glBindBuffer(GL_ARRAY_BUFFER, 0) 132 glBindBuffer(GL_ARRAY_BUFFER, 0)
171 133
172 134
173 cdef void render_elements(self, elements): 135 cdef void render_elements(self, elements):
307 if use_debug_group: 269 if use_debug_group:
308 glPopDebugGroup() 270 glPopDebugGroup()
309 271
310 272
311 cdef void render_framebuffer(self, Framebuffer fb): 273 cdef void render_framebuffer(self, Framebuffer fb):
312 cdef PassthroughVertex[4] buf
313
314 assert not is_legacy 274 assert not is_legacy
315 275
316 if use_debug_group: 276 if use_debug_group:
317 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Framebuffer drawing") 277 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Framebuffer drawing")
318 278
319 glBindFramebuffer(GL_FRAMEBUFFER, 0) 279 glBindFramebuffer(GL_FRAMEBUFFER, 0)
320 glViewport(self.x, self.y, self.width, self.height) 280 glViewport(self.x, self.y, self.width, self.height)
321 glBlendFunc(GL_ONE, GL_ZERO) 281 glBlendFunc(GL_ONE, GL_ZERO)
322 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 282 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
323 283
324 if use_vao: 284 fb.render()
325 glBindVertexArray(self.framebuffer_vao)
326 else:
327 self.set_framebuffer_state()
328
329 buf[0] = PassthroughVertex(fb.x, fb.y, 0, 1)
330 buf[1] = PassthroughVertex(fb.x + fb.width, fb.y, 1, 1)
331 buf[2] = PassthroughVertex(fb.x + fb.width, fb.y + fb.height, 1, 0)
332 buf[3] = PassthroughVertex(fb.x, fb.y + fb.height, 0, 0)
333
334 glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
335 glBufferData(GL_ARRAY_BUFFER, sizeof(buf), buf, GL_DYNAMIC_DRAW)
336 glBindBuffer(GL_ARRAY_BUFFER, 0)
337
338 glBindTexture(GL_TEXTURE_2D, fb.texture)
339 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL)
340 glBindTexture(GL_TEXTURE_2D, 0)
341
342 if use_vao:
343 glBindVertexArray(0)
344 else:
345 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
346 285
347 if use_debug_group: 286 if use_debug_group:
348 glPopDebugGroup() 287 glPopDebugGroup()
349
350
351 cdef class Framebuffer:
352 def __init__(self, int x, int y, int width, int height):
353 self.x = x
354 self.y = y
355 self.width = width
356 self.height = height
357
358 if use_debug_group:
359 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Framebuffer creation")
360
361 glGenTextures(1, &self.texture)
362 glBindTexture(GL_TEXTURE_2D, self.texture)
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
365 glTexImage2D(GL_TEXTURE_2D, 0,
366 GL_RGBA,
367 width, height,
368 0,
369 GL_RGBA, GL_UNSIGNED_BYTE,
370 NULL)
371 glBindTexture(GL_TEXTURE_2D, 0)
372
373 glGenRenderbuffers(1, &self.rbo)
374 glBindRenderbuffer(GL_RENDERBUFFER, self.rbo)
375 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height)
376 glBindRenderbuffer(GL_RENDERBUFFER, 0)
377
378 glGenFramebuffers(1, &self.fbo)
379 glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
380 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.texture, 0)
381 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, self.rbo)
382 assert glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
383 glBindFramebuffer(GL_FRAMEBUFFER, 0)
384
385 if use_debug_group:
386 glPopDebugGroup()
387
388 cpdef bind(self):
389 glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)