Working With FrameBuffer Objects#
Start with a simple window:
Starting template#
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:
Pass-through 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:
Pass-through 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 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:
Pass-through 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 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()
|