gpu_particle_burst_03.py Full Listing#

gpu_particle_burst_03.py#
 1"""
 2Example showing how to create particle explosions via the GPU.
 3"""
 4import random
 5import time
 6from array import array
 7from dataclasses import dataclass
 8import arcade
 9import arcade.gl
10
11SCREEN_WIDTH = 1024
12SCREEN_HEIGHT = 768
13SCREEN_TITLE = "GPU Particle Explosion"
14
15PARTICLE_COUNT = 300
16
17
18@dataclass
19class Burst:
20    """ Track for each burst. """
21    buffer: arcade.gl.Buffer
22    vao: arcade.gl.Geometry
23    start_time: float
24
25
26class MyWindow(arcade.Window):
27    """ Main window"""
28    def __init__(self):
29        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
30        self.burst_list = []
31
32        # Program to visualize the points
33        self.program = self.ctx.load_program(
34            vertex_shader="vertex_shader_v1.glsl",
35            fragment_shader="fragment_shader.glsl",
36        )
37
38        self.ctx.enable_only()
39
40    def on_draw(self):
41        """ Draw everything """
42        self.clear()
43
44        # Set the particle size
45        self.ctx.point_size = 2 * self.get_pixel_ratio()
46
47        # Loop through each burst
48        for burst in self.burst_list:
49
50            # Set the uniform data
51            self.program['time'] = time.time() - burst.start_time
52
53            # Render the burst
54            burst.vao.render(self.program, mode=self.ctx.POINTS)
55
56    def on_update(self, dt):
57        """ Update everything """
58        pass
59
60    def on_mouse_press(self, x: float, y: float, button: int, modifiers: int):
61        """ User clicks mouse """
62
63        def _gen_initial_data(initial_x, initial_y):
64            """ Generate data for each particle """
65            for i in range(PARTICLE_COUNT):
66                dx = random.uniform(-.2, .2)
67                dy = random.uniform(-.2, .2)
68                yield initial_x
69                yield initial_y
70                yield dx
71                yield dy
72
73        # Recalculate the coordinates from pixels to the OpenGL system with
74        # 0, 0 at the center.
75        x2 = x / self.width * 2. - 1.
76        y2 = y / self.height * 2. - 1.
77
78        # Get initial particle data
79        initial_data = _gen_initial_data(x2, y2)
80
81        # Create a buffer with that data
82        buffer = self.ctx.buffer(data=array('f', initial_data))
83
84        # Create a buffer description that says how the buffer data is formatted.
85        buffer_description = arcade.gl.BufferDescription(buffer,
86                                                         '2f 2f',
87                                                         ['in_pos', 'in_vel'])
88        # Create our Vertex Attribute Object
89        vao = self.ctx.geometry([buffer_description])
90
91        # Create the Burst object and add it to the list of bursts
92        burst = Burst(buffer=buffer, vao=vao, start_time=time.time())
93        self.burst_list.append(burst)
94
95
96if __name__ == "__main__":
97    window = MyWindow()
98    window.center_window()
99    arcade.run()