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