def data(self, buffer_type, data, offset): if buffer_type != "texture": gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffers[buffer_type]) if buffer_type == "color": offset *= 16 else: offset *= 12 gl_data = to_gl_float(data) length = len(data) * 4 gl.glBufferSubData(gl.GL_ARRAY_BUFFER, offset, length, gl_data) if buffer_type == "vertex": self.vertex_count += int(len(data) / 3) else: self.buffers["texture"] = gl.GLuint(0) gl.glGenTextures(1, self.buffers["texture"]) gl.glBindTexture(data.target, data.id) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, texture.width, texture.height, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, texture_data)
def __init__(self, image, f, t): self.image = image self.format = f self.type = t self.uploaded = False self.handle = GLuint() glGenTextures(1, self.handle) glBindTexture(GL_TEXTURE_2D, self.handle) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
def update(self, delta_time): """ Update our scene! """ # -- For the moment -- Might be able to improve the logic of this gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) self._player.update(delta_time)
def PILtoGL(image, mode=0): h = hash(image.tobytes()) path = f"swap/IMG_PIL_TO_GL_{h}.png" image.save(path) img = pyglet.image.load(f"swap/IMG_PIL_TO_GL_{h}.png") if mode == 0: img = img.get_texture() gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) remove(path) return img
def _apply_filter_settings(self): """Applies some hard-coded texture filtering settings.""" # TODO: Allow easy customization of filters gl.glTexParameterf(self.target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameterf(self.target, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameterf(self.target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(self.target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
def set_data(self, arr): arr = np.asarray(arr) self.src_format, self.dst_format = fmts_from_shape(arr.shape, self._texture_dim) # Float is default type if arr.dtype == np.uint8: arr = np.ascontiguousarray(arr) self.src_type = gl.GL_UNSIGNED_BYTE elif arr.dtype == np.float32: arr = np.ascontiguousarray(arr) self.src_type = gl.GL_FLOAT else: arr = np.astype(np.float32) self.src_type = gl.GL_FLOAT self._arr = arr if self._id: gl.glDeleteTextures(1, gl.byref(self._id)) id = gl.GLuint() gl.glGenTextures(1, gl.byref(id)) self._id = id gl.glPixelStorei (gl.GL_UNPACK_ALIGNMENT, 1) gl.glPixelStorei (gl.GL_PACK_ALIGNMENT, 1) gl.glBindTexture (self.target, self._id) gl.glTexParameterf (self.target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf (self.target, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameterf (self.target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP) gl.glTexParameterf (self.target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP) self._setup_tex() self.update()
def PygameToGL(image: pygame.SurfaceType, mode=0) -> pyglet.image.AbstractImage: h = hash(image) path = f"swap/IMG_PYGAME_TO_GL_{h}.png" pygame.image.save(image, path) img = pyglet.image.load(path) if mode == 0: img = img.get_texture() gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) remove(path) return img
def draw(self): for camera in CameraManager().collection: glClearColor(camera.backgroundColor[0] / 255, camera.backgroundColor[1] / 255, camera.backgroundColor[2] / 255, camera.backgroundColor[3] / 255) camera.worldProjection() sprites = self.frustumCulling.intersect( (*camera.transform.position, *(camera.transform.position + camera.size / camera.zoom))) for sprite in sprites: sprite.draw() glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ### for elem in self.GUI: for camera in CameraManager().collection: camera.hudProjection() elem.draw() glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
def _apply_filter_settings(self): """Applies some hard-coded texture filtering settings.""" # TODO: Allow easy customization of filters if self.mipmap: gl.glTexParameterf(self.target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR) else: gl.glTexParameterf(self.target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameterf(self.target, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameterf(self.target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(self.target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
def image(file, mode=0) -> pyglet.image.ImageData: try: img = pyglet.image.load(file) if mode == 0: img = img.get_texture() gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) log.info(f"Loading texture: {file}") return img except FileNotFoundError as e: log.info(f"Failed to load texture: {file}") if mode: return transform.PygameToGL(unknown).get_texture() else: return transform.PygameToGL(unknown)
def pyPackTextures(**kwargs): verbose = kwargs.get('verbose', False) print('Pygletting images') textures = {} texturePacks = findTexturePacks(**kwargs) for texturePack in texturePacks: textures.update({texturePack: []}) if verbose: print(' - Pygletting pack %s' % texturePack) for texture in texturePacks[texturePack]: if verbose: print(' -- Pygletting image %s' % texture) tex = pyglet.image.load(texture).texture gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) textures[texturePack].append(pyglet.graphics.TextureGroup(tex)) return textures
def _draw_rects(shape_list: Iterable[Sprite], vertex_vbo_id: gl.GLuint, texture_coord_vbo_id: gl.GLuint): """ Draw a set of rectangles using vertex buffers. This is more efficient than drawing them individually. """ gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_TEXTURE_2D) # As soon as this happens, can't use drawing commands gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glHint(gl.GL_POLYGON_SMOOTH_HINT, gl.GL_NICEST) gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST) # gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # gl.glMatrixMode(gl.GL_MODELVIEW) # gl.glDisable(gl.GL_BLEND) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertex_vbo_id) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, texture_coord_vbo_id) offset = 0 for shape in shape_list: if shape.can_cache: texture_coord_vbo_id = None gl.glColor4f(1, 1, 1, shape.alpha) _render_rect_filled(shape, offset, shape.texture.texture_id, texture_coord_vbo_id) offset += 4 else: shape.draw() gl.glDisable(gl.GL_TEXTURE_2D)
def _create_texture(textureID=None, texture_size=None): # create a texture for Rendering Color if textureID is not None: rgb_texture = textureID else: rgb_texture = (c_uint * 1)() ; gl.glGenTextures(1, rgb_texture) rgb_texture = rgb_texture[0] width, height = texture_size gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_2D, rgb_texture) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, None) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) return rgb_texture
def upload(asset: ModelAsset, gl_usage=GL_STATIC_DRAW): asset.vertex_array_id = GLuint() glGenVertexArrays(1, asset.vertex_array_id) asset.vertex_buffer_id = GLuint() glGenBuffers(1, asset.vertex_buffer_id) upload_vertices(asset, gl_usage) upload_indices(asset, gl_usage) if asset.texture is not None: glBindTexture(GL_TEXTURE_2D, asset.texture.id) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) # noinspection PyCallingNonCallable,PyTypeChecker texture_data = (GLubyte * len(asset.texture.buffer.flat))( *asset.texture.buffer.flatten()) glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, asset.texture.width, asset.texture.height, 0, asset.texture.format, asset.texture.type, texture_data)
def build_kernel(size=256): # From GPU Gems # Chapter 24. High-Quality Filtering # Kevin Bjorke, NVIDIA # http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html # # Mitchell Netravali Reconstruction Filter # a = 1.0, b = 0.0 - cubic B-spline # B = 1/3, b = 1/3 - recommended # a = 0.5, b = 0.0 - Catmull-Rom spline def MitchellNetravali(x, a=1, b=0): x = math.fabs(x) if x < 1.0: return ((12-9*a-6*b) *x*x*x + (-18+12*a+6*b)*x*x + (6-2*a))/6.0 elif x < 2.0: return ((-a-6*b)*x*x*x + (6*a+30*b)*x*x + (-12*a-48*b)*x + (8*a+24*b))/6.0 else: return 0 data = (gl.GLfloat*(4*size))() for i in range(size): x = i/float(size-1) data[i*4+0] = MitchellNetravali(x+1) data[i*4+1] = MitchellNetravali(x) data[i*4+2] = MitchellNetravali(1-x) data[i*4+3] = MitchellNetravali(2-x) texid = gl.GLuint() gl.glGenTextures(1, ctypes.byref(texid)) kernel = texid.value gl.glPixelStorei (gl.GL_UNPACK_ALIGNMENT, 1) gl.glPixelStorei (gl.GL_PACK_ALIGNMENT, 1) gl.glBindTexture (gl.GL_TEXTURE_1D, texid) gl.glTexParameterf (gl.GL_TEXTURE_1D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf (gl.GL_TEXTURE_1D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameterf (gl.GL_TEXTURE_1D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP) gl.glTexParameterf (gl.GL_TEXTURE_1D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP) gl.glTexImage1D (gl.GL_TEXTURE_1D, 0, gl.GL_RGBA16, size, 0, gl.GL_RGBA, gl.GL_FLOAT, data) return kernel
def load_textures(file_name: str, image_location_list: PointList, mirrored: bool=False, flipped: bool=False, scale: float=1) -> List['Texture']: """ Load a set of textures off of a single image file. Note, if the code is to load only part of the image, the given x, y coordinates will start with the origin (0, 0) in the upper left of the image. When drawing, Arcade uses (0, 0) in the lower left corner when drawing. Be careful about this reversal. For a longer explanation of why computers sometimes start in the upper left, see: http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5 Args: :file_name: Name of the file. :image_location_list: List of image locations. Each location should be a list of four floats. ``[x, y, width, height]``. :mirrored=False: If set to true, the image is mirrored left to right. :flipped=False: If set to true, the image is flipped upside down. Returns: :list: List of textures loaded. Raises: :SystemError: """ source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size texture_info_list = [] for image_location in image_location_list: x, y, width, height = image_location if width <= 0: raise ValueError("Texture has a width of {}, must be > 0." .format(width)) if x > source_image_width: raise ValueError("Can't load texture starting at an x of {} " "when the image is only {} across." .format(x, source_image_width)) if y > source_image_height: raise ValueError("Can't load texture starting at an y of {} " "when the image is only {} high." .format(y, source_image_height)) if x + width > source_image_width: raise ValueError("Can't load texture ending at an x of {} " "when the image is only {} wide." .format(x + width, source_image_width)) if y + height > source_image_height: raise ValueError("Can't load texture ending at an y of {} " "when the image is only {} high." .format(y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) # image = _trim_image(image) if mirrored: image = PIL.ImageOps.mirror(image) if flipped: image = PIL.ImageOps.flip(image) image_width, image_height = image.size texture = gl.GLuint(0) gl.glGenTextures(1, ctypes.byref(texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, texture) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR) image_width *= scale image_height *= scale texture_info_list.append(Texture(texture, width, height, image_location)) return texture_info_list
def draw(self, **kwargs): """ Draw this list of sprites. :param filter: Optional parameter to set OpenGL filter, such as `gl.GL_NEAREST` to avoid smoothing. """ if self.program is None: # Used in drawing optimization via OpenGL self.program = shader.program(vertex_shader=_VERTEX_SHADER, fragment_shader=_FRAGMENT_SHADER) if len(self.sprite_list) == 0: return if self._vao1 is None: self._calculate_sprite_buffer() self._texture.use(0) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if "filter" in kwargs: gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, kwargs["filter"]) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, kwargs["filter"]) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) with self._vao1: self.program['Texture'] = self.texture_id self.program['Projection'] = get_projection().flatten() texture_transform = None if len(self.sprite_list) > 0: # always wrap texture transformations with translations # so that rotate and resize operations act on the texture # center by default texture_transform = Matrix3x3().translate(-0.5, -0.5).multiply( self.sprite_list[0].texture_transform.v).multiply( Matrix3x3().translate(0.5, 0.5).v) if texture_transform == None: texture_transform = Matrix3x3() self.program['TextureTransform'] = texture_transform.v if not self.is_static: if self._sprite_pos_changed: self._sprite_pos_buf.orphan() self._sprite_pos_buf.write(self._sprite_pos_data.tobytes()) self._sprite_pos_changed = False if self._sprite_size_changed: self._sprite_size_buf.orphan() self._sprite_size_buf.write( self._sprite_size_data.tobytes()) self._sprite_size_changed = False if self._sprite_angle_changed: self._sprite_angle_buf.orphan() self._sprite_angle_buf.write( self._sprite_angle_data.tobytes()) self._sprite_angle_changed = False if self._sprite_color_changed: self._sprite_color_buf.orphan() self._sprite_color_buf.write( self._sprite_color_data.tobytes()) self._sprite_color_changed = False if self._sprite_sub_tex_changed: self._sprite_sub_tex_buf.orphan() self._sprite_sub_tex_buf.write( self._sprite_sub_tex_data.tobytes()) self._sprite_sub_tex_changed = False self._vao1.render(gl.GL_TRIANGLE_STRIP, instances=len(self.sprite_list))
def draw(self, **kwargs): """ Draw this list of sprites. :param filter: Optional parameter to set OpenGL filter, such as `gl.GL_NEAREST` to avoid smoothing. """ if self.program is None: # Used in drawing optimization via OpenGL self.program = shader.program(vertex_shader=_VERTEX_SHADER, fragment_shader=_FRAGMENT_SHADER) if len(self.sprite_list) == 0: return if self._vao1 is None: self._calculate_sprite_buffer() self._texture.use(0) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if "filter" in kwargs: gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, kwargs["filter"]) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, kwargs["filter"]) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) with self._vao1: self.program['Texture'] = self.texture_id self.program['Projection'] = get_projection().flatten() if not self.is_static: if self._sprite_pos_changed: self._sprite_pos_buf.orphan() self._sprite_pos_buf.write(self._sprite_pos_data.tobytes()) self._sprite_pos_changed = False if self._sprite_size_changed: self._sprite_size_buf.orphan() self._sprite_size_buf.write( self._sprite_size_data.tobytes()) self._sprite_size_changed = False if self._sprite_angle_changed: self._sprite_angle_buf.orphan() self._sprite_angle_buf.write( self._sprite_angle_data.tobytes()) self._sprite_angle_changed = False if self._sprite_color_changed: self._sprite_color_buf.orphan() self._sprite_color_buf.write( self._sprite_color_data.tobytes()) self._sprite_color_changed = False if self._sprite_sub_tex_changed: self._sprite_sub_tex_buf.orphan() self._sprite_sub_tex_buf.write( self._sprite_sub_tex_data.tobytes()) self._sprite_sub_tex_changed = False self._vao1.render(gl.GL_TRIANGLE_STRIP, instances=len(self.sprite_list))
def load_texture(file_name): texture = pyglet.image.load(file_name).get_texture() gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) return pyglet.graphics.TextureGroup(texture)
def load_textures(file_name: str, image_location_list: PointList, mirrored: bool = False, flipped: bool = False, scale: float = 1) -> List['Texture']: """ Load a set of textures off of a single image file. Args: :file_name: Name of the file. :image_location_list: List of image locations. Each location should be a list of four floats. ``[x, y, width, height]``. :mirrored=False: If set to true, the image is mirrored left to right. :flipped=False: If set to true, the image is flipped upside down. Returns: :list: List of textures loaded. Raises: :SystemError: """ source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size texture_info_list = [] for image_location in image_location_list: x, y, width, height = image_location if width <= 0: raise ValueError( "Texture has a width of {}, must be > 0.".format(width)) if x > source_image_width: raise ValueError("Can't load texture starting at an x of {} " "when the image is only {} across.".format( x, source_image_width)) if y > source_image_height: raise ValueError("Can't load texture starting at an y of {} " "when the image is only {} high.".format( y, source_image_height)) if x + width > source_image_width: raise ValueError("Can't load texture ending at an x of {} " "when the image is only {} wide.".format( x + width, source_image_width)) if y + height > source_image_height: raise ValueError("Can't load texture ending at an y of {} " "when the image is only {} high.".format( y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) # image = _trim_image(image) if mirrored: image = PIL.ImageOps.mirror(image) if flipped: image = PIL.ImageOps.flip(image) image_width, image_height = image.size texture = gl.GLuint(0) gl.glGenTextures(1, ctypes.byref(texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, texture) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR) image_width *= scale image_height *= scale texture_info_list.append(Texture(texture, width, height)) return texture_info_list
def _apply_filter_settings(self, *args, **kwargs): super(TextureCube, self)._apply_filter_settings() with self: gl.glTexParameterf(self.target, gl.GL_TEXTURE_WRAP_R, gl.GL_CLAMP_TO_EDGE)
def load_texture(file_name, x=0, y=0, width=0, height=0, scale=1): """ Load image from disk and create a texture. Args: :filename (str): Name of the file to that holds the texture. Returns: Integer identifier for the new texture. Raises: None >>> import arcade >>> arcade.open_window("Drawing Example", 800, 600) >>> name = "examples/images/meteorGrey_big1.png" >>> texture = load_texture(name, 1, 1, 50, 50) >>> arcade.close_window() """ # See if we already loaded this file, and we can just use a cached version. if file_name in load_texture.texture_cache: return load_texture.texture_cache[file_name] source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size if x != 0 or y != 0 or width != 0 or height != 0: if x > source_image_width: raise SystemError("Can't load texture starting at an x of {} " "when the image is only {} across." .format(x, source_image_width)) if y > source_image_height: raise SystemError("Can't load texture starting at an y of {} " "when the image is only {} high." .format(y, source_image_height)) if x + width > source_image_width: raise SystemError("Can't load texture ending at an x of {} " "when the image is only {} wide." .format(x + width, source_image_width)) if y + height > source_image_height: raise SystemError("Can't load texture ending at an y of {} " "when the image is only {} high." .format(y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) else: image = source_image # image = _trim_image(image) image_width, image_height = image.size image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1) texture = GL.GLuint(0) GL.glGenTextures(1, ctypes.byref(texture)) GL.glBindTexture(GL.GL_TEXTURE_2D, texture) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) # Appveyor work-around appveyor = True if not appveyor: GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_BORDER) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_BORDER) else: GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR) GLU.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA, image_width, image_height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, image_bytes) image_width *= scale image_height *= scale result = Texture(texture, image_width, image_height) load_texture.texture_cache[file_name] = result return result
def load_textures(file_name, image_location_list, mirrored=False, flipped=False): """ Load a set of textures off of a single image file. Args: :file_name: Name of the file. :image_location_list: List of image locations. Each location should be a list of four numbers. ``[x, y, width, height]``. :mirrored=False: If set to true, the image is mirrored left to right. :flipped=False: If set to true, the image is flipped upside down. Returns: :list: List of textures loaded. Raises: :SystemError: >>> import arcade >>> arcade.open_window("Drawing Example", 800, 600) >>> image_location_list = [[591, 5, 64, 93], ... [655, 10, 75, 88], ... [730, 7, 54, 91], ... [784, 3, 59, 95], ... [843, 6, 56, 92]] >>> texture_info_list = arcade.load_textures( \ "examples/images/character_sheet.png", image_location_list) >>> arcade.close_window() """ source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size texture_info_list = [] for image_location in image_location_list: x, y, width, height = image_location if x > source_image_width: raise SystemError("Can't load texture starting at an x of {} " "when the image is only {} across." .format(x, source_image_width)) if y > source_image_height: raise SystemError("Can't load texture starting at an y of {} " "when the image is only {} high." .format(y, source_image_height)) if x + width > source_image_width: raise SystemError("Can't load texture ending at an x of {} " "when the image is only {} wide." .format(x + width, source_image_width)) if y + height > source_image_height: raise SystemError("Can't load texture ending at an y of {} " "when the image is only {} high." .format(y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) # image = _trim_image(image) if mirrored: image = PIL.ImageOps.mirror(image) if flipped: image = PIL.ImageOps.flip(image) image_width, image_height = image.size image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1) texture = GL.GLuint(0) GL.glGenTextures(1, ctypes.byref(texture)) GL.glBindTexture(GL.GL_TEXTURE_2D, texture) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) # Appveyor work-around appveyor = True if not appveyor: GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_BORDER) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_BORDER) else: GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR) GLU.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA, image_width, image_height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, image_bytes) texture_info_list.append(Texture(texture, width, height)) return texture_info_list
def load_texture(file_name: str, x: float = 0, y: float = 0, width: float = 0, height: float = 0, mirrored: bool = False, flipped: bool = False, scale: float = 1) -> arcade.Texture: """ Load image from disk and create a texture. Args: :filename (str): Name of the file to that holds the texture. :x (float): X position of the crop area of the texture. :y (float): Y position of the crop area of the texture. :width (float): Width of the crop area of the texture. :height (float): Height of the crop area of the texture. :scale (float): Scale factor to apply on the new texture. Returns: The new texture. Raises: None >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> name = "arcade/examples/images/meteorGrey_big1.png" >>> texture1 = load_texture(name, 1, 1, 50, 50) >>> texture2 = load_texture(name, 1, 1, 50, 50) >>> texture = load_texture(name, 200, 1, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture starting at an x of 200 when the image is only 101 across. >>> texture = load_texture(name, 1, 50, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture ending at an y of 100 when the image is only 84 high. >>> texture = load_texture(name, 1, 150, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture starting at an y of 150 when the image is only 84 high. >>> texture = load_texture(name, 0, 0, 400, 50) Traceback (most recent call last): ... ValueError: Can't load texture ending at an x of 400 when the image is only 101 wide. >>> arcade.close_window() """ # See if we already loaded this file, and we can just use a cached version. cache_name = "{}{}{}{}{}{}{}{}".format(file_name, x, y, width, height, scale, flipped, mirrored) if cache_name in load_texture.texture_cache: return load_texture.texture_cache[cache_name] source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size if x != 0 or y != 0 or width != 0 or height != 0: if x > source_image_width: raise ValueError("Can't load texture starting at an x of {} " "when the image is only {} across.".format( x, source_image_width)) if y > source_image_height: raise ValueError("Can't load texture starting at an y of {} " "when the image is only {} high.".format( y, source_image_height)) if x + width > source_image_width: raise ValueError("Can't load texture ending at an x of {} " "when the image is only {} wide.".format( x + width, source_image_width)) if y + height > source_image_height: raise ValueError("Can't load texture ending at an y of {} " "when the image is only {} high.".format( y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) else: image = source_image # image = _trim_image(image) if mirrored: image = PIL.ImageOps.mirror(image) if flipped: image = PIL.ImageOps.flip(image) image_width, image_height = image.size image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1) texture = gl.GLuint(0) gl.glGenTextures(1, ctypes.byref(texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, texture) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) glu.gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGBA, image_width, image_height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, image_bytes) image_width *= scale image_height *= scale result = Texture(texture, image_width, image_height) load_texture.texture_cache[cache_name] = result return result
def load_texture(file_name: str, x: float=0, y: float=0, width: float=0, height: float=0, mirrored: bool=False, flipped: bool=False, scale: float=1) -> Texture: """ Load image from disk and create a texture. Note, if the code is to load only part of the image, the given x, y coordinates will start with the origin (0, 0) in the upper left of the image. When drawing, Arcade uses (0, 0) in the lower left corner when drawing. Be careful about this reversal. For a longer explanation of why computers sometimes start in the upper left, see: http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5 Args: :filename (str): Name of the file to that holds the texture. :x (float): X position of the crop area of the texture. :y (float): Y position of the crop area of the texture. :width (float): Width of the crop area of the texture. :height (float): Height of the crop area of the texture. :scale (float): Scale factor to apply on the new texture. Returns: The new texture. Raises: None >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> name = "arcade/examples/images/meteorGrey_big1.png" >>> texture1 = load_texture(name, 1, 1, 50, 50) >>> texture2 = load_texture(name, 1, 1, 50, 50) >>> texture = load_texture(name, 200, 1, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture starting at an x of 200 when the image is only 101 across. >>> texture = load_texture(name, 1, 50, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture ending at an y of 100 when the image is only 84 high. >>> texture = load_texture(name, 1, 150, 50, 50) Traceback (most recent call last): ... ValueError: Can't load texture starting at an y of 150 when the image is only 84 high. >>> texture = load_texture(name, 0, 0, 400, 50) Traceback (most recent call last): ... ValueError: Can't load texture ending at an x of 400 when the image is only 101 wide. >>> arcade.close_window() """ # See if we already loaded this file, and we can just use a cached version. cache_name = "{}{}{}{}{}{}{}{}".format(file_name, x, y, width, height, scale, flipped, mirrored) if cache_name in load_texture.texture_cache: return load_texture.texture_cache[cache_name] source_image = PIL.Image.open(file_name) source_image_width, source_image_height = source_image.size if x != 0 or y != 0 or width != 0 or height != 0: if x > source_image_width: raise ValueError("Can't load texture starting at an x of {} " "when the image is only {} across." .format(x, source_image_width)) if y > source_image_height: raise ValueError("Can't load texture starting at an y of {} " "when the image is only {} high." .format(y, source_image_height)) if x + width > source_image_width: raise ValueError("Can't load texture ending at an x of {} " "when the image is only {} wide." .format(x + width, source_image_width)) if y + height > source_image_height: raise ValueError("Can't load texture ending at an y of {} " "when the image is only {} high." .format(y + height, source_image_height)) image = source_image.crop((x, y, x + width, y + height)) else: image = source_image # image = _trim_image(image) if mirrored: image = PIL.ImageOps.mirror(image) if flipped: image = PIL.ImageOps.flip(image) image_width, image_height = image.size # image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1) texture = gl.GLuint(0) gl.glGenTextures(1, ctypes.byref(texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, texture) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR) # glu.gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGBA, # image_width, image_height, # gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, image_bytes) image_width *= scale image_height *= scale result = Texture(texture, image_width, image_height, file_name) load_texture.texture_cache[cache_name] = result return result
def _draw_rects(shape_list: List[Sprite], vertex_buffer: VertexBuffer, texture_coord_buffer: TextureCoordBuffer, color_buffer: ColorBuffer, change_x: float, change_y: float): """ Draw a set of rectangles using vertex buffers. This is more efficient than drawing them individually. """ if len(shape_list) == 0: return gl.glEnable(gl.GL_BLEND) gl.glEnable(gl.GL_TEXTURE_2D) # As soon as this happens, can't use drawing commands gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glHint(gl.GL_POLYGON_SMOOTH_HINT, gl.GL_NICEST) gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST) vertex_buffer.bind() color_buffer.bind() texture_coord_buffer.bind() gl.glLoadIdentity() gl.glTranslatef(change_x, change_y, 0) # Ideally, we want to draw these in "batches." # We seek to find groups of squares with the same texture. Then draw # them all at once. last_texture_id = None batch_count = 0 offset = 0 batch_offset = 0 texture_coord_vbo_id = None for shape in shape_list: if shape.texture.texture_id != last_texture_id: # Ok, if the 'if' triggered above, we are now looking at a different # texture than we looked at with the last loop. So draw the last # "batch" of squares. We'll start a new batch with the current # square but not draw it yet if batch_count > 0: _render_rect_filled(batch_offset, last_texture_id, texture_coord_vbo_id, batch_count) batch_count = 0 batch_offset = offset last_texture_id = shape.texture.texture_id batch_count += 4 offset += 4 # Draw the last batch, if it exists _render_rect_filled(batch_offset, last_texture_id, texture_coord_vbo_id, batch_count) # Must do this, or drawing commands won't work. gl.glDisable(gl.GL_TEXTURE_2D)
def __init__(self, font_name, size): FT = freetype2.FT # easier access to constants self.lib = freetype2.get_default_lib() # Load font and check it is monotype face = self.lib.find_face(font_name) face.set_char_size(size=size, resolution=90) if face.face_flags & FT.FACE_FLAG_FIXED_WIDTH == 0: raise 'Font is not monotype' # Determine largest glyph size width, height, ascender, descender = 0, 0, 0, 0 for c in range(32, 128): face.load_char(c, FT.LOAD_RENDER | FT.LOAD_FORCE_AUTOHINT) bitmap = face.glyph.bitmap width = max(width, bitmap.width) ascender = max(ascender, face.glyph.bitmap_top) descender = max(descender, bitmap.rows - face.glyph.bitmap_top) height = ascender + descender # Generate texture data Z = numpy.zeros((height * 6, width * 16), dtype=numpy.ubyte) for j in range(6): for i in range(16): face.load_char(32 + j * 16 + i, FT.LOAD_RENDER | FT.LOAD_FORCE_AUTOHINT) bitmap = face.glyph.bitmap.copy_with_array() x = i * width + face.glyph.bitmap_left y = j * height + ascender - face.glyph.bitmap_top Z[y:y + bitmap.rows, x:x + bitmap.width].flat = bitmap.buffer # Bound texture self.texture_ids = (pyglet.gl.GLuint * 1)() gl.glGenTextures(1, self.texture_ids) self.texture_id = self.texture_ids[0] gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture_id) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, Z.shape[1], Z.shape[0], 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, Z.tostring()) # Generate display lists dx, dy = width / float(Z.shape[1]), height / float(Z.shape[0]) self.base = gl.glGenLists(8 * 16) for i in range(8 * 16): c = chr(i) x = i % 16 y = i // 16 - 2 gl.glNewList(self.base + i, gl.GL_COMPILE) if (c == '\n'): gl.glPopMatrix() gl.glTranslatef(0, -height, 0) gl.glPushMatrix() elif (c == '\t'): gl.glTranslatef(4 * width, 0, 0) elif (i >= 32): gl.glBegin(gl.GL_QUADS) gl.glTexCoord2d((x) * dx, (y + 1) * dy), gl.glVertex2d(0, -height) gl.glTexCoord2d((x) * dx, (y) * dy), gl.glVertex2d(0, 0) gl.glTexCoord2d((x + 1) * dx, (y) * dy), gl.glVertex2d(width, 0) gl.glTexCoord2d((x + 1) * dx, (y + 1) * dy), gl.glVertex2d(width, -height) gl.glEnd() gl.glTranslatef(width, 0, 0) gl.glEndList()
def _apply_filter_settings(self): super(DepthTexture, self)._apply_filter_settings() gl.glTexParameterf(self.target, gl.GL_TEXTURE_COMPARE_MODE, gl.GL_COMPARE_REF_TO_TEXTURE)
def _draw_rects(shape_list: List[Sprite], vertex_vbo_id: gl.GLuint, texture_coord_vbo_id: gl.GLuint, change_x: float, change_y: float): """ Draw a set of rectangles using vertex buffers. This is more efficient than drawing them individually. """ if len(shape_list) == 0: return gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_TEXTURE_2D ) # As soon as this happens, can't use drawing commands # gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) # gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glHint(gl.GL_POLYGON_SMOOTH_HINT, gl.GL_NICEST) gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST) # gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # gl.glMatrixMode(gl.GL_MODELVIEW) # gl.glDisable(gl.GL_BLEND) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertex_vbo_id) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, texture_coord_vbo_id) last_alpha = shape_list[0].alpha gl.glColor4f(1, 1, 1, last_alpha) gl.glLoadIdentity() # gl.glLoadIdentity() gl.glTranslatef(change_x, change_y, 0) # Ideally, we want to draw these in "batches." # We seek to find groups of squares with the same texture. Then draw # them all at once. last_texture_id = None last_alpha = 1 batch_count = 0 offset = 0 batch_offset = 0 texture_coord_vbo_id = None for shape in shape_list: if shape.texture.texture_id != last_texture_id or shape.alpha != last_alpha: # Ok, if the 'if' triggered above, we are now looking at a different # texture than we looked at with the last loop. So draw the last # "batch" of squares. We'll start a new batch with the current # square but not draw it yet if batch_count > 0: gl.glColor4f(1, 1, 1, last_alpha) _render_rect_filled(batch_offset, last_texture_id, texture_coord_vbo_id, batch_count) batch_count = 0 batch_offset = offset last_texture_id = shape.texture.texture_id last_alpha = shape.alpha batch_count += 4 offset += 4 # Draw the last batch, if it exists _render_rect_filled(batch_offset, last_texture_id, texture_coord_vbo_id, batch_count) gl.glDisable(gl.GL_TEXTURE_2D)