def bind_attributes(**attributes): program_handle = glGetIntegerv(GL_CURRENT_PROGRAM) vertices_count = 0 bound = [] for raw_name, values in attributes.items(): # attribute key: <attribute_name>(_(_[(o<attribute_offset>)|(d<divisor>)])+)? name = raw_name offset = 0 divisor = None if '__' in raw_name: name, modifiers = name.split('__')[0], name.split('__')[1] for modifier in modifiers.split('_'): key, value = modifier[0], modifier[1:] if key == 'o': offset = int(value) elif key == 'd': divisor = int(value) location = glGetAttribLocation(program_handle, name) if location < 0: raise KeyError('Attribute not found: {} (from raw_name={})'.format(name, raw_name)) location += offset if _np.isscalar(values): glVertexAttrib1f(location, values) elif isinstance(values, tuple): gl_vertex_attrib_f = [glVertexAttrib1f, glVertexAttrib2f, glVertexAttrib3f, glVertexAttrib4f][len(values)-1] gl_vertex_attrib_f(location, *values) else: if divisor is not None: glVertexAttribDivisor(location, divisor) else: vertices_count = max(vertices_count, _np.prod(values.shape[:-1])) glEnableVertexAttribArray(location) if values.dtype == _np.float64: values = values.astype(_np.float32) if len(values.shape) == 1: values = values.reshape(-1, 1) # [1, 2, ... n] -> [[1], [2], ... [n]] item_size = values.shape[-1] stride = values.strides[-2] if isinstance(values, _BufferObject): with values: glVertexAttribPointer(location, item_size, _array_gl_type(values), GL_TRUE, stride, None) else: glVertexAttribPointer(location, item_size, _array_gl_type(values), GL_TRUE, stride, values) bound.append((location, divisor)) yield vertices_count for location, divisor in bound: if divisor is not None: glVertexAttribDivisor(location, 0) glDisableVertexAttribArray(location)
def locate_attribute(self, name): return glGetAttribLocation(self._handle, name)