我从一个旧的电脑游戏中得到了一些纹理。它们被存储在一个巨大的文件中,并使用了简单的游程编码。我知道图像的宽度和高度,图像也有一些完全透明的部分。
一种纹理结构如下:
**-颜色Map:**有256种颜色,每种颜色包含4个字节。一个值用于b、g、r,一个值为零
**-纹素数据:**通常,每个字节对应于颜色Map中的一种颜色,但透明的纹素数据是用某种游程长度编码压缩的:
- 第一个值指示第一行开始有多少透明纹理元素
- 下面的值指示下面的字节中有多少字节对应于来自色彩Map表的纹理元素(字节5意味着你必须将接下来的5个字节Map到色彩Map表)。5个字节之后的值可以是另一个透明像素计数指示符,其后面将跟随另一个色彩像素计数。
- 但是如果该值是0xFE,则在该行中没有其它有色纹理像素。如果该行中的纹理像素少于图像宽度所给出的纹理像素,则其余纹理像素是透明的。
- 如果值为0xFF,则到达图像的末尾/最后一行。如果行少于图像高度,则其余的纹理像素是透明的。
例如,4 × 4纹理可以看起来像这样:
02 01 99 FE(两个透明像素,颜色99,一个透明像素填充宽度)
01 02 98 99 FE(一个透明像素,颜色98,颜色99,一个透明像素填充宽度)
00 01 99 01 02 98 99 FE(颜色99,一个透明像素,颜色98,颜色99)
02 02 99 98 FF(两个透明像素,颜色99,颜色98)
所以我认为,因为这是一个非常初级的压缩,也许有人知道它是否被称为一个特定的名称或什么?最重要的是,有没有一种方法可以上传这个“压缩”的数据到openGL?我知道,为此我必须指定一些编码的数据在openGL。
我已经写了一个算法把这些数据转换成普通的rgba数据。但是这需要比游戏实际指定的更多的图形内存(每个图像大约30%是透明的,可以用游程编码代替)。所以如果游戏没有把图像转换成所有的rgba,我也想找到一种方法。
有人能给予我吗?
2条答案
按热度按时间cfh9epnr1#
这只是一个调色板图像,使用RLE编码的空白空间。没有真正的名称。它像GIF只是没有那么好,但可能更容易解压缩。
我已经编写了一个算法来将这些数据转换为普通的RGBA数据。
然后你就完成了。上传到一个OpenGL纹理。
因此,如果游戏不是转换图像到所有的rgba,我也想找到一种方法。
你不能这样
虽然可以通过对调色板使用两个纹理或一个纹理与一个UBO/SSBO来在着色器中实现调色板,但不能在着色器中实现游程编码方案。
RLE在数据存储和批量解压缩方面很好,但是在随机访问方面就 * 糟糕 * 了。而随机访问正是纹理的工作方式。没有真实的的方法可以将纹理坐标Map到包含相应texel数据的内存地址。如果你不能做到这一点,你就不能访问texel。
实际的压缩纹理格式是这样设计的,你可以直接从纹理坐标到包含该纹理元素的数据块的确切内存地址。
pb3skfrl2#
你必须知道文件中的纹理元素是如何被索引的,但是你实际上可以在不解压缩的情况下访问数据,尽管你必须线性地遍历文件。你读它,比如说......“run”接“run”地读它的相关颜色,然后你用你刚刚读到的“run”中的纹理元素的数量来递增计数器。给定作为标量的像素索引(在平面数组中),然后可以将计数器与要访问的索引进行比较,同时:
你读下一个“运行”,并尽快:
你知道像素在“运行”范围内,你可以得到颜色。你可以用它来读取CPU和GPU上的数据,但在GPU端,每个线程都需要从开始读取数据,直到找到所需的像素。但由于数据仍然是压缩的,你得到了O(n)时间,基于你读取的“运行”次数,而不是像素数,这可能不是那么糟糕...或者你可能会找到一个更好的方法来读取数据,而不是线性访问它...:)我没有仔细研究你写的东西,所以我不能说这个方法会与你文件中的数据格式一起工作,但也许通过一些修补你能够让它工作。