def on_mouse_press(self, x: float, y: float, button: int, modifiers: int):
        burst = Burst()
        x2 = x / self.width * 2. - 1.
        y2 = y / self.height * 2. - 1.
        burst.buffer = self.ctx.buffer(data=array('f', self.gen_initial_data(PARTICLE_COUNT, x2, y2)))

        # We also need to be able to visualize both versions (draw to the screen)
        buffer_description = BufferDescription(burst.buffer,
                                               '2f 2f f 3f',
                                               ['in_pos', 'in_vel', 'in_fade', 'in_color'])
        burst.vao = self.ctx.geometry([buffer_description])

        burst.time = time.time()
        self.burst_list.append(burst)
Beispiel #2
0
 def _create_device_objects(self):
     self._program = self._ctx.program(
         vertex_shader=self.VERTEX_SHADER_SRC,
         fragment_shader=self.FRAGMENT_SHADER_SRC,
     )
     self._program["Texture"] = 0
     self._vbo = self._ctx.buffer(reserve=imgui.VERTEX_SIZE * 65536)
     self._ibo = self._ctx.buffer(reserve=imgui.INDEX_SIZE * 65536)
     # NOTE: imgui.INDEX_SIZE is type size for the index buffer. We might need to support 8 and 16 bit
     # but right now we are assuming 32 bit
     self._vao = self._ctx.geometry(
         [
             BufferDescription(self._vbo,
                               "2f 2f 4f1", ("Position", "UV", "Color"),
                               normalized=("Color", )),
         ],
         index_buffer=self._ibo,
     )
Beispiel #3
0
def create_line_generic_with_colors(point_list: PointList,
                                    color_list: Iterable[Color],
                                    shape_mode: int,
                                    line_width: float = 1) -> Shape:
    """
    This function is used by ``create_line_strip`` and ``create_line_loop``,
    just changing the OpenGL type for the line drawing.

    :param PointList point_list:
    :param Iterable[Color] color_list:
    :param float shape_mode:
    :param float line_width:

    :Returns Shape:
    """
    window = get_window()
    ctx = window.ctx
    program = ctx.line_generic_with_colors_program

    buffer_type = np.dtype([('vertex', '2f4'), ('color', '4B')])
    data = np.zeros(len(point_list), dtype=buffer_type)
    data['vertex'] = point_list
    data['color'] = [get_four_byte_color(color) for color in color_list]

    vbo = ctx.buffer(data=data.tobytes())
    vao_content = [
        BufferDescription(
            vbo,
            '2f 4f1',
            ('in_vert', 'in_color'),
            normalized=['in_color']
        )
    ]

    vao = ctx.geometry(vao_content)

    shape = Shape()
    shape.vao = vao
    shape.vbo = vbo
    shape.program = program
    shape.mode = shape_mode
    shape.line_width = line_width

    return shape
Beispiel #4
0
    def _refresh_shape(self, group):
        # Create a buffer large enough to hold all the shapes buffers
        batch = self.batches[group]

        total_vbo_bytes = sum(s.vbo.size for s in batch.items)
        vbo = self.ctx.buffer(reserve=total_vbo_bytes)
        offset = 0
        # Copy all the shapes buffer in our own vbo
        for shape in batch.items:
            vbo.copy_from_buffer(shape.vbo, offset=offset)
            offset += shape.vbo.size

        # Create an index buffer object. It should count starting from 0. We need to
        # use a reset_idx to indicate that a new shape will start.
        reset_idx = 2 ** 32 - 1
        indices = []
        counter = itertools.count()
        for shape in batch.items:
            indices.extend(itertools.islice(counter, shape.vao.num_vertices))
            indices.append(reset_idx)
        del indices[-1]
        indices = np.array(indices)
        ibo = self.ctx.buffer(data=indices.astype('i4').tobytes())

        vao_content = [
            BufferDescription(
                vbo,
                '2f 4f1',
                ('in_vert', 'in_color'),
                normalized=['in_color']
            )
        ]
        vao = self.ctx.geometry(vao_content, ibo)
        self.program['Position'] = [self.center_x, self.center_y]
        self.program['Angle'] = self.angle

        batch.shape.vao = vao
        batch.shape.vbo = vbo
        batch.shape.ibo = ibo
        batch.shape.program = self.program
        mode, line_width = group
        batch.shape.mode = mode
        batch.shape.line_width = line_width
Beispiel #5
0
def quad_2d(size: Tuple[float, float] = (1.0, 1.0),
            pos: Tuple[float, float] = (0.0, 0.0)) -> Geometry:
    """
    Creates 2D quad Geometry using 2 triangle strip with texture coordinates.

    :param tuple size: width and height
    :param float pos: Center position x and y
    :rtype: A :py:class:`~arcade.gl.geometry.Geometry` instance.       
    """
    ctx = _get_active_context()
    width, height = size
    x_pos, y_pos = pos

    data = array.array('f', [
        x_pos - width / 2.0,
        y_pos + height / 2.0,
        0.0,
        1.0,
        x_pos - width / 2.0,
        y_pos - height / 2.0,
        0.0,
        0.0,
        x_pos + width / 2.0,
        y_pos + height / 2.0,
        1.0,
        1.0,
        x_pos + width / 2.0,
        y_pos - height / 2.0,
        1.0,
        0.0,
    ])

    return ctx.geometry([
        BufferDescription(
            ctx.buffer(data=data),
            '2f 2f',
            ['in_vert', 'in_uv'],
        )
    ],
                        mode=ctx.TRIANGLE_STRIP)
Beispiel #6
0
def screen_rectangle(bottom_left_x: float, bottom_left_y: float, width: float,
                     height: float) -> Geometry:
    """
    Creates screen rectangle using 2 triangle strip with texture coordinates.
    
    :param float bottom_left_x: Bottom left x position
    :param float bottom_left_y: Bottom left y position
    :param float width: Width of the rectangle
    :param float height: Height of the rectangle   
    """
    ctx = _get_active_context()
    data = array.array('f', [
        bottom_left_x,
        bottom_left_y + height,
        0.0,
        1.0,
        bottom_left_x,
        bottom_left_y,
        0.0,
        0.0,
        bottom_left_x + width,
        bottom_left_y + height,
        1.0,
        1.0,
        bottom_left_x + width,
        bottom_left_y,
        1.0,
        0.0,
    ])
    return ctx.geometry([
        BufferDescription(
            ctx.buffer(data=data),
            '2f 2f',
            ['in_vert', 'in_uv'],
        )
    ],
                        mode=ctx.TRIANGLE_STRIP)
Beispiel #7
0
    def __init__(self, window: pyglet.window.Window):
        """
        :param pyglet.window.Window window: The pyglet window
        """
        super().__init__(window)

        # Set up a default orthogonal projection for sprites and shapes
        self._projection_2d_buffer = self.buffer(reserve=64)
        self._projection_2d_buffer.bind_to_uniform_block(0)
        self._projection_2d_matrix = None
        self.projection_2d = (
            0,
            self.screen.width,
            0,
            self.screen.height,
        )

        # --- Pre-load system shaders here ---
        # FIXME: These pre-created resources needs to be packaged nicely
        #        Just having them globally in the context is probably not a good idea
        self.line_vertex_shader = self.load_program(
            vertex_shader=":resources:shaders/shapes/line/line_vertex_shader_vs.glsl",
            fragment_shader=":resources:shaders/shapes/line/line_vertex_shader_fs.glsl",
        )
        self.line_generic_with_colors_program = self.load_program(
            vertex_shader=":resources:shaders/shapes/line/line_generic_with_colors_vs.glsl",
            fragment_shader=":resources:shaders/shapes/line/line_generic_with_colors_fs.glsl",
        )
        self.shape_element_list_program = self.load_program(
            vertex_shader=":resources:shaders/shape_element_list_vs.glsl",
            fragment_shader=":resources:shaders/shape_element_list_fs.glsl",
        )
        # self.sprite_list_program = self.load_program(
        #     vertex_shader=':resources:shaders/sprites/sprite_list_instanced_vs.glsl',
        #     fragment_shader=':resources:shaders/sprites/sprite_list_instanced_fs.glsl',
        # )
        self.sprite_list_program_no_cull = self.load_program(
            vertex_shader=":resources:shaders/sprites/sprite_list_geometry_vs.glsl",
            geometry_shader=":resources:shaders/sprites/sprite_list_geometry_no_cull_geo.glsl",
            fragment_shader=":resources:shaders/sprites/sprite_list_geometry_fs.glsl",
        )
        self.sprite_list_program_cull = self.load_program(
            vertex_shader=":resources:shaders/sprites/sprite_list_geometry_vs.glsl",
            geometry_shader=":resources:shaders/sprites/sprite_list_geometry_cull_geo.glsl",
            fragment_shader=":resources:shaders/sprites/sprite_list_geometry_fs.glsl",
        )

        # Shapes
        self.shape_line_program = self.load_program(
            vertex_shader=":resources:/shaders/shapes/line/unbuffered_vs.glsl",
            fragment_shader=":resources:/shaders/shapes/line/unbuffered_fs.glsl",
            geometry_shader=":resources:/shaders/shapes/line/unbuffered_geo.glsl",
        )
        self.shape_ellipse_filled_unbuffered_program = self.load_program(
            vertex_shader=":resources:/shaders/shapes/ellipse/filled_unbuffered_vs.glsl",
            fragment_shader=":resources:/shaders/shapes/ellipse/filled_unbuffered_fs.glsl",
            geometry_shader=":resources:/shaders/shapes/ellipse/filled_unbuffered_geo.glsl",
        )
        self.shape_ellipse_outline_unbuffered_program = self.load_program(
            vertex_shader=":resources:/shaders/shapes/ellipse/outline_unbuffered_vs.glsl",
            fragment_shader=":resources:/shaders/shapes/ellipse/outline_unbuffered_fs.glsl",
            geometry_shader=":resources:/shaders/shapes/ellipse/outline_unbuffered_geo.glsl",
        )
        self.shape_rectangle_filled_unbuffered_program = self.load_program(
            vertex_shader=":resources:/shaders/shapes/rectangle/filled_unbuffered_vs.glsl",
            fragment_shader=":resources:/shaders/shapes/rectangle/filled_unbuffered_fs.glsl",
            geometry_shader=":resources:/shaders/shapes/rectangle/filled_unbuffered_geo.glsl",
        )

        # --- Pre-created geometry and buffers for unbuffered draw calls ----
        # FIXME: These pre-created resources needs to be packaged nicely
        #        Just having them globally in the context is probably not a good idea
        self.generic_draw_line_strip_color = self.buffer(reserve=4 * 1000)
        self.generic_draw_line_strip_vbo = self.buffer(reserve=8 * 1000)
        self.generic_draw_line_strip_geometry = self.geometry(
            [
                BufferDescription(self.generic_draw_line_strip_vbo, "2f", ["in_vert"]),
                BufferDescription(
                    self.generic_draw_line_strip_color,
                    "4f1",
                    ["in_color"],
                    normalized=["in_color"],
                ),
            ]
        )
        # Shape line(s)
        # Reserve space for 1000 lines (2f pos, 4f color)
        # TODO: Different version for buffered and unbuffered
        # TODO: Make round-robin buffers
        self.shape_line_buffer_pos = self.buffer(reserve=8 * 10)
        # self.shape_line_buffer_color = self.buffer(reserve=4 * 10)
        self.shape_line_geometry = self.geometry(
            [
                BufferDescription(self.shape_line_buffer_pos, "2f", ["in_vert"]),
                # BufferDescription(self.shape_line_buffer_color, '4f1', ['in_color'], normalized=['in_color'])
            ]
        )
        # ellipse/circle filled
        self.shape_ellipse_unbuffered_buffer = self.buffer(reserve=8)
        self.shape_ellipse_unbuffered_geometry = self.geometry(
            [BufferDescription(self.shape_ellipse_unbuffered_buffer, "2f", ["in_vert"])]
        )
        # ellipse/circle outline
        self.shape_ellipse_outline_unbuffered_buffer = self.buffer(reserve=8)
        self.shape_ellipse_outline_unbuffered_geometry = self.geometry(
            [
                BufferDescription(
                    self.shape_ellipse_outline_unbuffered_buffer, "2f", ["in_vert"]
                )
            ]
        )
        # rectangle filled
        self.shape_rectangle_filled_unbuffered_buffer = self.buffer(reserve=8)
        self.shape_rectangle_filled_unbuffered_geometry = self.geometry(
            [
                BufferDescription(
                    self.shape_rectangle_filled_unbuffered_buffer, "2f", ["in_vert"]
                )
            ]
        )
Beispiel #8
0
    def __init__(self, width, height, title):
        super().__init__(width, height, title, resizable=True)
        self.time = 0

        # Program to visualize the points
        self.points_program = self.ctx.program(
            vertex_shader="""
            #version 330
            in vec2 in_pos;
            void main() {
                // Just pass the position to the geometry shader
                gl_Position = vec4(in_pos, 0.0, 1.0);
            }
            """,
            geometry_shader="""
            #version 330

            uniform Projection {
                mat4 matrix;
            } proj;

            // We are receiving points and emitting triangle strip (4 vertices making a quad)
            layout (points) in;
            layout (triangle_strip, max_vertices = 4) out;

            const float P_SIZE = 10.0;
            out vec2 uv;

            void main() {
                // The input point is the center of the quad
                vec2 center = gl_in[0].gl_Position.xy;
                // Emit 4 vertices making a triangle strip representing a quad

                gl_Position = proj.matrix * vec4(center + vec2(-P_SIZE,  P_SIZE), 0.0, 1.0);
                uv = vec2(0, 1);
                EmitVertex();

                gl_Position = proj.matrix * vec4(center + vec2(-P_SIZE, -P_SIZE), 0.0, 1.0);
                uv = vec2(0, 0);
                EmitVertex();

                gl_Position = proj.matrix * vec4(center + vec2( P_SIZE,  P_SIZE), 0.0, 1.0);
                uv = vec2(1, 1);
                EmitVertex();

                gl_Position = proj.matrix * vec4(center + vec2( P_SIZE, -P_SIZE), 0.0, 1.0);
                uv = vec2(1, 0);
                EmitVertex();
                EndPrimitive();
            }
            """,
            fragment_shader="""
            #version 330

            // Texture coordinates generated in geometry shader
            in vec2 uv;
            // The pixel we are writing to in the framebuffer
            out vec4 fragColor;

            void main() {
                float l = length(uv * 2.0 - vec2(1.0));
                if (l > 1.0) discard;
                fragColor = vec4(0.1);
            }
            """,
        )

        # A program tranforming points being affected by a gravity point
        self.gravity_program = self.ctx.program(vertex_shader="""
            #version 330

            // Delta time (since last frame)
            uniform float dt;
            // Strength of gravity
            uniform float force;
            // Position of gravity
            uniform vec2 gravity_pos;

            // The format of the data in our tranform buffer(s)
            in vec2 in_pos;
            in vec2 in_vel;

            // We are writing to a buffer of the same format
            out vec2 out_pos;
            out vec2 out_vel;

            void main() {
                // Simplified gravity calculations
                vec2 dir = normalize(gravity_pos - in_pos) * force;
                vec2 vel = in_vel + dir / length(dir) * 1.0;

                // Write to the output buffer
                out_vel = vel;
                out_pos = in_pos + vel * dt;
            }
            """, )
        N = 10_000
        # Make two buffers we tranform between so we can work on the previous result
        self.buffer_1 = self.ctx.buffer(
            data=array('f', self.gen_initial_data(N)))
        self.buffer_2 = self.ctx.buffer(reserve=self.buffer_1.size)

        # We also need to be able to visualize both versions (draw to the screen)
        self.vao_1 = self.ctx.geometry(
            [BufferDescription(self.buffer_1, '2f 2x4', ['in_pos'])])
        self.vao_2 = self.ctx.geometry(
            [BufferDescription(self.buffer_2, '2f 2x4', ['in_pos'])])

        # We need to be able to tranform both buffers (ping-pong)
        self.gravity_1 = self.ctx.geometry(
            [BufferDescription(self.buffer_1, '2f 2f', ['in_pos', 'in_vel'])])
        self.gravity_2 = self.ctx.geometry(
            [BufferDescription(self.buffer_2, '2f 2f', ['in_pos', 'in_vel'])])

        # Set up blending states
        self.ctx.enable_only(self.ctx.BLEND)
        self.ctx.blend_func = self.ctx.BLEND_ADDITIVE

        self.mouse_pos = SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2
        self.on_resize(*self.get_framebuffer_size())
        self.time = time.time()
Beispiel #9
0
    def __init__(self, width, height, title):
        """
        Set up the application.
        """
        self.time = 0
        super().__init__(width, height, title, resizable=True)
        self.program = self.ctx.program(
            vertex_shader="""
            #version 330
            in vec2 in_vert;
            void main() {
                gl_Position = vec4(in_vert, 0.0, 1.0);
            }
            """,
            geometry_shader="""
            #version 330

            layout (points) in;
            // Emit 4 vertices per point (Makes two triangles with a triangle strip)
            layout (triangle_strip, max_vertices = 4) out;

            uniform float time;
            out vec3 gs_color;

            void main() {
                // Get the position emitted from the vertex shader
                // We get the 0th element because point primitives only have 1 position.
                vec4 pos = gl_in[0].gl_Position;
                float offset = 0.02 + sin(time * 5.0 + gl_PrimitiveIDIn) / 200.0;

                float rot = time + length(pos) * 10.0;
                mat2 rotate = mat2(
                    cos(rot), -sin(rot),
                    sin(rot),  cos(rot)
                );
                vec3 color = vec3(
                    (sin(time + gl_PrimitiveIDIn) + 1.0) / 2.0,
                    (sin(time + 2 + gl_PrimitiveIDIn) + 1.0) / 2.0,
                    (sin(time + 3 + gl_PrimitiveIDIn) + 1.0) / 2.0
                );
                // Emit 4 vertices around the original vertex position making a quad
                gl_Position = pos + vec4(rotate * vec2(-offset, offset), 0.0, 0.0);
                gs_color = color;
                EmitVertex();

                gl_Position = pos + vec4(rotate * vec2(-offset, -offset), 0.0, 0.0);
                gs_color = color;
                EmitVertex();

                gl_Position = pos + vec4(rotate * vec2(offset, offset), 0.0, 0.0);
                gs_color = color;
                EmitVertex();

                gl_Position = pos + vec4(rotate * vec2(offset, -offset), 0.0, 0.0);
                gs_color = color;
                EmitVertex();

                // Done with the primitive
                EndPrimitive();
            }
            """,
            fragment_shader="""
            #version 330
            out vec4 out_color;
            in vec3 gs_color;
            void main() {
                out_color = vec4(gs_color, 1.0);
            }
            """,
        )
        num_points = 1000
        self.points = self.ctx.geometry([
            BufferDescription(
                self.ctx.buffer(data=array(
                    'f',
                    [random.uniform(-1.0, 1.0)
                     for _ in range(num_points * 2)])),
                '2f',
                ['in_vert'],
            )
        ])
    def __init__(self, width, height, title):
        super().__init__(width, height, title, resizable=True)
        self.time = 0

        # Program to visualize the points
        self.points_progran = self.ctx.program(
            vertex_shader="""
            #version 330
            in vec2 in_pos;
            out vec3 color;
            void main() {
                // Let's just give them a "random" color based on the vertex id
                color = vec3(
                    mod((gl_VertexID * 100 % 11) / 10.0, 1.0),
                    mod((gl_VertexID * 100 % 27) / 10.0, 1.0),
                    mod((gl_VertexID * 100 % 71) / 10.0, 1.0));
                // Pass the point position to primitive assembly
                gl_Position = vec4(in_pos, 0.0, 1.0);
            }
            """,
            fragment_shader="""
            #version 330

            // Color passed in from the vertex shader
            in vec3 color;
            // The pixel we are writing to in the framebuffer
            out vec4 fragColor;

            void main() {
                // Fill the point
                fragColor = vec4(color, 1.0);
            }
            """,
        )

        # A program tranforming points being affected by a gravity point
        self.gravity_program = self.ctx.program(vertex_shader="""
            #version 330

            // Delta time (since last frame)
            uniform float dt;
            // Strength of gravity
            uniform float force;
            // Position of gravity
            uniform vec2 gravity_pos;

            // The format of the data in our tranform buffer(s)
            in vec2 in_pos;
            in vec2 in_vel;

            // We are writing to a buffer of the same format
            out vec2 out_pos;
            out vec2 out_vel;

            void main() {
                // Simplified gravity calculations
                vec2 dir = normalize(gravity_pos - in_pos) * force;
                vec2 vel = in_vel + dir / length(dir) * 0.01;

                // Write to the output buffer
                out_vel = vel;
                out_pos = in_pos + vel * dt;
            }
            """, )
        N = 50_000
        # Make two buffers we tranform between so we can work on the previous result
        self.buffer_1 = self.ctx.buffer(
            data=array('f', self.gen_initial_data(N)))
        self.buffer_2 = self.ctx.buffer(reserve=self.buffer_1.size)

        # We also need to be able to visualize both versions (draw to the screen)
        self.vao_1 = self.ctx.geometry(
            [BufferDescription(self.buffer_1, '2f 2x4', ['in_pos'])])
        self.vao_2 = self.ctx.geometry(
            [BufferDescription(self.buffer_2, '2f 2x4', ['in_pos'])])

        # We need to be able to tranform both buffers (ping-pong)
        self.gravity_1 = self.ctx.geometry(
            [BufferDescription(self.buffer_1, '2f 2f', ['in_pos', 'in_vel'])])
        self.gravity_2 = self.ctx.geometry(
            [BufferDescription(self.buffer_2, '2f 2f', ['in_pos', 'in_vel'])])

        self.ctx.enable_only()  # Ensure no context flags are set
        self.time = time.time()
    def __init__(self, width, height, title):
        super().__init__(width, height, title)
        self.program = self.ctx.program(vertex_shader="""
            #version 330

            in vec2 in_position;
            in vec3 in_color;

            out vec3 v_color;

            void main() {
                gl_Position = vec4(in_position, 0.0, 1.0);
                v_color = in_color;
            }
            """,
                                        fragment_shader="""
            #version 330

            out vec4 out_color;
            in vec3 v_color;

            void main() {
                out_color = vec4(v_color, 1.0);
            }
            """)

        # Vertices
        self.vertex_buffer = self.ctx.buffer(data=array(
            'f',
            [
                # x  y    r    g    b
                -1.0,
                -1.0,
                1.0,
                0.0,
                0.0,  # lower left
                1,
                -1.0,
                0.0,
                1.0,
                0.0,  # lower right
                1.0,
                1.0,
                0.0,
                0.0,
                1.0,  # upper right
                -1.0,
                1.0,
                0.0,
                1.0,
                1.0,  # upper left
                0,
                0,
                0,
                0,
                0,  # dummy data for testing
            ]))
        self.ibo_8 = self.ctx.buffer(data=array('B', [3, 0, 2, 1]))
        self.ibo_16 = self.ctx.buffer(data=array('H', [3, 0, 2, 1]))
        self.ibo_32 = self.ctx.buffer(data=array('I', [3, 0, 2, 1]))

        self.vao_32 = self.ctx.geometry([
            BufferDescription(self.vertex_buffer, "2f 3f",
                              ["in_position", "in_color"]),
        ],
                                        index_buffer=self.ibo_32,
                                        index_element_size=4,
                                        mode=self.ctx.TRIANGLE_STRIP)
        self.vao_16 = self.ctx.geometry([
            BufferDescription(self.vertex_buffer, "2f 3f",
                              ["in_position", "in_color"]),
        ],
                                        index_buffer=self.ibo_16,
                                        index_element_size=2,
                                        mode=self.ctx.TRIANGLE_STRIP)
        self.vao_8 = self.ctx.geometry([
            BufferDescription(self.vertex_buffer, "2f 3f",
                              ["in_position", "in_color"]),
        ],
                                       index_buffer=self.ibo_16,
                                       index_element_size=2,
                                       mode=self.ctx.TRIANGLE_STRIP)
        self.frames = 0
Beispiel #12
0
def cube(size=(1.0, 1.0, 1.0), center=(0.0, 0.0, 0.0)) -> Geometry:
    """Creates a cube with normals and texture coordinates.

    :param tuple size: size of the cube as a 3-component tuple
    :param tuple center: center of the cube as a 3-component tuple
    :rtype: arcade.gl.Geometry
    :returns: A cube
    """
    ctx = _get_active_context()
    width, height, depth = size
    width, height, depth = width / 2.0, height / 2.0, depth / 2.0

    pos = array('f', [
        center[0] + width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] + height,
        center[2] + depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] + height,
        center[2] + depth,
        center[0] - width,
        center[1] + height,
        center[2] + depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] - height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] - depth,
        center[0] + width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] + height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] + depth,
        center[0] + width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] - height,
        center[2] - depth,
        center[0] + width,
        center[1] - height,
        center[2] + depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] + width,
        center[1] - height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] - width,
        center[1] - height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] - width,
        center[1] + height,
        center[2] + depth,
        center[0] - width,
        center[1] + height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] + depth,
        center[0] - width,
        center[1] + height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] - depth,
        center[0] + width,
        center[1] - height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] - depth,
        center[0] - width,
        center[1] - height,
        center[2] - depth,
        center[0] - width,
        center[1] + height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] - depth,
        center[0] - width,
        center[1] + height,
        center[2] - depth,
        center[0] + width,
        center[1] + height,
        center[2] + depth,
        center[0] - width,
        center[1] + height,
        center[2] - depth,
        center[0] - width,
        center[1] + height,
        center[2] + depth,
        center[0] + width,
        center[1] + height,
        center[2] + depth,
    ])

    normal = array('f', [
        -0,
        0,
        1,
        -0,
        0,
        1,
        -0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        -1,
        -0,
        0,
        -1,
        -0,
        0,
        -1,
        -0,
        0,
        -1,
        -0,
        0,
        -1,
        -0,
        0,
        -1,
        -0,
        0,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        0,
        -1,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
    ])

    uv = array('f', [
        1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
        1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1,
        1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0
    ])

    return ctx.geometry([
        BufferDescription(ctx.buffer(data=pos), '3f', ['in_position']),
        BufferDescription(ctx.buffer(data=normal), '3f', ['in_normal']),
        BufferDescription(ctx.buffer(data=uv), '2f', ['in_uv']),
    ])
Beispiel #13
0
    def __init__(self, width, height, title):
        """
        Set up the application.
        """
        self.time = 0
        super().__init__(width, height, title)
        self.program = self.ctx.program(vertex_shader="""
            #version 330

            uniform float time;

            in vec2 in_vert;
            // Per instance data
            in vec2 in_offset;
            in vec4 in_color;

            out vec4 v_color;

            void main() {
                // Create rotation based on what instance we are drawing
                float angle = time * 0.5 + gl_InstanceID;
                mat2 rot = mat2(
                    cos(angle), sin(angle),
                    -sin(angle), cos(angle)
                );

                // scale down triangle, offset and rotate
                vec2 pos = (rot * (in_vert * 0.07)) + in_offset;

                gl_Position = vec4(pos, 0.0, 1.0);
                v_color = in_color;
            }
            """,
                                        fragment_shader="""
            #version 330

            in vec4 v_color;
            out vec4 out_color;

            void main() {
                out_color = v_color;
            }
            """)

        self.instances = 1_000
        # Create triangle
        vertices = array(
            "f",
            [
                # x, y
                0.0,
                0.8,
                -0.8,
                -0.8,
                0.8,
                -0.8,
            ])

        # Generat per instance data. We'll create a generator function for this (less messy)
        def gen_instance_data(instances):
            random.seed(123456)
            for _ in range(instances):
                # random x and y
                yield random.uniform(-1.0, 1.0)
                yield random.uniform(-1.0, 1.0)
                # random rgba color
                yield random.uniform(0.1, 1.0)
                yield random.uniform(0.1, 1.0)
                yield random.uniform(0.1, 1.0)
                yield random.uniform(0.1, 1.0)

        per_instance = array("f", gen_instance_data(self.instances))

        self.geometry = self.ctx.geometry(
            [
                # Base geometry
                BufferDescription(
                    self.ctx.buffer(data=vertices),
                    '2f',
                    ['in_vert'],
                ),
                # Per instance buffer
                BufferDescription(
                    self.ctx.buffer(data=per_instance),
                    '2f 4f',
                    ['in_offset', 'in_color'],
                    instanced=True,
                ),
            ],
            mode=self.ctx.TRIANGLES)