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