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
  8
  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_v2.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                dx = random.uniform(-.2, .2)
 68                dy = random.uniform(-.2, .2)
 69                yield initial_x
 70                yield initial_y
 71                yield dx
 72                yield dy
 73
 74        # Recalculate the coordinates from pixels to the OpenGL system with
 75        # 0, 0 at the center.
 76        x2 = x / self.width * 2. - 1.
 77        y2 = y / self.height * 2. - 1.
 78
 79        # Get initial particle data
 80        initial_data = _gen_initial_data(x2, y2)
 81
 82        # Create a buffer with that data
 83        buffer = self.ctx.buffer(data=array('f', initial_data))
 84
 85        # Create a buffer description specifying the buffer's data format
 86        buffer_description = arcade.gl.BufferDescription(
 87            buffer,
 88            '2f 2f',
 89            ['in_pos', 'in_vel'])
 90
 91        # Create our Vertex Attribute Object
 92        vao = self.ctx.geometry([buffer_description])
 93
 94        # Create the Burst object and add it to the list of bursts
 95        burst = Burst(buffer=buffer, vao=vao, start_time=time.time())
 96        self.burst_list.append(burst)
 97
 98
 99if __name__ == "__main__":
100    window = MyWindow()
101    window.center_window()
102    arcade.run()