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 _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)
def construct_offset_buffer(): gl.glBufferData(gl.GL_ARRAY_BUFFER, 9 * 2 * sizeof(gl.GLfloat), None, gl.GL_DYNAMIC_DRAW) gl.glEnableVertexAttribArray(1) gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, False, 2 * sizeof(gl.GLfloat), 0) gl.glVertexAttribDivisor(1, 1)