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