Example #1
0
    def vertex_attrib(self, name, data, size=2, stride=0, offset=0):
        """
        Set vertex attribute data in a shader, lacks the flexibility of
        setting several attributes in one vertex buffer.

        Parameters
        ----------

        name: the attribute name in the shader.

        data: a list of vertex attributes (positions, colors, ...)

        Example: name = "positions", data = [0, 0, 0, 1, 1, 0, 1, 1].
        """
        data_ctype = (gl.GLfloat * len(data))(*data)

        vbo_id = gl.GLuint(0)
        gl.glGenBuffers(1, ct.byref(vbo_id))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
        gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_ctype), data_ctype,
                        gl.GL_STATIC_DRAW)

        location = gl.glGetAttribLocation(self.program, name.encode("ascii"))
        gl.glEnableVertexAttribArray(location)
        gl.glVertexAttribPointer(location, size, gl.GL_FLOAT, gl.GL_FALSE,
                                 stride, ct.c_void_p(offset))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
        return vbo_id
Example #2
0
    def __init__(self, **args):
        super(Window, self).__init__(**args)

        self.vao = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vao))
        gl.glBindVertexArray(self.vao)

        self.vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo)

        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(vertex_positions)),
                        (gl.GLfloat *
                         len(vertex_positions))(*vertex_positions),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        self.ibo = gl.GLuint(0)
        gl.glGenBuffers(1, self.ibo)
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)

        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * len(indices)),
                        (gl.GLuint * len(indices))(*indices),
                        gl.GL_STATIC_DRAW)
Example #3
0
    def set_vertex_attrib(self, name, data):
        '''
        this is an ugly way to set vertex attribute data in a shader.
        lacks the flexibility of setting several attributes in one vertex buffer.

        name: the attribute name in the shader.
        data: a list of vertex attributes (positions, colors, texcoords, normals,...)

        example:
        name = 'positions'
        data = [(1, 1, 0), (2, 2, 1), ...]

        the items in data must all be 1D lists(or tuples) of the same length.
        '''
        data_flatten = [x for vertex in data for x in vertex]
        size = len(data[0])
        data_ctype = (gl.GLfloat * len(data_flatten))(*data_flatten)

        vbo_id = gl.GLuint(0)
        gl.glGenBuffers(1, ct.byref(vbo_id))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
        gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_ctype), data_ctype, gl.GL_STATIC_DRAW)

        location = gl.glGetAttribLocation(self.program, name.encode('ascii'))
        gl.glEnableVertexAttribArray(location)
        gl.glVertexAttribPointer(location, size, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
        return vbo_id
def setup_copy_vertexbuffer():
    '''
    Create the vertexbuffer object for the copying program
    '''
    # gl.glGenVertexArrays(1, ctypes.byref(copy_vao))
    gl.glGenBuffers(1, ctypes.byref(copy_vertexbuffer))

    loc_position = gl.glGetAttribLocation(copy_program, ctypes.create_string_buffer(b'position'))
    loc_texcoord = gl.glGetAttribLocation(copy_program, ctypes.create_string_buffer(b'texcoord'))

    if loc_position < 0:
        print('Warning: position is not used in the shader')
    if loc_texcoord < 0:
        print('Warning: texcoord is not used in the shader')

    gl.glBindVertexArray(copy_vao)

    gl.glEnableVertexAttribArray(loc_position)
    gl.glEnableVertexAttribArray(loc_texcoord)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, copy_vertexbuffer)

    gl.glVertexAttribPointer(loc_position, 2, gl.GL_FLOAT, False, ctypes.sizeof(TEXTURE_VERTEX), ctypes.c_void_p(TEXTURE_VERTEX.position.offset))
    gl.glVertexAttribPointer(loc_texcoord, 2, gl.GL_FLOAT, False, ctypes.sizeof(TEXTURE_VERTEX), ctypes.c_void_p(TEXTURE_VERTEX.texcoord.offset))

    gl.glBindVertexArray(0)
Example #5
0
def setup_render_vertexbuffer():
    '''
	Create the vertexbuffer object for the rendering program
	'''
    gl.glGenVertexArrays(1, ctypes.byref(render_vao))
    gl.glGenBuffers(1, ctypes.byref(render_vertexbuffer))

    loc_position = gl.glGetAttribLocation(
        render_program, ctypes.create_string_buffer(b'position'))
    loc_color = gl.glGetAttribLocation(render_program,
                                       ctypes.create_string_buffer(b'color'))

    if loc_position < 0:
        print('Warning: position is not used in the shader')
    if loc_color < 0:
        print('Warning: color is not used in the shader')

    gl.glBindVertexArray(render_vao)

    gl.glEnableVertexAttribArray(loc_position)
    gl.glEnableVertexAttribArray(loc_color)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, render_vertexbuffer)

    gl.glVertexAttribPointer(loc_position, 2, gl.GL_FLOAT, False,
                             ctypes.sizeof(COLOR_VERTEX),
                             ctypes.c_void_p(COLOR_VERTEX.position.offset))
    gl.glVertexAttribPointer(loc_color, 4, gl.GL_FLOAT, False,
                             ctypes.sizeof(COLOR_VERTEX),
                             ctypes.c_void_p(COLOR_VERTEX.color.offset))

    gl.glBindVertexArray(0)
Example #6
0
def setup_copy_vertexbuffer():
    '''
	Create the vertexbuffer object for the copying program
	'''
    # gl.glGenVertexArrays(1, ctypes.byref(copy_vao))
    gl.glGenBuffers(1, ctypes.byref(copy_vertexbuffer))

    loc_position = gl.glGetAttribLocation(
        copy_program, ctypes.create_string_buffer(b'position'))
    loc_texcoord = gl.glGetAttribLocation(
        copy_program, ctypes.create_string_buffer(b'texcoord'))

    if loc_position < 0:
        print('Warning: position is not used in the shader')
    if loc_texcoord < 0:
        print('Warning: texcoord is not used in the shader')

    gl.glBindVertexArray(copy_vao)

    gl.glEnableVertexAttribArray(loc_position)
    gl.glEnableVertexAttribArray(loc_texcoord)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, copy_vertexbuffer)

    gl.glVertexAttribPointer(loc_position, 2, gl.GL_FLOAT, False,
                             ctypes.sizeof(TEXTURE_VERTEX),
                             ctypes.c_void_p(TEXTURE_VERTEX.position.offset))
    gl.glVertexAttribPointer(loc_texcoord, 2, gl.GL_FLOAT, False,
                             ctypes.sizeof(TEXTURE_VERTEX),
                             ctypes.c_void_p(TEXTURE_VERTEX.texcoord.offset))

    gl.glBindVertexArray(0)
def setup_render_vertexbuffer():
    '''
    Create the vertexbuffer object for the rendering program
    '''
    gl.glGenVertexArrays(1, ctypes.byref(render_vao))
    gl.glGenBuffers(1, ctypes.byref(render_vertexbuffer))

    loc_position = gl.glGetAttribLocation(render_program, ctypes.create_string_buffer(b'position'))
    loc_color = gl.glGetAttribLocation(render_program, ctypes.create_string_buffer(b'color'))

    if loc_position < 0:
        print('Warning: position is not used in the shader')
    if loc_color < 0:
        print('Warning: color is not used in the shader')


    gl.glBindVertexArray(render_vao)

    gl.glEnableVertexAttribArray(loc_position)
    gl.glEnableVertexAttribArray(loc_color)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, render_vertexbuffer)

    gl.glVertexAttribPointer(loc_position, 2, gl.GL_FLOAT, False, ctypes.sizeof(COLOR_VERTEX), ctypes.c_void_p(COLOR_VERTEX.position.offset))
    gl.glVertexAttribPointer(loc_color, 4, gl.GL_FLOAT, False, ctypes.sizeof(COLOR_VERTEX), ctypes.c_void_p(COLOR_VERTEX.color.offset))

    gl.glBindVertexArray(0)
Example #8
0
    def _enable_attrib(self, buf_desc: BufferDescription):
        buff = buf_desc.buffer
        stride = sum(attribsize for _, attribsize, _ in buf_desc.formats)

        if buf_desc.instanced:
            if self.num_vertices == -1:
                raise ShaderException(
                    "The first vertex attribute cannot be a per instance attribute."
                )
        else:
            self.num_vertices = max(self.num_vertices, buff.size // stride)
            # print(f"Number of vertices: {self.num_vertices}")

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buff.buffer_id)
        offset = 0
        for (size, attribsize,
             gl_type_enum), attrib in zip(buf_desc.formats,
                                          buf_desc.attributes):
            loc = gl.glGetAttribLocation(self.program, attrib.encode('utf-8'))
            if loc == -1:
                raise ShaderException(
                    f"Attribute {attrib} not found in shader program")
            normalized = gl.GL_TRUE if attrib in buf_desc.normalized else gl.GL_FALSE
            gl.glVertexAttribPointer(loc, size, gl_type_enum, normalized,
                                     stride, c_void_p(offset))
            # print(f"{attrib} of size {size} with stride {stride} and offset {offset}")
            if buf_desc.instanced:
                gl.glVertexAttribDivisor(loc, 1)
            offset += attribsize
            gl.glEnableVertexAttribArray(loc)
Example #9
0
    def draw(self, shader):
        attribute_table = shader.attribute_table

        self.indexed_vbo.bind()

        # Bind all attributes.
        location_list = []  # Used to disable all VertexAttribArrays.
        for name, vbo in self.vbo_array.items():
            vbo.bind()
            attribute_location = attribute_table[name]
            location_list.append(attribute_location)
            glEnableVertexAttribArray(attribute_location)
            # specify that the data for the attribute will be pulled from the buffer that is currently bound to
            # GL_ARRAY_BUFFER. (http://stackoverflow.com/questions/30016833/multiple-in-attributes-in-shader-opengl)
            glVertexAttribPointer(attribute_location, vbo.dimension,
                                  vbo.data_type, GL_FALSE, 0, 0)

        # Draw.
        # glDrawArrays(GL_TRIANGLES, 0, vbo.count)
        glDrawElements(GL_TRIANGLES, self.indexed_vbo.count,
                       self.indexed_vbo.data_type, 0)

        # Disable and unbind everything.
        for location in location_list:
            glDisableVertexAttribArray(location)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
Example #10
0
    def set_vertex_attrib(self, name, data):
        """This is an ugly way to set vertex attribute data in a shader, it lacks
        the flexibility of setting several attributes in one vertex buffer.

        name: the attribute name in the shader.
        data: a list of vertex attributes (positions, colors, texcoords, normals,...)
        example: name = 'positions', data = [(1, 1, 0), (2, 2, 1), ...]
        the items in data must all be 1D lists(or tuples) of the same length.
        """
        data_flatten = [x for vertex in data for x in vertex]
        size = len(data[0])
        data_ctype = (gl.GLfloat * len(data_flatten))(*data_flatten)

        vbo_id = gl.GLuint(0)
        gl.glGenBuffers(1, ct.byref(vbo_id))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
        gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_ctype), data_ctype,
                        gl.GL_STATIC_DRAW)

        location = gl.glGetAttribLocation(self.program, name.encode('ascii'))
        gl.glEnableVertexAttribArray(location)
        gl.glVertexAttribPointer(location, size, gl.GL_FLOAT, gl.GL_FALSE, 0,
                                 0)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
        return vbo_id
Example #11
0
def draw_lights(lights, shader, models):
    """


    Dependencies are location, rotation, scale, and model (optionally texture).

    Args:
        lights:
        shader:
        models:

    Returns:

    """
    attribute_location = shader.attribute_location
    location_location = attribute_location['location']

    for entity in lights:

        shader.load_uniform_matrix(entity.transformation, name='transform')

        model = models[entity.model]

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.indexed_vbo)

        glBindBuffer(GL_ARRAY_BUFFER, model.vbo_array['location'])
        glEnableVertexAttribArray(location_location)
        glVertexAttribPointer(location_location, 3, GL_FLOAT, GL_FALSE, 0, 0)

        glDrawElements(GL_TRIANGLES, model.indexed_vbo.count, GL_UNSIGNED_INT,
                       0)

    glDisableVertexAttribArray(location_location)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
    glBindBuffer(GL_ARRAY_BUFFER, 0)
Example #12
0
 def draw(self):
     """Draw the object to the display buffer"""
     from pyglet import gl
     gl.glUseProgram(self._program)
     for kind in ('fill', 'line'):
         if self._counts[kind] > 0:
             if kind == 'line':
                 if self._line_width <= 0.0:
                     continue
                 gl.glLineWidth(self._line_width)
                 if self._line_loop:
                     mode = gl.GL_LINE_LOOP
                 else:
                     mode = gl.GL_LINE_STRIP
                 cmd = partial(gl.glDrawArrays, mode, 0, self._counts[kind])
             else:
                 gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER,
                                 self._buffers[kind]['index'])
                 cmd = partial(gl.glDrawElements, gl.GL_TRIANGLES,
                               self._counts[kind], gl.GL_UNSIGNED_INT, 0)
             gl.glBindBuffer(gl.GL_ARRAY_BUFFER,
                             self._buffers[kind]['array'])
             loc_pos = gl.glGetAttribLocation(self._program, b'a_position')
             gl.glEnableVertexAttribArray(loc_pos)
             gl.glVertexAttribPointer(loc_pos, 2, gl.GL_FLOAT, gl.GL_FALSE,
                                      0, 0)
             loc_col = gl.glGetUniformLocation(self._program, b'u_color')
             gl.glUniform4f(loc_col, *self._colors[kind])
             cmd()
             # The following line is probably only necessary because
             # Pyglet makes some assumptions about the GL state that
             # it perhaps shouldn't. Without it, Text might not
             # render properly (see #252)
             gl.glDisableVertexAttribArray(loc_pos)
     gl.glUseProgram(0)
Example #13
0
 def draw(self):
     """Draw the object to the display buffer"""
     from pyglet import gl
     gl.glUseProgram(self._program)
     for kind in ('fill', 'line'):
         if self._counts[kind] > 0:
             if kind == 'line':
                 if self._line_width <= 0.0:
                     continue
                 gl.glLineWidth(self._line_width)
                 if self._line_loop:
                     mode = gl.GL_LINE_LOOP
                 else:
                     mode = gl.GL_LINE_STRIP
                 cmd = partial(gl.glDrawArrays, mode, 0, self._counts[kind])
             else:
                 gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER,
                                 self._buffers[kind]['index'])
                 cmd = partial(gl.glDrawElements, gl.GL_TRIANGLES,
                               self._counts[kind], gl.GL_UNSIGNED_INT, 0)
             gl.glBindBuffer(gl.GL_ARRAY_BUFFER,
                             self._buffers[kind]['array'])
             loc_pos = gl.glGetAttribLocation(self._program, b'a_position')
             gl.glEnableVertexAttribArray(loc_pos)
             gl.glVertexAttribPointer(loc_pos, 2, gl.GL_FLOAT, gl.GL_FALSE,
                                      0, 0)
             loc_col = gl.glGetUniformLocation(self._program, b'u_color')
             gl.glUniform4f(loc_col, *self._colors[kind])
             cmd()
             # The following line is probably only necessary because
             # Pyglet makes some assumptions about the GL state that
             # it perhaps shouldn't. Without it, Text might not
             # render properly (see #252)
             gl.glDisableVertexAttribArray(loc_pos)
     gl.glUseProgram(0)
Example #14
0
        def construct_vertex_buffer():
            # Crazy thought, instead of creating quads here, we can render points
            #   and use a geometry shader to create the quads.
            # Saves (width + height) * 2 * sizeof(float) bytes on vertices and completely
            #   elminiates indices.

            # Create vertex buffer.
            x_slice = y_slice = cell_size
            chunk_vertices = (gl.GLfloat * (num_vertices_x * num_vertices_y * 2))()
            for row in range(num_vertices_y):
                for col in range(num_vertices_x):
                    index = (row * num_vertices_x + col) * 2  # Convert to array space.
                    chunk_vertices[index:index + 2] = (
                        # Define the chunk by its center.
                        x_slice * float(col) - 0.5,
                        y_slice * float(row) - 0.5
                    )

            gl.glBufferData(
                gl.GL_ARRAY_BUFFER,
                sizeof(chunk_vertices),
                chunk_vertices,
                gl.GL_STATIC_DRAW
            )

            gl.glEnableVertexAttribArray(0)
            gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, False, 2 * sizeof(gl.GLfloat), 0)
Example #15
0
 def bind(self, location: int, shader: Shader):
     stride = self.stride * sizeof(GLfloat)
     offset = self.offset * sizeof(GLfloat)
     glEnableVertexAttribArray(location)
     glVertexAttribPointer(location, self.vertex_size, GL_FLOAT, GL_FALSE,
                           stride, offset)
     glBindAttribLocation(shader.handle, location,
                          bytes(self.name, "utf-8"))
Example #16
0
 def vertex_attrib_pointer(self, buffer, name, size, type=gl.GL_FLOAT, normalized=False, stride=0, offset=0):
     self.use()
     loc = gl.glGetAttribLocation(self.handle, ctypes.create_string_buffer(name))
     if loc < 0:
         logging.warning('Attribute {} is not in the shader.'.format(name))
         return
     gl.glEnableVertexAttribArray(loc)
     gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
     gl.glVertexAttribPointer(loc, size, type, normalized, stride, ctypes.c_void_p(offset))
Example #17
0
    def enable(self, index):
        glBindBuffer(VBO.TARGET, self.id)
        glEnableVertexAttribArray(index)

        # TODO(ted): Assuming data should not be normalized and without stride or a pointer
        normalized = GL_FALSE
        stride = 0
        pointer = 0
        glVertexAttribPointer(index, self.dimension, self.type, normalized,
                              stride, pointer)
Example #18
0
  def __set_attributes(self):
    if self.__vao is None:
      self.__vao = util.vertex_array()
    gl.glBindVertexArray(self.__vao.value)

    # coord
    coord_loc = gl.glGetAttribLocation(self.__prog.value, "coord")
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.__geom_buffer.value)
    gl.glVertexAttribPointer(coord_loc, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
    gl.glEnableVertexAttribArray(coord_loc)
    def __init__(self,
                 vertices: np.ndarray,
                 indices: np.ndarray,
                 mode=None,
                 texture=None):
        if mode is None:
            mode = gl.GL_TRIANGLES
        self.vertices = vertices
        self.indices = indices
        self.indices_size = indices.size
        self.mode = mode
        self.texture = texture

        self.vao = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vao))
        gl.glBindVertexArray(self.vao)

        self.vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo)
        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,  # target
            vertices.nbytes,  # size
            (gl.GLbyte * vertices.nbytes)(*vertices.tobytes()),  # data
            gl.GL_STATIC_DRAW,
        )  # usage

        self.ebo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.ebo))
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ebo)
        gl.glBufferData(
            gl.GL_ELEMENT_ARRAY_BUFFER,
            indices.nbytes,
            (gl.GLbyte * indices.nbytes)(*indices.tobytes()),
            gl.GL_STATIC_DRAW,
        )

        for ind, fld in enumerate(
                sorted([f for f in vertices.dtype.fields.items()],
                       key=lambda i: i[1][1])):
            gl.glVertexAttribPointer(
                ind,  # index
                vertices[0][fld[0]].size,  # size
                gl.GL_FLOAT,  # type
                gl.GL_FALSE,  # normalized
                vertices.itemsize,  # stride
                ctypes.c_void_p(fld[1][1]),
            )  # pointer
            gl.glEnableVertexAttribArray(ind)

        if texture is not None:
            texture_image = pyglet.image.load(texture)
            self.texture = texture_image.get_texture()

        gl.glBindVertexArray(0)
Example #20
0
 def bind_data(entity):
     glBindVertexArray(entity.asset.vertex_array_id)
     glBindBuffer(GL_ARRAY_BUFFER, entity.asset.vertex_buffer_id)
     for position, name, gl_type, size, stride, offset in entity.asset.attributes:
         glVertexAttribPointer(position, size, gl_type,
                               GL_FALSE, stride, offset)
         glEnableVertexAttribArray(position)
         glBindAttribLocation(entity.asset.shader.handle,
                              position, bytes(name, "utf-8"))
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
                  entity.asset.index_buffers[entity.asset.current_index_buffer_id].id)
Example #21
0
    def assign_vertex_attrib_location(self, vbo, location):
        """Load data into a vbo"""
        with vbo:
            if self.n_verts:
                assert vbo.ndarray.shape[0] == self.n_verts
            else:
                self.n_verts = vbo.ndarray.shape[0]

            # vbo.buffer_data()
            gl.glVertexAttribPointer(location, vbo.ndarray.shape[1], gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
            gl.glEnableVertexAttribArray(location)
Example #22
0
    def __init__(self, **args):
        super().__init__(**args)

        # create vertex array object

        self.vao = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vao))
        gl.glBindVertexArray(self.vao)

        # create vertex buffer object

        self.vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo)

        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(vertex_positions)),
                        (gl.GLfloat *
                         len(vertex_positions))(*vertex_positions),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        # create index buffer object

        self.ibo = gl.GLuint(0)
        gl.glGenBuffers(1, self.ibo)
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)

        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * len(indices)),
                        (gl.GLuint * len(indices))(*indices),
                        gl.GL_STATIC_DRAW)

        # create shader

        self.shader = shader.Shader("vert.glsl", "frag.glsl")
        self.shader_matrix_location = self.shader.find_uniform(
            b"matrix")  # get the shader matrix uniform location
        self.shader.use()

        # create matrices

        self.mv_matrix = matrix.Matrix()  # modelview
        self.p_matrix = matrix.Matrix()  # projection

        self.x = 0  # temporary variable
        pyglet.clock.schedule_interval(
            self.update,
            1.0 / 60)  # call update function every 60th of a second
Example #23
0
    def gen_vertices(self):
        # Just make a cube for now
        self.vertices = (GLfloat * 108)(*[
            -1.0, -1.0, -1.0,
            -1.0, -1.0, 1.0,
            -1.0, 1.0, 1.0,
            1.0, 1.0, -1.0,
            -1.0, -1.0, -1.0,
            -1.0, 1.0, -1.0,
            1.0, -1.0, 1.0,
            -1.0, -1.0, -1.0,
            1.0, -1.0, -1.0,
            1.0, 1.0, -1.0,
            1.0, -1.0, -1.0,
            -1.0, -1.0, -1.0,
            -1.0, -1.0, -1.0,
            -1.0, 1.0, 1.0,
            -1.0, 1.0, -1.0,
            1.0, -1.0, 1.0,
            -1.0, -1.0, 1.0,
            -1.0, -1.0, -1.0,
            -1.0, 1.0, 1.0,
            -1.0, -1.0, 1.0,
            1.0, -1.0, 1.0,
            1.0, 1.0, 1.0,
            1.0, -1.0, -1.0,
            1.0, 1.0, -1.0,
            1.0, -1.0, -1.0,
            1.0, 1.0, 1.0,
            1.0, -1.0, 1.0,
            1.0, 1.0, 1.0,
            1.0, 1.0, -1.0,
            -1.0, 1.0, -1.0,
            1.0, 1.0, 1.0,
            -1.0, 1.0, -1.0,
            -1.0, 1.0, 1.0,
            1.0, 1.0, 1.0,
            -1.0, 1.0, 1.0,
            1.0, -1.0, 1.0
        ])
        glGenVertexArrays(1, self.vao)
        glGenBuffers(1, self.vbo)

        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, sizeof(self.vertices), self.vertices, GL_STATIC_DRAW)

        glBindVertexArray(self.vao)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0)
        glEnableVertexAttribArray(0)
Example #24
0
    def set(self, source):
        """A.set(source)

        Set the given attribute's value using the source for data.
        """

        if 0 <= self.__gl_id <= _MAX_VERTEX_ATTRIB:

            gl.glEnableVertexAttribArray(self.__gl_id)
            gl.glVertexAttribPointer(
                self.__gl_id,
                self.components_per_vertex(),
                self.__gl_type.element_type_tag(),
                gl.GL_FALSE, 0,
                source)
Example #25
0
    def update_attribute(self, name, vbo_id):
        """Update the value of the given attribute.

        :param name: name of the attribute to be updated.
        :type name: str

        :param vbo_id: The id of the vertex buffer object that
            contains the data for the given attribute.
        :type vbo_id: int

        """
        attr = self._attributes[name]
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
        gl.glEnableVertexAttribArray(attr.loc)
        gl.glVertexAttribPointer(attr.loc, attr.size, attr.dtype, attr.norm,
                                 attr.stride, attr.offset)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
Example #26
0
 def vertex_attrib_pointer(self,
                           buffer,
                           name,
                           size,
                           dtype=gl.GL_FLOAT,
                           normalized=False,
                           stride=0,
                           offset=0):
     self.use()
     loc = gl.glGetAttribLocation(self.handle,
                                  ctypes.create_string_buffer(name))
     if loc < 0:
         logging.warning('Attribute %s is not in the shader.', name)
         return
     gl.glEnableVertexAttribArray(loc)
     gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
     gl.glVertexAttribPointer(loc, size, dtype, normalized, stride,
                              ctypes.c_void_p(offset))
Example #27
0
    def __init__(self, vertex_shader, fragment_shader, attributes):
        # compile and link
        self.program_name = gl.glCreateProgram()
        gl.glAttachShader(self.program_name,
                          compile_shader(gl.GL_VERTEX_SHADER, vertex_shader))
        gl.glAttachShader(
            self.program_name,
            compile_shader(gl.GL_FRAGMENT_SHADER, fragment_shader))
        link_program(self.program_name)

        # vertex type
        class VERTEX(ctypes.Structure):
            _fields_ = [(name, TYPE_NAME_TO_TYPE[tname] * size)
                        for (name, tname, size) in attributes]

        self.VERTEX = VERTEX

        # vertex array and buffer
        self.vertex_array_name = gl.GLuint(0)
        self.vertex_buffer_name = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vertex_array_name))
        gl.glGenBuffers(1, ctypes.byref(self.vertex_buffer_name))

        gl.glBindVertexArray(self.vertex_array_name)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer_name)
        for (name, tname, size) in attributes:
            location = gl.glGetAttribLocation(
                self.program_name,
                ctypes.create_string_buffer(name.encode('ascii')))
            if location < 0:
                warnings.warn('Attribute %r is not present.' % name,
                              stacklevel=2)
                continue
            gl.glEnableVertexAttribArray(location)
            gl.glVertexAttribPointer(
                location, size, tname, False, ctypes.sizeof(VERTEX),
                ctypes.c_void_p(getattr(VERTEX, name).offset))
        gl.glBindVertexArray(0)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
    def __init__(self, **args):
        super().__init__(**args)

        # create vertex array object

        self.vao = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vao))
        gl.glBindVertexArray(self.vao)

        # create vertex buffer object

        self.vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo)

        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(vertex_positions)),
                        (gl.GLfloat *
                         len(vertex_positions))(*vertex_positions),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        # create index buffer object

        self.ibo = gl.GLuint(0)
        gl.glGenBuffers(1, self.ibo)
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)

        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * len(indices)),
                        (gl.GLuint * len(indices))(*indices),
                        gl.GL_STATIC_DRAW)

        # create shader

        self.shader = shader.Shader("vert.glsl", "frag.glsl")
        self.shader.use()
Example #29
0
    def _create_device_objects(self):
        # save state
        last_texture = gl.GLint()
        gl.glGetIntegerv(gl.GL_TEXTURE_BINDING_2D, byref(last_texture))
        last_array_buffer = gl.GLint()
        gl.glGetIntegerv(gl.GL_ARRAY_BUFFER_BINDING, byref(last_array_buffer))

        last_vertex_array = gl.GLint()
        gl.glGetIntegerv(gl.GL_VERTEX_ARRAY_BINDING, byref(last_vertex_array))

        self._shader_handle = gl.glCreateProgram()
        # note: no need to store shader parts handles after linking
        vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER)
        fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)

        gl.glShaderSource(vertex_shader, 1, make_string_buffer(self.VERTEX_SHADER_SRC), None)
        gl.glShaderSource(fragment_shader, 1, make_string_buffer(self.FRAGMENT_SHADER_SRC), None)
        gl.glCompileShader(vertex_shader)
        gl.glCompileShader(fragment_shader)

        gl.glAttachShader(self._shader_handle, vertex_shader)
        gl.glAttachShader(self._shader_handle, fragment_shader)

        gl.glLinkProgram(self._shader_handle)

        # note: after linking shaders can be removed
        gl.glDeleteShader(vertex_shader)
        gl.glDeleteShader(fragment_shader)

        self._attrib_location_tex = gl.glGetUniformLocation(self._shader_handle, create_string_buffer(b"Texture"))
        self._attrib_proj_mtx = gl.glGetUniformLocation(self._shader_handle, create_string_buffer(b"ProjMtx"))
        self._attrib_location_position = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"Position"))
        self._attrib_location_uv = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"UV"))
        self._attrib_location_color = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"Color"))

        self._vbo_handle = gl.GLuint()
        gl.glGenBuffers(1, byref(self._vbo_handle))
        self._elements_handle = gl.GLuint()
        gl.glGenBuffers(1, byref(self._elements_handle))

        self._vao_handle = gl.GLuint()
        gl.glGenVertexArrays(1, byref(self._vao_handle))
        gl.glBindVertexArray(self._vao_handle)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._vbo_handle)

        gl.glEnableVertexAttribArray(self._attrib_location_position)
        gl.glEnableVertexAttribArray(self._attrib_location_uv)
        gl.glEnableVertexAttribArray(self._attrib_location_color)

        gl.glVertexAttribPointer(self._attrib_location_position, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_POS_OFFSET))
        gl.glVertexAttribPointer(self._attrib_location_uv, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_UV_OFFSET))
        gl.glVertexAttribPointer(self._attrib_location_color, 4, gl.GL_UNSIGNED_BYTE, gl.GL_TRUE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_COL_OFFSET))

        # restore state

        gl.glBindTexture(gl.GL_TEXTURE_2D, cast((c_int*1)(last_texture), POINTER(c_uint)).contents)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, cast((c_int*1)(last_array_buffer), POINTER(c_uint)).contents)
        gl.glBindVertexArray(cast((c_int*1)(last_vertex_array), POINTER(c_uint)).contents)
Example #30
0
def draw_entities(entities, shader, models):
    """


    Dependencies are location, rotation, scale, and model (optionally texture).

    Args:
        shader:
        models:

    Returns:

    """
    attribute_location = shader.attribute_location
    location_location = attribute_location['location']
    texture_location = attribute_location['texture_coordinate']
    normal_location = attribute_location['normal']

    for entity in entities:
        model = models[entity.model]

        shader.set_uniform_matrix('transform', entity.transformation)

        # glActiveTexture(GL_TEXTURE0)
        # texture = textures[entity.diffuse]
        # glBindTexture(GL_TEXTURE_2D, texture.id)
        # glActiveTexture(GL_TEXTURE0 + 1)
        # texture = textures[entity.specular]
        # glBindTexture(GL_TEXTURE_2D, texture.id)
        # glActiveTexture(GL_TEXTURE0 + 2)
        # texture = textures[entity.emission]
        # glBindTexture(GL_TEXTURE_2D, texture.id)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.indexed_vbo)

        glBindBuffer(GL_ARRAY_BUFFER, model.vbo_array['location'])
        glEnableVertexAttribArray(location_location)
        glVertexAttribPointer(location_location, 3, GL_FLOAT, GL_FALSE, 0, 0)

        glBindBuffer(GL_ARRAY_BUFFER, model.vbo_array['texture_coordinate'])
        glEnableVertexAttribArray(texture_location)
        glVertexAttribPointer(texture_location, 2, GL_FLOAT, GL_FALSE, 0, 0)

        glBindBuffer(GL_ARRAY_BUFFER, model.vbo_array['normal'])
        glEnableVertexAttribArray(normal_location)
        glVertexAttribPointer(normal_location, 3, GL_FLOAT, GL_FALSE, 0, 0)

        glDrawElements(GL_TRIANGLES, model.indexed_vbo.count, GL_UNSIGNED_INT,
                       0)

    Entity.needs_update.clear()

    glDisableVertexAttribArray(location_location)
    glDisableVertexAttribArray(texture_location)
    glDisableVertexAttribArray(normal_location)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    def send_mesh_data_to_gpu(self):  # pass mesh data to gpu
        if not self.mesh_index_counter:
            return

        gl.glBindVertexArray(self.vao)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_position_vbo)
        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,
            ctypes.sizeof(gl.GLfloat * len(self.mesh_vertex_positions)),
            (gl.GLfloat *
             len(self.mesh_vertex_positions))(*self.mesh_vertex_positions),
            gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.tex_coord_vbo)
        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(self.mesh_tex_coords)),
                        (gl.GLfloat *
                         len(self.mesh_tex_coords))(*self.mesh_tex_coords),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(1)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.shading_values_vbo)
        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,
            ctypes.sizeof(gl.GLfloat * len(self.mesh_shading_values)),
            (gl.GLfloat *
             len(self.mesh_shading_values))(*self.mesh_shading_values),
            gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(2, 1, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(2)

        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)
        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * self.mesh_indices_length),
                        (gl.GLuint *
                         self.mesh_indices_length)(*self.mesh_indices),
                        gl.GL_STATIC_DRAW)
Example #32
0
    def __init__(self, **args):
        super().__init__(**args)

        # create blocks

        self.texture_manager = texture_manager.Texture_manager(16, 16, 256)

        self.cobblestone = block_type.Block_type(self.texture_manager,
                                                 "cobblestone",
                                                 {"all": "cobblestone"})
        self.grass = block_type.Block_type(self.texture_manager, "grass", {
            "top": "grass",
            "bottom": "dirt",
            "sides": "grass_side"
        })
        self.dirt = block_type.Block_type(self.texture_manager, "dirt",
                                          {"all": "dirt"})
        self.stone = block_type.Block_type(self.texture_manager, "stone",
                                           {"all": "stone"})
        self.sand = block_type.Block_type(self.texture_manager, "sand",
                                          {"all": "sand"})
        self.planks = block_type.Block_type(self.texture_manager, "planks",
                                            {"all": "planks"})
        self.log = block_type.Block_type(self.texture_manager, "log", {
            "top": "log_top",
            "bottom": "log_top",
            "sides": "log_side"
        })

        self.texture_manager.generate_mipmaps()

        # create vertex array object

        self.vao = gl.GLuint(0)
        gl.glGenVertexArrays(1, ctypes.byref(self.vao))
        gl.glBindVertexArray(self.vao)

        # create vertex position vbo

        self.vertex_position_vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.vertex_position_vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_position_vbo)

        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,
            ctypes.sizeof(gl.GLfloat * len(self.grass.vertex_positions)),
            (gl.GLfloat *
             len(self.grass.vertex_positions))(*self.grass.vertex_positions),
            gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        # create tex coord vbo

        self.tex_coord_vbo = gl.GLuint(0)
        gl.glGenBuffers(1, ctypes.byref(self.tex_coord_vbo))
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.tex_coord_vbo)

        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(self.grass.tex_coords)),
                        (gl.GLfloat *
                         len(self.grass.tex_coords))(*self.grass.tex_coords),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(1)

        # create index buffer object

        self.ibo = gl.GLuint(0)
        gl.glGenBuffers(1, self.ibo)
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)

        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * len(self.grass.indices)),
                        (gl.GLuint *
                         len(self.grass.indices))(*self.grass.indices),
                        gl.GL_STATIC_DRAW)

        # create shader

        self.shader = shader.Shader("vert.glsl", "frag.glsl")
        self.shader_sampler_location = self.shader.find_uniform(
            b"texture_array_sampler")
        self.shader.use()

        # pyglet stuff

        pyglet.clock.schedule_interval(self.update, 1.0 / 60)
        self.mouse_captured = False

        # camera stuff

        self.camera = camera.Camera(self.shader, self.width, self.height)
Example #33
0
    def draw(self):
        gl.glPushMatrix()
        self.transform()

        # color preserve - at least nvidia 6150SE needs that
        gl.glPushAttrib(gl.GL_CURRENT_BIT)
        # glPointSize(self.get_scaled_particle_size())

        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glEnable(gl.GL_PROGRAM_POINT_SIZE)
        # glBindTexture(GL_TEXTURE_2D, self.texture.id)


        gl.glEnable(gl.GL_POINT_SPRITE)
        gl.glTexEnvi(gl.GL_POINT_SPRITE, gl.GL_COORD_REPLACE, gl.GL_TRUE)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        vertex_ptr = PointerToNumpy(self.particle_pos)
        gl.glVertexPointer(2, gl.GL_FLOAT, 0, vertex_ptr)

        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        color_ptr = PointerToNumpy(self.particle_color)
        gl.glColorPointer(4, gl.GL_FLOAT, 0, color_ptr)

        gl.glEnableVertexAttribArray(self.particle_size_idx)

        size_ptr = PointerToNumpy(self.particle_size_scaled)
        gl.glVertexAttribPointer(self.particle_size_idx, 1, gl.GL_FLOAT,
            False, 0, size_ptr)

        gl.glPushAttrib(gl.GL_COLOR_BUFFER_BIT)
        gl.glEnable(gl.GL_BLEND)
        if self.blend_additive:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE)
        else:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        # mode = GLint()
        # glTexEnviv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode )
        #
        # if self.color_modulate:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )
        # else:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE )

        self.sprite_shader.install()
        self.sprite_shader.usetTex('sprite_texture', 0, 
            gl.GL_TEXTURE_2D, self.texture.id)

        gl.glDrawArrays(gl.GL_POINTS, 0, self.total_particles)

        self.sprite_shader.uninstall()
        # un -blend
        gl.glPopAttrib()

        # color restore
        gl.glPopAttrib()

        # restore env mode
        # glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode)

        # disable states
        gl.glDisableVertexAttribArray(self.particle_size_idx)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

        gl.glDisable(gl.GL_POINT_SPRITE)
        gl.glDisable(gl.GL_PROGRAM_POINT_SIZE)
        gl.glDisable(gl.GL_TEXTURE_2D)

        gl.glPopMatrix()
Example #34
0
 def enable(self):
     " Enable the shader attribute "
     glEnableVertexAttribArray(self.loc)
Example #35
0
        def __init__(self, frames):
            #consider bumping opengl version if apple supports it
            #amdgpu-mesa currently supports up to 4.5
            super(ControledRender,
                  self).__init__(512,
                                 512,
                                 fullscreen=False,
                                 config=gl.Config(major_version=4,
                                                  minor_version=1),
                                 visible=False)
            print(self.context.get_info().get_version())

            self.frames = frames
            self.vertex_buffer = gl.GLuint(0)
            self.vao = gl.GLuint(0)
            #self.prev_program = (gl.GLint * 1)()

            self.dimx = args["A"].shape[0]
            self.dimy = args["A"].shape[1]

            A = args["A"].astype(np.float32)
            #print("A shape " + str(A.shape))
            #print(str(A.dtype))
            #print(A)

            B = args["B"].astype(np.float32)

            #self.dp = self.tdata.ctypes.data_as(ctypes.POINTER(ctypes.c_void_p))
            self.Ap = A.ctypes.data_as(ctypes.POINTER(ctypes.c_void_p))
            self.Bp = B.ctypes.data_as(ctypes.POINTER(ctypes.c_void_p))

            self.setupFBOandTextures()

            self.setupShaders()

            data = [
                -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
                1.0
            ]

            dataGl = (gl.GLfloat * len(data))(*data)

            gl.glGenBuffers(1, ctypes.byref(self.vertex_buffer))
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer)
            gl.glBufferData(gl.GL_ARRAY_BUFFER,
                            len(dataGl) * 4, dataGl, gl.GL_STATIC_DRAW)

            gl.glGenVertexArrays(1, ctypes.byref(self.vao))
            gl.glBindVertexArray(self.vao)
            gl.glUseProgram(self.programA)
            self.pos_posA = gl.glGetAttribLocation(
                self.programA, ctypes.create_string_buffer(b"a_position"))
            assert (self.pos_posA >= 0)
            gl.glEnableVertexAttribArray(self.pos_posA)
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer)
            gl.glVertexAttribPointer(self.pos_posA, 2, gl.GL_FLOAT, False, 0,
                                     0)

            self.tex_pos_A_A = gl.glGetUniformLocation(self.programA, b"A")
            self.tex_pos_A_B = gl.glGetUniformLocation(self.programA, b"B")
            self.feed_pos_A = gl.glGetUniformLocation(self.programA, b"f")
            self.kill_pos_A = gl.glGetUniformLocation(self.programA, b"k")
            self.dA_pos_A = gl.glGetUniformLocation(self.programA, b"dA")
            self.dB_pos_A = gl.glGetUniformLocation(self.programA, b"dB")
            self.dt_pos_A = gl.glGetUniformLocation(self.programA, b"timestep")
            self.step_pos_A = gl.glGetUniformLocation(self.programA, b"step")
            gl.glUniform1f(self.feed_pos_A, args["feed"])
            gl.glUniform1f(self.kill_pos_A, args["kill"])
            gl.glUniform1f(self.dA_pos_A, args["dA"])
            gl.glUniform1f(self.dB_pos_A, args["dB"])
            gl.glUniform1f(self.dt_pos_A, args["dt"])
            #may need changed for nonsquare textures
            gl.glUniform1f(self.step_pos_A, 1 / self.dimx)

            gl.glUseProgram(self.programB)
            self.pos_posB = gl.glGetAttribLocation(
                self.programB, ctypes.create_string_buffer(b"a_position"))
            assert (self.pos_posB >= 0)
            gl.glEnableVertexAttribArray(self.pos_posB)
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer)
            gl.glVertexAttribPointer(self.pos_posB, 2, gl.GL_FLOAT, False, 0,
                                     0)

            self.tex_pos_B_A = gl.glGetUniformLocation(self.programB, b"A")
            self.tex_pos_B_B = gl.glGetUniformLocation(self.programB, b"B")
            self.feed_pos_B = gl.glGetUniformLocation(self.programB, b"f")
            self.kill_pos_B = gl.glGetUniformLocation(self.programB, b"k")
            self.dA_pos_B = gl.glGetUniformLocation(self.programB, b"dA")
            self.dB_pos_B = gl.glGetUniformLocation(self.programB, b"dB")
            self.dt_pos_B = gl.glGetUniformLocation(self.programB, b"timestep")
            self.step_pos_B = gl.glGetUniformLocation(self.programB, b"step")
            gl.glUniform1f(self.feed_pos_B, args["feed"])
            gl.glUniform1f(self.kill_pos_B, args["kill"])
            gl.glUniform1f(self.dA_pos_B, args["dA"])
            gl.glUniform1f(self.dB_pos_B, args["dB"])
            gl.glUniform1f(self.dt_pos_B, args["dt"])
            #may need changed for nonsquare textures
            gl.glUniform1f(self.step_pos_B, 1 / self.dimx)

            gl.glViewport(0, 0, self.dimx, self.dimy)
Example #36
0
    def draw(self):
        """Draw the particles system"""
        gl.glPushMatrix()
        self.transform()

        # color preserve - at least nvidia 6150SE needs that
        gl.glPushAttrib(gl.GL_CURRENT_BIT)
        # glPointSize(self.get_scaled_particle_size())

        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glEnable(gl.GL_PROGRAM_POINT_SIZE)
        # glBindTexture(GL_TEXTURE_2D, self.texture.id)


        gl.glEnable(gl.GL_POINT_SPRITE)
        gl.glTexEnvi(gl.GL_POINT_SPRITE, gl.GL_COORD_REPLACE, gl.GL_TRUE)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        vertex_ptr = PointerToNumpy(self.particle_pos)
        gl.glVertexPointer(2, gl.GL_FLOAT, 0, vertex_ptr)

        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        color_ptr = PointerToNumpy(self.particle_color)
        gl.glColorPointer(4, gl.GL_FLOAT, 0, color_ptr)

        gl.glEnableVertexAttribArray(self.particle_size_idx)

        size_ptr = PointerToNumpy(self.particle_size_scaled)
        gl.glVertexAttribPointer(self.particle_size_idx, 1, gl.GL_FLOAT,
                                 False, 0, size_ptr)

        gl.glPushAttrib(gl.GL_COLOR_BUFFER_BIT)
        gl.glEnable(gl.GL_BLEND)
        if self.blend_additive:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE)
        else:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        # mode = GLint()
        # glTexEnviv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode )
        #
        # if self.color_modulate:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )
        # else:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE )

        self.sprite_shader.install()
        self.sprite_shader.usetTex('sprite_texture', 0,
                                   gl.GL_TEXTURE_2D, self.texture.id)

        gl.glDrawArrays(gl.GL_POINTS, 0, self.total_particles)

        self.sprite_shader.uninstall()
        # un -blend
        gl.glPopAttrib()

        # color restore
        gl.glPopAttrib()

        # restore env mode
        # glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode)

        # disable states
        gl.glDisableVertexAttribArray(self.particle_size_idx)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

        gl.glDisable(gl.GL_POINT_SPRITE)
        gl.glDisable(gl.GL_PROGRAM_POINT_SIZE)
        gl.glDisable(gl.GL_TEXTURE_2D)

        gl.glPopMatrix()
    def update_mesh(self):
        self.has_mesh = True

        self.mesh_vertex_positions = []
        self.mesh_tex_coords = []
        self.mesh_shading_values = []

        self.mesh_index_counter = 0
        self.mesh_indices = []

        def add_face(face):
            vertex_positions = block_type.vertex_positions[face].copy()

            for i in range(4):
                vertex_positions[i * 3 + 0] += x
                vertex_positions[i * 3 + 1] += y
                vertex_positions[i * 3 + 2] += z

            self.mesh_vertex_positions.extend(vertex_positions)

            indices = [0, 1, 2, 0, 2, 3]
            for i in range(6):
                indices[i] += self.mesh_index_counter

            self.mesh_indices.extend(indices)
            self.mesh_index_counter += 4

            self.mesh_tex_coords.extend(block_type.tex_coords[face])
            self.mesh_shading_values.extend(block_type.shading_values[face])

        for local_x in range(CHUNK_WIDTH):
            for local_y in range(CHUNK_HEIGHT):
                for local_z in range(CHUNK_LENGTH):
                    block_number = self.blocks[local_x][local_y][local_z]

                    if block_number:
                        block_type = self.world.block_types[block_number]

                        x, y, z = (self.position[0] + local_x,
                                   self.position[1] + local_y,
                                   self.position[2] + local_z)

                        # if block is cube, we want it to check neighbouring blocks so that we don't uselessly render faces
                        # if block isn't a cube, we just want to render all faces, regardless of neighbouring blocks
                        # since the vast majority of blocks are probably anyway going to be cubes, this won't impact performance all that much; the amount of useless faces drawn is going to be minimal

                        if block_type.is_cube:
                            if not self.world.get_block_number((x + 1, y, z)):
                                add_face(0)
                            if not self.world.get_block_number((x - 1, y, z)):
                                add_face(1)
                            if not self.world.get_block_number((x, y + 1, z)):
                                add_face(2)
                            if not self.world.get_block_number((x, y - 1, z)):
                                add_face(3)
                            if not self.world.get_block_number((x, y, z + 1)):
                                add_face(4)
                            if not self.world.get_block_number((x, y, z - 1)):
                                add_face(5)

                        else:
                            for i in range(len(block_type.vertex_positions)):
                                add_face(i)

        # pass mesh data to gpu

        if not self.mesh_index_counter:
            return

        gl.glBindVertexArray(self.vao)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_position_vbo)
        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,
            ctypes.sizeof(gl.GLfloat * len(self.mesh_vertex_positions)),
            (gl.GLfloat *
             len(self.mesh_vertex_positions))(*self.mesh_vertex_positions),
            gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(0)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.tex_coord_vbo)
        gl.glBufferData(gl.GL_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLfloat * len(self.mesh_tex_coords)),
                        (gl.GLfloat *
                         len(self.mesh_tex_coords))(*self.mesh_tex_coords),
                        gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(1)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.shading_values_vbo)
        gl.glBufferData(
            gl.GL_ARRAY_BUFFER,
            ctypes.sizeof(gl.GLfloat * len(self.mesh_shading_values)),
            (gl.GLfloat *
             len(self.mesh_shading_values))(*self.mesh_shading_values),
            gl.GL_STATIC_DRAW)

        gl.glVertexAttribPointer(2, 1, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
        gl.glEnableVertexAttribArray(2)

        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)
        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
                        ctypes.sizeof(gl.GLuint * len(self.mesh_indices)),
                        (gl.GLuint *
                         len(self.mesh_indices))(*self.mesh_indices),
                        gl.GL_STATIC_DRAW)
Example #38
0
def main(level_file):
    clock = events.dispatcher('Clock')
    keyboard = events.dispatcher('Keyboard')
    pygame.init()
    pygame.display.gl_set_attribute(pygame.GL_ALPHA_SIZE, 8)

    pygame.display.set_mode((1000, 600), pygame.OPENGL | pygame.DOUBLEBUF | pygame.RESIZABLE)
    handle_resize(1000, 600)
    screen_center = (500, 300)
    camera_offset = 230
    gl.glEnable(gl.GL_TEXTURE_2D)

    gl.glEnable(gl.GL_BLEND)
    gl.glBlendEquation(gl.GL_FUNC_ADD)
    gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
    gl.glClearColor(0, 0, 0, 1)

    tick_event = pygame.event.Event(constants.TICK)
    datadir = find_datadir()
    loader = pyglet.resource.Loader(datadir)

    player1 = viking(datadir, clock, keyboard,
                     pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_j)
    player2 = viking(datadir, clock, keyboard,
                     pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_RETURN)
    player2.location[0] = 900

    entities = [player1, player2]
    scream = pygame.mixer.Sound(os.path.join(datadir, 'wilhelm.wav'))
    background = load_sprite(datadir, 'background')
    backgroundbuf = GLBuffer(4 * 4, numpy.float32, gl.GL_STATIC_DRAW)
    backgroundbuf[:] = background.xyuv
    if level_file is None:
        walls = [components.hitbox((-5, -5), (10, 610)),
                 components.hitbox((995, -5), (10, 610)),
                 components.hitbox((-5, 595), (1010, 5)), ]
    else:
        walls = level.load(level_file)
        for w in walls:
            numpy.round(w.point, out=w.point)
            numpy.round(w.size, out=w.size)
    walls_tlbr = numpy.empty((2, len(walls), 2))
    walls_tlbr[0] = [w.point for w in walls]
    walls_tlbr[1] = [w.point + w.size for w in walls]

    # vertex positions for walls
    quads = numpy.empty((len(walls), 4, 2), dtype=numpy.float32)
    quads[:, 0, :] = [w.point for w in walls]
    quads[:, 2, :] = [w.size for w in walls]
    quads[:, 2, :] += quads[:, 0, :]
    quads[:, 1, 0] = quads[:, 0, 0]
    quads[:, 1, 1] = quads[:, 2, 1]
    quads[:, 3, 0] = quads[:, 2, 0]
    quads[:, 3, 1] = quads[:, 0, 1]
    wallbuf = GLBuffer(quads.size, numpy.float32, gl.GL_STATIC_DRAW)
    wallbuf[:] = quads
    del quads

    # contains vertex and texture positions for sprites
    entitybuf = GLBuffer(dtype=numpy.float32)

    # walls program
    wallprog = shaders.wall()

    spriteprog = shaders.sprite()

    dragonprog = shaders.psycho()
    dragonpalette = load_texture(os.path.join(datadir, 'wallpalette.png'), dimensions=1)
    dragonsprite_scales = load_sprite(datadir, 'dragon_scales')
    dragonsprite_contours = load_sprite(datadir, 'dragon_contours')
    dragonbuf = GLBuffer(4 * 4, numpy.float32, gl.GL_STATIC_DRAW)
    dragonbuf[:] = dragonsprite_scales.xyuv + (-100, 145, 0, 0)
    contourbuf = GLBuffer(4 * 4, numpy.float32, gl.GL_STATIC_DRAW)
    contourbuf[:] = dragonsprite_contours.xyuv + (-100, 145, 0, 0)

    debug_draw = False
    pause = False
    do_frame = False
    ticks_done = 0
    while True:
        start = time.clock()

        key_events = []
        resize_event = None
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return 0
            elif event.type == pygame.KEYDOWN or event.type == pygame.KEYUP:
                key_events.append(event)
            elif event.type == pygame.VIDEORESIZE:
                resize_event = event

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return 0
                if event.key == pygame.K_F2:
                    debug_draw = not debug_draw
                elif event.key == pygame.K_F3:
                    entities.append(sheep(datadir, clock))
                elif event.key == pygame.K_F4:
                    entities.append(drake(datadir, clock))
                elif event.key == pygame.K_F5:
                    entities.append(floaty_sheep(datadir, clock))
                elif event.key == pygame.K_p:
                    pause = not pause
                elif event.key == pygame.K_PERIOD and pause:
                    do_frame = True

        if resize_event:
            handle_resize(resize_event.w, resize_event.h)
            screen_center = (resize_event.w // 2, resize_event.h // 2)
            background.xyuv[:, :2] = [[0, 0], [0, resize_event.h],
                                      [resize_event.w, resize_event.h], [resize_event.w, 0]]
            backgroundbuf[:] = background.xyuv

        if (not pause) or do_frame:
            for event in key_events:
                keyboard.dispatch(event)

            location = components.entity.location
            delta = numpy.array(location)
            motion_a = components.entity.motion_a
            motion_v = components.entity.motion_v
            active_tl = components.entity.active_tl
            active_br = components.entity.active_br
            passive_tl = components.entity.passive_tl
            passive_br = components.entity.passive_br
            instances = components.entity._all[:components.entity._nentities]
            do_translate = components.entity.translate_all

            GROUNDED = intern('grounded')
            motion_a[:] = (0, constants.G)
            clock.dispatch(tick_event)
            for thing in entities:
                thing.tags.discard(GROUNDED)
            motion_v[:] += motion_a

            collisions.resolve_passive_active_collisions(instances, active_tl, active_br, passive_tl, passive_br)
            attempts = 0
            adjust_significant = True
            rppc = collisions.resolve_passive_passive_collisions
            rwc = collisions.resolve_wall_collisions
            grounded_mask = numpy.zeros((len(instances),), dtype=bool)
            stop = numpy.empty((len(instances),2), dtype=bool)
            adjust, sides = rwc(motion_v, passive_tl, passive_br, walls_tlbr[0], walls_tlbr[1])
            numpy.logical_or.reduce(sides.reshape(-1, 2, 2), out=stop, axis=2)
            motion_v[stop] = 0
            do_translate(motion_v[:])
            while attempts < 20 and adjust_significant:
                adjust, sides, done_impulse = rppc(motion_v, passive_tl, passive_br)
                grounded_mask |= sides[:,3]
                adjust *= 0.5
                do_translate(adjust)
                adjust_significant = not numpy.allclose(adjust, 0, atol=0.125)
                adjust_significant |= done_impulse > 0.125
                del adjust, sides
                adjust, sides = rwc(motion_v, passive_tl, passive_br, walls_tlbr[0], walls_tlbr[1])
                adjust_significant |= not numpy.allclose(adjust, 0, atol=0.5)
                do_translate(adjust)
                numpy.logical_or.reduce(sides.reshape(-1, 2, 2), out=stop, axis=2)
                motion_v[stop] = 0
                grounded_mask |= sides[:,3]

                attempts += 1

            for thing in numpy.compress(grounded_mask, instances):
                thing.tags.add(GROUNDED)

            do_frame = False
            ticks_done += 1

        dead = []

        gl.glLoadIdentity()
        gl.glEnableVertexAttribArray(0)
        gl.glUseProgram(spriteprog.id)
        gl.glBindTexture(gl.GL_TEXTURE_2D, background.texid)
        spriteprog['texture'] = 0

        with backgroundbuf.bound:
            gl.glVertexAttribPointer(0, 4, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
            gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4)

        # Now move camera
        camera_location = (screen_center - numpy.round(entities[0].location)) + (0, camera_offset)
        gl.glTranslated(camera_location[0], camera_location[1], 0.0)

        for thing in entities:
            if thing.hitpoints <= 0 or thing.location[1] > 10000:
                dead.append(thing)
                continue

        for thing in dead:
            scream.play()
            if thing.name == 'Player':
                thing.hitpoints = 100
                thing.location[:] = (500, -10)
                thing.motion_v[:] = 0
                if thing.physics is not None:
                    thing.physics.last_position[:] = thing.location
            else:
                entities.remove(thing)
                thing.dispose()

        xyuv = numpy.empty((4, 4), dtype=numpy.float32)
        texid = [0] * len(entities)
        with entitybuf.bound:
            for n, thing in enumerate(entities):
                xyuv[:] = thing.graphics.sprite.xyuv
                xy = xyuv[:, 0:2]
                xy[:] += thing.graphics.anchor
                xy[:] += thing.location
                numpy.round(xy, out=xy)
                offset = n * 16
                entitybuf[offset:] = xyuv
                texid[n] = thing.graphics.sprite.texid
                #print('Loaded data for entity', n, xyuv, 'texid', texid[n])

            gl.glVertexAttribPointer(0, 4, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)

            for n, t in enumerate(texid):
                gl.glBindTexture(gl.GL_TEXTURE_2D, t)
                gl.glDrawArrays(gl.GL_TRIANGLE_FAN, n * 4, 4)

        # draw walls
        gl.glUseProgram(wallprog.id)
        wallprog['color'] = (162.0/255.0, 153.0/255.0, 118.0/255.0, 1.0)
        with wallbuf.bound:
            gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
            gl.glDrawArrays(gl.GL_QUADS, 0, len(walls) * 8)

        # draw some shaders
        gl.glUseProgram(dragonprog.id)
        gl.glBindTexture(gl.GL_TEXTURE_2D, dragonsprite_scales.texid)
        gl.glActiveTexture(gl.GL_TEXTURE0 + 1)
        gl.glBindTexture(gl.GL_TEXTURE_1D, dragonpalette)
        gl.glActiveTexture(gl.GL_TEXTURE0)
        dragonprog['texture'] = 0
        dragonprog['palette'] = 1
        dragonprog['perturb'] = (ticks_done % 1024) / 128
        dragonprog['shift'] = ticks_done / 600
        with dragonbuf.bound:
            gl.glVertexAttribPointer(0, 4, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
            gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4)

        # now draw the rest of the f****n' dragon
        gl.glUseProgram(spriteprog.id)
        gl.glBindTexture(gl.GL_TEXTURE_2D, dragonsprite_contours.texid)
        spriteprog['texture'] = 0
        with contourbuf.bound:
            gl.glVertexAttribPointer(0, 4, gl.GL_FLOAT, gl.GL_FALSE, 0, 0)
            gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4)

        if debug_draw:
            gl.glUseProgram(wallprog.id)
            wallprog['color'] = (0.89, 0.89, 0.89, 1.0)
            quads = numpy.zeros((len(entities), 4, 2), dtype=numpy.float32)
            quads[:, 0, :] = components.entity.passive_tl
            quads[:, 2, :] = components.entity.passive_br
            quads[:, 1, 0] = quads[:, 0, 0]
            quads[:, 1, 1] = quads[:, 2, 1]
            quads[:, 3, 0] = quads[:, 2, 0]
            quads[:, 3, 1] = quads[:, 0, 1]
            gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, quads.ctypes.data)
            gl.glDrawArrays(gl.GL_QUADS, 0, quads.size // 2)

        gl.glColor3f(1, 1, 1)
        gl.glEnable(gl.GL_TEXTURE_2D)

        #screen.fill((120, 50, 50), pygame.Rect(0, 10, player1.hitpoints * 2, 10))
        #screen.fill((120, 50, 50), pygame.Rect(1000 - player2.hitpoints * 2, 10, player2.hitpoints * 2, 10))

        pygame.display.flip()

        delta = time.clock() - start
        if delta < constants.FRAME:
            time.sleep(constants.FRAME - delta)
Example #39
0
    def _build(self, program: Program, content: Sequence[BufferDescription],
               index_buffer):
        """Build a vertex array compatible with the program passed in"""
        gl.glGenVertexArrays(1, byref(self.glo))
        gl.glBindVertexArray(self.glo)

        # Lookup dict for BufferDescription attrib names
        # print(content)
        descr_attribs = {
            attr.name: (descr, attr)
            for descr in content for attr in descr.formats
        }
        # print('->', descr_attribs)

        # Build the vao according to the shader's attribute specifications
        for i, prog_attr in enumerate(program.attributes):
            # print('prog_attr', prog_attr)
            # Do we actually have an attribute with this name in buffer descriptions?
            if prog_attr.name.startswith("gl_"):
                continue
            try:
                buff_descr, attr_descr = descr_attribs[prog_attr.name]
            except KeyError:
                raise ValueError((
                    f"Program needs attribute '{prog_attr.name}', but is not present in buffer description. "
                    f"Buffer descriptions: {content}"))

            # TODO: Sanity check this
            # if buff_descr.instanced and i == 0:
            #     raise ValueError("The first vertex attribute cannot be a per instance attribute.")

            # Make sure components described in BufferDescription and in the shader match
            if prog_attr.components != attr_descr.components:
                raise ValueError((
                    f"Program attribute '{prog_attr.name}' has {prog_attr.components} components "
                    f"while the buffer description has {attr_descr.components} components. "
                ))

            # TODO: Compare gltype between buffer descr and program attr

            gl.glEnableVertexAttribArray(prog_attr.location)
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buff_descr.buffer.glo)

            # TODO: Detect normalization
            normalized = (gl.GL_TRUE if attr_descr.name
                          in buff_descr.normalized else gl.GL_FALSE)
            gl.glVertexAttribPointer(
                prog_attr.location,  # attrib location
                attr_descr.components,  # 1, 2, 3 or 4
                attr_descr.gl_type,  # GL_FLOAT etc
                normalized,  # normalize
                buff_descr.stride,
                c_void_p(attr_descr.offset),
            )
            # print((
            #     f"gl.glVertexAttribPointer(\n"
            #     f"    {prog_attr.location},  # attrib location\n"
            #     f"    {attr_descr.components},  # 1, 2, 3 or 4\n"
            #     f"    {attr_descr.gl_type},  # GL_FLOAT etc\n"
            #     f"    {normalized},  # normalize\n"
            #     f"    {buff_descr.stride},\n"
            #     f"    c_void_p({attr_descr.offset}),\n"
            # ))
            # TODO: Sanity check this
            if buff_descr.instanced:
                gl.glVertexAttribDivisor(prog_attr.location, 1)

        if index_buffer is not None:
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, index_buffer.glo)