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
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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"))
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))
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)
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)
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)
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)
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
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)
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)
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)
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))
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()
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)
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)
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)
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()
def enable(self): " Enable the shader attribute " glEnableVertexAttribArray(self.loc)
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)
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)
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)
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)