comparison pytouhou/ui/opengl/framebuffer.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
children 6c9d8a3d853f
comparison
equal deleted inserted replaced
585:e0166cda75d5 586:4b0593da29d5
1 # -*- encoding: utf-8 -*-
2 ##
3 ## Copyright (C) 2014 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
4 ##
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published
7 ## by the Free Software Foundation; version 3 only.
8 ##
9 ## This program is distributed in the hope that it will be useful,
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details.
13 ##
14
15 from pytouhou.lib.opengl cimport \
16 (glPushDebugGroup, glPopDebugGroup, GL_DEBUG_SOURCE_APPLICATION,
17 glGenTextures, glDeleteTextures, glBindTexture, glTexParameteri,
18 glTexImage2D, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
19 GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_RGBA, GL_UNSIGNED_BYTE,
20 glGenRenderbuffers, glDeleteRenderbuffers, glBindRenderbuffer,
21 glRenderbufferStorage, GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
22 glGenFramebuffers, glDeleteFramebuffers, glBindFramebuffer,
23 glFramebufferTexture2D, glFramebufferRenderbuffer,
24 glCheckFramebufferStatus, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
25 GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_COMPLETE, glGenBuffers,
26 glDeleteBuffers, glBindBuffer, glBufferData, GL_ARRAY_BUFFER,
27 GL_STATIC_DRAW, glGenVertexArrays, glDeleteVertexArrays,
28 glBindVertexArray, glVertexAttribPointer, GL_SHORT, GL_FLOAT,
29 glEnableVertexAttribArray, glDrawArrays, GL_TRIANGLE_STRIP)
30
31 from .backend cimport use_debug_group, use_vao
32
33 cdef class Framebuffer:
34 def __init__(self, int x, int y, int width, int height):
35 if use_debug_group:
36 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Framebuffer creation")
37
38 # This texture will receive the game area in native resolution.
39 glGenTextures(1, &self.texture)
40 glBindTexture(GL_TEXTURE_2D, self.texture)
41 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
42 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
43 glTexImage2D(GL_TEXTURE_2D, 0,
44 GL_RGBA,
45 width, height,
46 0,
47 GL_RGBA, GL_UNSIGNED_BYTE,
48 NULL)
49 glBindTexture(GL_TEXTURE_2D, 0)
50
51 # We need a depth buffer, but don’t care about retrieving it.
52 glGenRenderbuffers(1, &self.rbo)
53 glBindRenderbuffer(GL_RENDERBUFFER, self.rbo)
54 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height)
55 glBindRenderbuffer(GL_RENDERBUFFER, 0)
56
57 # The framebuffer is there as a rendering target.
58 glGenFramebuffers(1, &self.fbo)
59 glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
60 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.texture, 0)
61 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, self.rbo)
62 assert glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
63 glBindFramebuffer(GL_FRAMEBUFFER, 0)
64
65 # We’ll use only those vertices, everytime.
66 self.buf[0] = PassthroughVertex(x, y, 0, 1)
67 self.buf[1] = PassthroughVertex(x + width, y, 1, 1)
68 self.buf[2] = PassthroughVertex(x, y + height, 0, 0)
69 self.buf[3] = PassthroughVertex(x + width, y + height, 1, 0)
70
71 # Now we upload those vertices into a static vbo.
72 glGenBuffers(1, &self.vbo)
73 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
74 glBufferData(GL_ARRAY_BUFFER, sizeof(self.buf), self.buf, GL_STATIC_DRAW)
75
76 # As a performance optimisation, if supported, store the rendering state into a vao.
77 if use_vao:
78 glGenVertexArrays(1, &self.vao)
79 glBindVertexArray(self.vao)
80 self.set_state()
81 glBindVertexArray(0)
82
83 glBindBuffer(GL_ARRAY_BUFFER, 0)
84
85 if use_debug_group:
86 glPopDebugGroup()
87
88 def __dealloc__(self):
89 if use_vao:
90 glDeleteVertexArrays(1, &self.vao)
91 glDeleteTextures(1, &self.texture)
92 glDeleteRenderbuffers(1, &self.rbo)
93 glDeleteFramebuffers(1, &self.fbo)
94 glDeleteBuffers(1, &self.vbo)
95
96 cpdef bind(self):
97 glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
98
99 cdef void set_state(self) nogil:
100 glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
101
102 #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
103 glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
104 glEnableVertexAttribArray(0)
105 glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
106 glEnableVertexAttribArray(1)
107
108 cdef void render(self) nogil:
109 if use_vao:
110 glBindVertexArray(self.vao)
111 else:
112 self.set_state()
113
114 glBindTexture(GL_TEXTURE_2D, self.texture)
115 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
116 glBindTexture(GL_TEXTURE_2D, 0)
117
118 if use_vao:
119 glBindVertexArray(0)
120 else:
121 glBindBuffer(GL_ARRAY_BUFFER, 0)