# HG changeset patch # User Emmanuel Gil Peyrot # Date 1360176954 -3600 # Node ID 9e2cbb2c2c6412a47849a3665c518754176e108a # Parent 45e1a9a37e66edbbd6ba1ae6168ec7aa5c167fad Implement THTX, uncompressed textures stored inside ANM files, and use it instead of pyglet’s own wrapper. diff --git a/pytouhou/formats/thtx.py b/pytouhou/formats/thtx.py new file mode 100644 --- /dev/null +++ b/pytouhou/formats/thtx.py @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2013 Emmanuel Gil Peyrot +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + + +class Texture(object): + def __init__(self, width, height, fmt, data): + self.width = width + self.height = height + self.fmt = fmt + self.data = data diff --git a/pytouhou/ui/gamerenderer.py b/pytouhou/ui/gamerenderer.py --- a/pytouhou/ui/gamerenderer.py +++ b/pytouhou/ui/gamerenderer.py @@ -102,7 +102,7 @@ class GameRenderer(Renderer): glEnable(GL_DEPTH_TEST) for (texture_key, blendfunc), (nb_vertices, vertices, uvs, colors) in get_background_rendering_data(back): glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) - glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key].id) + glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key]) glVertexPointer(3, GL_FLOAT, 0, vertices) glTexCoordPointer(2, GL_FLOAT, 0, uvs) glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors) diff --git a/pytouhou/ui/renderer.pyx b/pytouhou/ui/renderer.pyx --- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -89,7 +89,7 @@ cdef class Renderer: nb_indices = len(indices) indices = pack(str(nb_indices) + 'H', *indices) glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) - glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key].id) + glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key]) glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, indices) diff --git a/pytouhou/ui/sprite.pyx b/pytouhou/ui/sprite.pyx --- a/pytouhou/ui/sprite.pyx +++ b/pytouhou/ui/sprite.pyx @@ -66,7 +66,7 @@ cpdef object get_sprite_rendering_data(o (x1, x2 , x3, x4), (y1, y2, y3, y4), (z1, z2, z3, z4), _ = vertmat.data - key = (sprite.anm.first_name, sprite.anm.secondary_name), sprite.blendfunc + key = sprite.anm.texture, sprite.blendfunc r, g, b = sprite.color values = ((x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4)), uvs, [r, g, b, sprite.alpha] * 4 sprite._rendering_data = key, values diff --git a/pytouhou/ui/texture.pyx b/pytouhou/ui/texture.pyx --- a/pytouhou/ui/texture.pyx +++ b/pytouhou/ui/texture.pyx @@ -15,10 +15,17 @@ from libc.stdlib cimport malloc, free import pyglet -from pyglet.gl import (glTexParameteri, - GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_LINEAR) +from pyglet.gl import (glTexParameteri, GL_TEXTURE_MIN_FILTER, + GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_BGRA, GL_RGBA, + GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV, + glGenTextures, glBindTexture, glTexImage2D, + GL_TEXTURE_2D) +from ctypes import c_uint, byref import os +from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere? + cdef class TextureManager: def __init__(self, loader=None): @@ -33,32 +40,24 @@ cdef class TextureManager: def preload(self, anm_wrapper): - try: - anms = anm_wrapper.anm_files - except AttributeError: - anms = anm_wrapper - - for anm in anms: - key = anm.first_name, anm.secondary_name - texture = self[key] + for anm in anm_wrapper: + anm.texture = self.load_png_texture(anm.first_name, anm.secondary_name) - def load_texture(self, key): + def load_png_texture(self, first_name, secondary_name): cdef char *image, *alpha, *new_data cdef unsigned int i, width, height, pixels - first_name, secondary_name = key - image_file = pyglet.image.load(first_name, file=self.loader.get_file(os.path.basename(first_name))) + width, height = image_file.width, image_file.height + image_data = image_file.get_data('RGB', width * 3) if secondary_name: alpha_file = pyglet.image.load(secondary_name, file=self.loader.get_file(os.path.basename(secondary_name))) assert (image_file.width, image_file.height) == (alpha_file.width, image_file.height) - width, height = image_file.width, image_file.height pixels = width * height - image_data = image_file.get_data('RGB', width * 3) alpha_data = alpha_file.get_data('RGB', width * 3) image = image_data alpha = alpha_data @@ -70,13 +69,56 @@ cdef class TextureManager: new_data[i*4+1] = image[i*3+1] new_data[i*4+2] = image[i*3+2] new_data[i*4+3] = alpha[i*3] - image_file = pyglet.image.ImageData(width, height, 'RGBA', new_data[:(pixels * 4)]) + data = new_data[:(pixels * 4)] free(new_data) + return Texture(width, height, -4, data) - texture = image_file.get_texture() + return Texture(width, height, -3, image_data) + + + def load_texture(self, key): + if not isinstance(key, Texture): + first_name, secondary_name = key + key = self.load_png_texture(first_name, secondary_name) - glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR) - glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) + if key.fmt == 1: + format_ = GL_BGRA + type_ = GL_UNSIGNED_BYTE + composants = GL_RGBA + elif key.fmt == 3: + format_ = GL_RGB + type_ = GL_UNSIGNED_SHORT_5_6_5 + composants = GL_RGB + elif key.fmt == 5: + format_ = GL_BGRA + type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV + composants = GL_RGBA + elif key.fmt == 7: + format_ = GL_LUMINANCE + type_ = GL_UNSIGNED_BYTE + composants = GL_LUMINANCE + elif key.fmt == -3: #XXX: non-standard, remove it! + format_ = GL_RGB + type_ = GL_UNSIGNED_BYTE + composants = GL_RGB + elif key.fmt == -4: #XXX: non-standard + format_ = GL_RGBA + type_ = GL_UNSIGNED_BYTE + composants = GL_RGBA + else: + raise Exception('Unknown texture type') - return texture + id_ = c_uint() + glGenTextures(1, byref(id_)) + glBindTexture(GL_TEXTURE_2D, id_.value) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) + glTexImage2D(GL_TEXTURE_2D, 0, + composants, + key.width, key.height, + 0, + format_, type_, + key.data) + + return id_.value