Working With FrameBuffer Objects#
Start with a simple window:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Frame Buffer Object Demo" class MyGame(arcade.Window): def __init__(self, width, height, title): super().__init__(width, height, title) arcade.set_background_color(arcade.color.ALMOND) def setup(self): pass def on_draw(self): self.clear() def main(): """ Main function """ window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) window.setup() arcade.run() if __name__ == "__main__": main() |
Then create a simple program with a frame buffer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import arcade from arcade.experimental.texture_render_target import RenderTargetTexture SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Starting Template Simple" class RandomFilter(RenderTargetTexture): def __init__(self, width, height): super().__init__(width, height) self.program = self.ctx.program( vertex_shader=""" #version 330 in vec2 in_vert; in vec2 in_uv; out vec2 uv; void main() { gl_Position = vec4(in_vert, 0.0, 1.0); uv = in_uv; } """, fragment_shader=""" #version 330 uniform sampler2D texture0; in vec2 uv; out vec4 fragColor; void main() { vec4 color = texture(texture0, uv); fragColor = color; } """, ) def use(self): self._fbo.use() def draw(self): self.texture.use(0) self._quad_fs.render(self.program) class MyGame(arcade.Window): def __init__(self, width, height, title): super().__init__(width, height, title) self.filter = RandomFilter(width, height) def on_draw(self): self.clear() self.filter.clear() self.filter.use() print(self.width / 2) arcade.draw_circle_filled(self.width / 2, self.height / 2, 100, arcade.color.RED) arcade.draw_circle_filled(400, 300, 100, arcade.color.GREEN) self.use() self.filter.draw() def main(): """ Main function """ MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) arcade.run() if __name__ == "__main__": main() |
Now, color everything that doesn’t have an alpha of zero as green:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import arcade from arcade.experimental.texture_render_target import RenderTargetTexture SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Starting Template Simple" class RandomFilter(RenderTargetTexture): def __init__(self, width, height): super().__init__(width, height) self.program = self.ctx.program( vertex_shader=""" #version 330 in vec2 in_vert; in vec2 in_uv; out vec2 uv; void main() { gl_Position = vec4(in_vert, 0.0, 1.0); uv = in_uv; } """, fragment_shader=""" #version 330 uniform sampler2D texture0; in vec2 uv; out vec4 fragColor; void main() { vec4 color = texture(texture0, uv); if (color.a > 0) fragColor = vec4(0, 1, 0, 1.0); else fragColor = vec4(0, 0, 0, 0); } """, ) def use(self): self._fbo.use() def draw(self): self.texture.use(0) self._quad_fs.render(self.program) class MyGame(arcade.Window): def __init__(self, width, height, title): super().__init__(width, height, title) self.filter = RandomFilter(width, height) def on_draw(self): self.clear() self.filter.clear() self.filter.use() arcade.draw_circle_filled(self.width / 2, self.height / 2, 100, arcade.color.RED) self.use() self.filter.draw() def main(): """ Main function """ MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) arcade.run() if __name__ == "__main__": main() |
Something about passing uniform data to the shader:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import arcade from arcade.experimental.texture_render_target import RenderTargetTexture SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_TITLE = "Starting Template Simple" class RandomFilter(RenderTargetTexture): def __init__(self, width, height): super().__init__(width, height) self.program = self.ctx.program( vertex_shader=""" #version 330 in vec2 in_vert; in vec2 in_uv; out vec2 uv; void main() { gl_Position = vec4(in_vert, 0.0, 1.0); uv = in_uv; } """, fragment_shader=""" #version 330 uniform sampler2D texture0; in vec2 uv; uniform vec4 my_color; out vec4 fragColor; void main() { vec4 color = texture(texture0, uv); if (color.a > 0) fragColor = my_color; else fragColor = vec4(0, 0, 0, 0); } """, ) self.program["my_color"] = 1, 0, 1, 1 def use(self): self._fbo.use() def draw(self): self.texture.use(0) self._quad_fs.render(self.program) class MyGame(arcade.Window): def __init__(self, width, height, title): super().__init__(width, height, title) self.filter = RandomFilter(width, height) def on_draw(self): self.clear() self.filter.clear() self.filter.use() arcade.draw_circle_filled(self.width / 2, self.height / 2, 100, arcade.color.RED) self.use() self.filter.draw() def main(): """ Main function """ MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) arcade.run() if __name__ == "__main__": main() |