Beispiel #1
0
    def __init__(self, use_spatial_hash=True, spatial_hash_cell_size=128, is_static=False, use_lights=False):
        """
        Initialize the sprite list
        """
        # List of sprites in the sprite list
        self.sprite_list = []
        self.sprite_idx = dict()

        # Used in drawing optimization via OpenGL
        if use_lights:
            fragment_shader = FRAGMENT_SHADER_LIGHT
        else:
            fragment_shader = FRAGMENT_SHADER

        self.program = shader.program(
            vertex_shader=VERTEX_SHADER,
            fragment_shader=fragment_shader
        )
        self.sprite_data = None
        self.sprite_data_buf = None
        self.texture_id = None
        self.texture = None
        self.vao = None
        self.vbo_buf = None

        self.array_of_texture_names = []
        self.array_of_images = []

        self.light_list = None
        self.ambient_light = (255, 255, 255)

        # Used in collision detection optimization
        self.spatial_hash = SpatialHash(cell_size=spatial_hash_cell_size)
        self.use_spatial_hash = use_spatial_hash
        self.is_static = is_static
Beispiel #2
0
    def draw(self):
        """ Draw this list of sprites. """
        if self.program is None:
            # Used in drawing optimization via OpenGL
            self.program = shader.program(vertex_shader=VERTEX_SHADER,
                                          fragment_shader=FRAGMENT_SHADER)

        if len(self.sprite_list) == 0:
            return

        if self.vao is None:
            self._calculate_sprite_buffer()

        self._texture.use(0)

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)

        with self.vao:
            self.program['Texture'] = self.texture_id
            self.program['Projection'] = get_projection().flatten()

            if not self.is_static:
                self.sprite_data_buf.write(self.sprite_data.tobytes())

            self.vao.render(gl.GL_TRIANGLE_STRIP,
                            instances=len(self.sprite_list))

            if not self.is_static:
                self.sprite_data_buf.orphan()
Beispiel #3
0
def create_line(start_x: float,
                start_y: float,
                end_x: float,
                end_y: float,
                color: Color,
                line_width: float = 1) -> Shape:
    """
    Create a line to be rendered later. This works faster than draw_line because
    the vertexes are only loaded to the graphics card once, rather than each frame.
    """

    program = shader.program(
        vertex_shader='''
            #version 330
            uniform mat4 Projection;
            in vec2 in_vert;
            in vec4 in_color;
            out vec4 v_color;
            void main() {
               gl_Position = Projection * vec4(in_vert, 0.0, 1.0);
               v_color = in_color;
            }
        ''',
        fragment_shader='''
            #version 330
            in vec4 v_color;
            out vec4 f_color;
            void main() {
                f_color = v_color;
            }
        ''',
    )

    buffer_type = np.dtype([('vertex', '2f4'), ('color', '4B')])
    data = np.zeros(2, dtype=buffer_type)
    data['vertex'] = (start_x, start_y), (end_x, end_y)
    data['color'] = get_four_byte_color(color)

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

    vao = shader.vertex_array(program, vao_content)
    with vao:
        program['Projection'] = get_projection().flatten()

    shape = Shape()
    shape.vao = vao
    shape.vbo = vbo
    shape.program = program
    shape.mode = gl.GL_LINE_STRIP
    shape.line_width = line_width

    return shape
Beispiel #4
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.
    """
    program = shader.program(
        vertex_shader='''
            #version 330
            uniform mat4 Projection;
            in vec2 in_vert;
            in vec4 in_color;
            out vec4 v_color;
            void main() {
               gl_Position = Projection * vec4(in_vert, 0.0, 1.0);
               v_color = in_color;
            }
        ''',
        fragment_shader='''
            #version 330
            in vec4 v_color;
            out vec4 f_color;
            void main() {
                f_color = v_color;
            }
        ''',
    )

    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 = shader.buffer(data.tobytes())
    vao_content = [
        shader.BufferDescription(
            vbo,
            '2f 4B',
            ('in_vert', 'in_color'),
            normalized=['in_color']
        )
    ]

    vao = shader.vertex_array(program, vao_content)
    with vao:
        program['Projection'] = get_projection().flatten()

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

    return shape
Beispiel #5
0
def _generic_draw_line_strip(point_list: PointList,
                             color: Color,
                             line_width: float=1,
                             mode: int=moderngl.LINE_STRIP):
    """
    Draw a line strip. A line strip is a set of continuously connected
    line segments.

    Args:
        :point_list: List of points making up the line. Each point is
         in a list. So it is a list of lists.
        :color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
        :border_width: Width of the line in pixels.
    Returns:
        None
    Raises:
        None
    """
    program = shader.program(
        vertex_shader=line_vertex_shader,
        fragment_shader=line_fragment_shader,
    )
    buffer_type = np.dtype([('vertex', '2f4'), ('color', '4B')])
    data = np.zeros(len(point_list), dtype=buffer_type)

    data['vertex'] = point_list

    color = get_four_byte_color(color)
    data['color'] = color

    vbo = shader.buffer(data.tobytes())
    vbo_desc = shader.BufferDescription(
        vbo,
        '2f 4B',
        ('in_vert', 'in_color'),
        normalized=['in_color']
    )

    vao_content = [vbo_desc]

    vao = shader.vertex_array(program, vao_content)
    with vao:
        program['Projection'] = get_projection().flatten()

        gl.glLineWidth(line_width)
        gl.glPointSize(line_width)

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glEnable(gl.GL_LINE_SMOOTH)
        gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
        gl.glHint(gl.GL_POLYGON_SMOOTH_HINT, gl.GL_NICEST)

        vao.render(mode=mode)
Beispiel #6
0
def _generic_draw_line_strip(point_list: PointList,
                             color: Color,
                             mode: int = gl.GL_LINE_STRIP):
    """
    Draw a line strip. A line strip is a set of continuously connected
    line segments.

    :param point_list: List of points making up the line. Each point is
         in a list. So it is a list of lists.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    """
    # Cache the program. But not on linux because it fails unit tests for some reason.
    # if not _generic_draw_line_strip.program or sys.platform == "linux":

    _generic_draw_line_strip.program = shader.program(
        vertex_shader=_line_vertex_shader,
        fragment_shader=_line_fragment_shader,
    )

    c4 = get_four_byte_color(color)
    c4e = c4 * len(point_list)
    a = array.array('B', c4e)
    color_buf = shader.buffer(a.tobytes())
    color_buf_desc = shader.BufferDescription(
        color_buf,
        '4B',
        ['in_color'],
        normalized=['in_color'],
    )

    def gen_flatten(my_list):
        return [item for sublist in my_list for item in sublist]

    vertices = array.array('f', gen_flatten(point_list))

    vbo_buf = shader.buffer(vertices.tobytes())
    vbo_buf_desc = shader.BufferDescription(vbo_buf, '2f', ['in_vert'])

    vao_content = [vbo_buf_desc, color_buf_desc]

    vao = shader.vertex_array(_generic_draw_line_strip.program, vao_content)
    with vao:
        _generic_draw_line_strip.program['Projection'] = get_projection(
        ).flatten()
        vao.render(mode=mode)
Beispiel #7
0
    def __init__(self):
        """
        Initialize the sprite list
        """
        # List of sprites in the sprite list
        self.shape_list = []
        self.change_x = 0
        self.change_y = 0
        self._center_x = 0
        self._center_y = 0
        self._angle = 0
        self.program = shader.program(
            vertex_shader='''
                #version 330
                uniform mat4 Projection;
                uniform vec2 Position;
                uniform float Angle;

                in vec2 in_vert;
                in vec4 in_color;

                out vec4 v_color;
                void main() {
                    float angle = radians(Angle);
                    mat2 rotate = mat2(
                        cos(angle), sin(angle),
                        -sin(angle), cos(angle)
                    );
                   gl_Position = Projection * vec4(Position + (rotate * in_vert), 0.0, 1.0);
                   v_color = in_color;
                }
            ''',
            fragment_shader='''
                #version 330
                in vec4 v_color;
                out vec4 f_color;
                void main() {
                    f_color = v_color;
                }
            ''',
        )
        # Could do much better using just one vbo and glDrawElementsBaseVertex
        self.batches = defaultdict(_Batch)
        self.dirties = set()
Beispiel #8
0
def _generic_draw_line_strip(point_list: PointList,
                             color: Color,
                             mode: int = gl.GL_LINE_STRIP):
    """
    Draw a line strip. A line strip is a set of continuously connected
    line segments.

    :param point_list: List of points making up the line. Each point is
         in a list. So it is a list of lists.
    :param Color color: color, specified in a list of 3 or 4 bytes in RGB or
         RGBA format.
    """
    program = shader.program(
        vertex_shader=line_vertex_shader,
        fragment_shader=line_fragment_shader,
    )
    buffer_type = np.dtype([('vertex', '2f4'), ('color', '4B')])
    data = np.zeros(len(point_list), dtype=buffer_type)

    data['vertex'] = point_list

    color = get_four_byte_color(color)
    data['color'] = color

    vbo = shader.buffer(data.tobytes())
    vbo_desc = shader.BufferDescription(
        vbo,
        '2f 4B',
        ('in_vert', 'in_color'),
        normalized=['in_color']
    )

    vao_content = [vbo_desc]

    vao = shader.vertex_array(program, vao_content)
    with vao:
        program['Projection'] = get_projection().flatten()

        vao.render(mode=mode)
Beispiel #9
0
    def __init__(self):
        self.vao = None
        self._queue = deque()
        self._layers = deque()
        self.sprite_data_buf = None
        self.texture_id = None
        self._texture = None
        self.program = shader.program(vertex_shader=VERTEX_SHADER,
                                      fragment_shader=FRAGMENT_SHADER)

        self.array_of_texture_names = []
        self.array_of_images = []
        self.array_of_layers = []
        self.is_static = False
        self.vertices = np.array(
            [
                #  x,    y,   u,   v in GL Triangle Strip Mode
                -1.0,
                -1.0,
                0.0,
                0.0,
                -1.0,
                1.0,
                0.0,
                1.0,
                1.0,
                -1.0,
                1.0,
                0.0,
                1.0,
                1.0,
                1.0,
                1.0,
            ],
            dtype=np.float32)
        self.ended = False
        self.times = []
Beispiel #10
0
    def draw(self, **kwargs):
        """
        Draw this list of sprites.

        :param filter: Optional parameter to set OpenGL filter, such as
                       `gl.GL_NEAREST` to avoid smoothing.
        """
        if self.program is None:
            # Used in drawing optimization via OpenGL
            self.program = shader.program(vertex_shader=_VERTEX_SHADER,
                                          fragment_shader=_FRAGMENT_SHADER)

        if len(self.sprite_list) == 0:
            return

        if self._vao1 is None:
            self._calculate_sprite_buffer()

        self._texture.use(0)

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        if "filter" in kwargs:
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                               kwargs["filter"])
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                               kwargs["filter"])
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)

        with self._vao1:
            self.program['Texture'] = self.texture_id
            self.program['Projection'] = get_projection().flatten()
            texture_transform = None
            if len(self.sprite_list) > 0:
                # always wrap texture transformations with translations
                # so that rotate and resize operations act on the texture
                # center by default
                texture_transform = Matrix3x3().translate(-0.5, -0.5).multiply(
                    self.sprite_list[0].texture_transform.v).multiply(
                        Matrix3x3().translate(0.5, 0.5).v)
            if texture_transform == None:
                texture_transform = Matrix3x3()
            self.program['TextureTransform'] = texture_transform.v

            if not self.is_static:
                if self._sprite_pos_changed:
                    self._sprite_pos_buf.orphan()
                    self._sprite_pos_buf.write(self._sprite_pos_data.tobytes())
                    self._sprite_pos_changed = False

                if self._sprite_size_changed:
                    self._sprite_size_buf.orphan()
                    self._sprite_size_buf.write(
                        self._sprite_size_data.tobytes())
                    self._sprite_size_changed = False

                if self._sprite_angle_changed:
                    self._sprite_angle_buf.orphan()
                    self._sprite_angle_buf.write(
                        self._sprite_angle_data.tobytes())
                    self._sprite_angle_changed = False

                if self._sprite_color_changed:
                    self._sprite_color_buf.orphan()
                    self._sprite_color_buf.write(
                        self._sprite_color_data.tobytes())
                    self._sprite_color_changed = False

                if self._sprite_sub_tex_changed:
                    self._sprite_sub_tex_buf.orphan()
                    self._sprite_sub_tex_buf.write(
                        self._sprite_sub_tex_data.tobytes())
                    self._sprite_sub_tex_changed = False

            self._vao1.render(gl.GL_TRIANGLE_STRIP,
                              instances=len(self.sprite_list))
Beispiel #11
0
    def draw(self, **kwargs):
        """
        Draw this list of sprites.

        :param filter: Optional parameter to set OpenGL filter, such as
                       `gl.GL_NEAREST` to avoid smoothing.
        """
        if self.program is None:
            # Used in drawing optimization via OpenGL
            self.program = shader.program(vertex_shader=_VERTEX_SHADER,
                                          fragment_shader=_FRAGMENT_SHADER)

        if len(self.sprite_list) == 0:
            return

        if self._vao1 is None:
            self._calculate_sprite_buffer()

        self._texture.use(0)

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        if "filter" in kwargs:
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                               kwargs["filter"])
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                               kwargs["filter"])
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
        # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)

        with self._vao1:
            self.program['Texture'] = self.texture_id
            self.program['Projection'] = get_projection().flatten()

            if not self.is_static:
                if self._sprite_pos_changed:
                    self._sprite_pos_buf.orphan()
                    self._sprite_pos_buf.write(self._sprite_pos_data.tobytes())
                    self._sprite_pos_changed = False

                if self._sprite_size_changed:
                    self._sprite_size_buf.orphan()
                    self._sprite_size_buf.write(
                        self._sprite_size_data.tobytes())
                    self._sprite_size_changed = False

                if self._sprite_angle_changed:
                    self._sprite_angle_buf.orphan()
                    self._sprite_angle_buf.write(
                        self._sprite_angle_data.tobytes())
                    self._sprite_angle_changed = False

                if self._sprite_color_changed:
                    self._sprite_color_buf.orphan()
                    self._sprite_color_buf.write(
                        self._sprite_color_data.tobytes())
                    self._sprite_color_changed = False

                if self._sprite_sub_tex_changed:
                    self._sprite_sub_tex_buf.orphan()
                    self._sprite_sub_tex_buf.write(
                        self._sprite_sub_tex_data.tobytes())
                    self._sprite_sub_tex_changed = False

            self._vao1.render(gl.GL_TRIANGLE_STRIP,
                              instances=len(self.sprite_list))
Beispiel #12
0
 def setup_shader_program_if_needed(self):
     if self.program is None:
         self.program = shader.program(vertex_shader=VERTEX_SHADER,
                                       fragment_shader=FRAGMENT_SHADER)
Beispiel #13
0
 def get_program():
     if GLShader._PROGRAM is None:
         GLShader._PROGRAM = shader.program(vertex_shader=VERTEX_SHADER,
                                            fragment_shader=FRAGMENT_SHADER)
     return GLShader._PROGRAM