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