我正在创建一个 openGL 游戏,到目前为止,我一直在使用 RGBA8888 格式的 .png 作为纹理表,但这些太占用内存了,而且我的应用程序经常崩溃。我在 Apple 网站上读到,这种格式仅在需要太多质量时才使用,并建议使用 RGBA4444 和 RGBA5551(我已经将纹理转换为 PVR,但大多数精灵表中的质量损失太大)。
我只需要在纹理加载器类中的 glTexImage2D 调用中使用 GL_UNSIGNED_SHORT_5_5_5_1 或 GL_UNSIGNED_SHORT_4_4_4_4 来加载我的纹理,但我需要将纹理表转换为 RGBA4444 和 RGBA5551,而且我对如何实现这一点一无所知。
严重地?有一些库可以进行这种转换。但坦率地说,这有点无聊。有些库使用 asm 或专门的 SSE 命令来加速这一过程,速度会很快,但在 C/C++ 中使用您自己的格式转换器非常容易。
您的基本流程是:
- 给定一个 RGBA8888 编码值的缓冲区
- 创建一个足够大的缓冲区来容纳 RGBA4444 或 RGBA5551 值。在这种情况下,很简单——尺寸减半。
-
循环源缓冲区,解包每个组件,重新打包为目标格式,并将其写入目标缓冲区。
void* rgba8888_to_rgba4444(
void* src, // IN, pointer to source buffer
int cb) // IN size of source buffer, in bytes
{
// this code assumes that a long is 4 bytes and short is 2.
//on some compilers this isnt true
int i;
// compute the actual number of pixel elements in the buffer.
int cpel = cb/4;
unsigned long* psrc = (unsigned long*)src;
// create the RGBA4444 buffer
unsigned short* pdst = (unsigned short*)malloc(cpel*2);
// convert every pixel
for(i=0;i<cpel; i++)
{
// read a source pixel
unsigned pel = psrc[i];
// unpack the source data as 8 bit values
unsigned r = p & 0xff;
unsigned g = (pel >> 8) & 0xff;
unsigned b = (pel >> 16) & 0xff;
unsigned a = (pel >> 24) & 0xff;
//convert to 4 bit vales
r >>= 4;
g >>= 4;
b >>= 4;
a >>= 4;
// and store
pdst[i] = r | g << 4 | b << 8 | a << 12;
}
return pdst;
}
我所做的实际转换循环非常浪费,可以在一次传递中提取、转换和重新打包组件,从而实现更快的代码。我这样做是为了使转换明确并且易于更改。另外,我不确定我是否以正确的方式获得了组件订单。因此它可能是 b、r、g、a,但它不应该影响函数的结果,因为它以相同的顺序重新打包到目标缓冲区中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)