def set_data(self, data, format=None, shape=None, offset=None, data_type=None, level=0, swizzle=None, **kwargs): def set_swizzle(swizzle): # sets the swizzle before loading # only available on OpenGL Core if isinstance(swizzle, (list, tuple)): swizzle = (GL.GLint * len(swizzle))(*swizzle) elif isinstance(swizzle, basestring): result = [ Texture.channels[channel] for channel in swizzle.lower() ] swizzle = (GL.GLint * len(result))(*result) GL.glTexParameteriv(self._target, GL.GL_TEXTURE_SWIZZLE_RGBA, swizzle) ndims = Texture.target_ndims[self._target] _, func = Texture.funcs[ndims] if not shape: # take the shape from the data # but ignore the last dimension # this will cause a problem if the data is not in the appropriate shape if data.ndims != (ndims + 1): raise ValueError('Data must be appropriate shape if shape not specified') shape = data.shape[:-1] if not offset: offset = [0] * ndims if not data_type: # infer the data type from the numpy dtype data_type = numpy_utils.dtype_gl_enum(data.dtype) if not format: # infer the passed data format using the last dimension of the data num_channels = data.shape[-1] format = Texture.inferred_formats[num_channels] if gl.is_core(): if swizzle: set_swizzle(swizzle) args = [ self.target, level,] + \ list(offset) + \ list(shape) + [ format, data_type, data, ] func(*args)
def allocate(self, shape, data_type, internal_format=None, **kwargs): # assume same format of data if not internal_format: internal_format = self._internal_format else: self._internal_format = internal_format ndims = Texture.target_ndims[self._target] func, _ = Texture.funcs[ndims] border = 1 if self._border else 0 self._shape = tuple(shape) if not data_type: # attempt to detect the data type from the dtype data_type = numpy_utils.dtype_gl_enum(data.dtype) else: # if we have a dtype # determine what type of dtype it is if isinstance(data_type, numpy.dtype): # numpy dtype data_type = numpy_utils.dtype_gl_enum(data_type) elif isinstance(data_type, basestring): # numpy dtype string data_type = numpy_utils.dtype_gl_enum(numpy.dtype(data_type)) args = [ self.target, 0, internal_format,] + \ list(shape) + [ border, GL.GL_RED, # just use any valid value data_type, None, ] func(*args)
def from_dtype( cls, buffer, dtype, name, offset = 0, **kwargs ): import numpy_utils args = { 'buffer': buffer, 'values_per_vertex': numpy_utils.dtype_element_count( dtype, name ), 'gl_type': numpy_utils.dtype_gl_enum( dtype, name ), 'stride': dtype.itemsize, 'offset': offset + numpy_utils.dtype_offset( dtype, name ) } args.update( kwargs ) return cls( **args )
def set_data(self, data, format=None, shape=None, offset=None, data_type=None, level=0, swizzle=None, **kwargs): def set_swizzle(swizzle): # sets the swizzle before loading # only available on OpenGL Core if isinstance(swizzle, (list, tuple)): swizzle = (GL.GLint * len(swizzle))(*swizzle) elif isinstance(swizzle, basestring): result = [ Texture.channels[channel] for channel in swizzle.lower() ] swizzle = (GL.GLint * len(result))(*result) GL.glTexParameteriv(self._target, GL.GL_TEXTURE_SWIZZLE_RGBA, swizzle) ndims = Texture.target_ndims[self._target] _, func = Texture.funcs[ndims] if not shape: # take the shape from the data # but ignore the last dimension # this will cause a problem if the data is not in the appropriate shape if data.ndims != (ndims + 1): raise ValueError( 'Data must be appropriate shape if shape not specified') shape = data.shape[:-1] if not offset: offset = [0] * ndims if not data_type: # infer the data type from the numpy dtype data_type = numpy_utils.dtype_gl_enum(data.dtype) if not format: # infer the passed data format using the last dimension of the data num_channels = data.shape[-1] format = Texture.inferred_formats[num_channels] if gl.is_core(): if swizzle: set_swizzle(swizzle) args = [ self.target, level,] + \ list(offset) + \ list(shape) + [ format, data_type, data, ] func(*args)
def __init__(self, data=None, target=None, internal_format=None, min_filter=GL.GL_NEAREST, mag_filter=GL.GL_NEAREST, wrap_s=GL.GL_REPEAT, wrap_t=GL.GL_REPEAT, shape=None, format=None, data_type=None, border=False, **kwargs): """Creates a new texture. By default, only the handle will be allocated. Optional parameters allow the texture to be allocated and have data set. :param GLuint target: The OpenGL texture target type. :param GLuint internal_format: The internal format used by this texture. :param GLuint min_filter: The minification filter to use for scaling the image down. This MUST be set on OpenGL 3.0+ or the texture won't render. :param GLuint mag_filter: The magnification filter to use for scaling the image down. This MUST be set on OpenGL 3.0+ or the texture won't render. :param GLuint wrap_s: The wrap setting for the S dimension. :param GLuint wrap_t: The wrap setting for the T dimension. :param bool border: Whether or not to apply a border to the texture. This MUST be False on OpenGL 3.0+. :param iterable data: Data to set on the texture. The data shape should represent the dimensions of the texture and the number of channels. For example, a 32x32 RGBA texture would have the shape (32,32,4). :param tuple shape: Specify the data's shape instead of using the shape of the data variable itself. :param GLuint data_type: OpenGL data type (GL_FLOAT, etc). Inferred from data dtype if not set. :param GLuint format: The OpenGL format of the data. Inferred from data shape if not set. """ super(Texture, self).__init__() if data != None: # infer any data we haven't be given if not target: target = Texture.inferred_targets[data.ndims - 1] if not shape: shape = data.shape[:-1] if not data_type: data_type = numpy_utils.dtype_gl_enum(data.dtype) if not internal_format: internal_format = Texture.inferred_formats[data.shape[-1]] # TODO: handle target and format being integers or strings self._target = target self._internal_format = internal_format self._handle = GL.glGenTextures(1) self._border = border self._shape = shape self.bind() # we should set the min / mag filter now # if we don't set it, the texture won't show up in GL 3+ # and it's a real bitch to debug self.min_filter = min_filter self.mag_filter = mag_filter self.wrap_s = wrap_s self.wrap_t = wrap_t if shape and data_type and internal_format: self.allocate(shape, data_type, self._internal_format, **kwargs) if data != None: self.set_data(data, format=format, shape=shape, data_type=data_type, **kwargs) self.unbind()
def __init__( self, data=None, target=None, internal_format=None, min_filter=GL.GL_NEAREST, mag_filter=GL.GL_NEAREST, wrap_s=GL.GL_REPEAT, wrap_t=GL.GL_REPEAT, shape=None, format=None, data_type=None, border=False, **kwargs ): """Creates a new texture. By default, only the handle will be allocated. Optional parameters allow the texture to be allocated and have data set. :param GLuint target: The OpenGL texture target type. :param GLuint internal_format: The internal format used by this texture. :param GLuint min_filter: The minification filter to use for scaling the image down. This MUST be set on OpenGL 3.0+ or the texture won't render. :param GLuint mag_filter: The magnification filter to use for scaling the image down. This MUST be set on OpenGL 3.0+ or the texture won't render. :param GLuint wrap_s: The wrap setting for the S dimension. :param GLuint wrap_t: The wrap setting for the T dimension. :param bool border: Whether or not to apply a border to the texture. This MUST be False on OpenGL 3.0+. :param iterable data: Data to set on the texture. The data shape should represent the dimensions of the texture and the number of channels. For example, a 32x32 RGBA texture would have the shape (32,32,4). :param tuple shape: Specify the data's shape instead of using the shape of the data variable itself. :param GLuint data_type: OpenGL data type (GL_FLOAT, etc). Inferred from data dtype if not set. :param GLuint format: The OpenGL format of the data. Inferred from data shape if not set. """ super(Texture, self).__init__() if data != None: # infer any data we haven't be given if not target: target = Texture.inferred_targets[data.ndims - 1] if not shape: shape = data.shape[:-1] if not data_type: data_type = numpy_utils.dtype_gl_enum(data.dtype) if not internal_format: internal_format = Texture.inferred_formats[data.shape[-1]] # TODO: handle target and format being integers or strings self._target = target self._internal_format = internal_format self._handle = GL.glGenTextures(1) self._border = border self._shape = shape self.bind() # we should set the min / mag filter now # if we don't set it, the texture won't show up in GL 3+ # and it's a real bitch to debug self.min_filter = min_filter self.mag_filter = mag_filter self.wrap_s = wrap_s self.wrap_t = wrap_t if shape and data_type and internal_format: self.allocate(shape, data_type, self._internal_format, **kwargs) if data != None: self.set_data(data, format=format, shape=shape, data_type=data_type, **kwargs) self.unbind()