我正在创建一个openGL游戏,到目前为止,我一直在使用RGBA8888格式的.pngs作为纹理表,但那些内存太多,我的应用程序经常崩溃。我在Apple的网站上看到,只要需要太多质量就可以使用这种格式,并建议使用RGBA4444和RGBA5551(我已经将纹理转换为PVR,但在大多数精灵表中质量损失太大)。
我只需要在我的纹理加载器类中的glTexImage2D调用中使用GL_UNSIGNED_SHORT_5_5_5_1或GL_UNSIGNED_SHORT_4_4_4_4来加载我的纹理,但我需要将纹理表转换为RGBA4444和RGBA5551,我对如何实现无能为力此
答案 0 :(得分:5)
使用ImageMagick,您可以运行以下命令创建RGBA4444 PNG文件:
convert source.png -depth 4 destination.png
您可以从MacPorts获取ImageMagick。
答案 1 :(得分:5)
您可以考虑在Windows上使用Imagination的PVRTexTool。它专门用于以每种支持的颜色格式创建PVR纹理。它可以在8888,5551,4444等中创建PVRTC压缩纹理(你称之为“PVR”)以及未压缩纹理。
但是,它不输出PNG(仅PVR),因此您的加载代码会发生变化。此外,有时PVR比PNG大得多,因为PNG中的像素是通过压缩压缩来压缩的。
由于您最有可能运行OS X,因此可以使用Darwine (now WineBottler)在OS X上运行它(以及其他Windows程序)。
在下载PVRTexTool之前,您需要register as an Imagination developer。注册和工具都是免费的。
一旦你进行了设置,它就会非常轻松,它为你提供了一个适合使用PVR的图形用户界面。
答案 2 :(得分:4)
您可能还想了解如何使用GIMP中的floyd-steinberg抖动优化RGBA8888以转换为RGBA4444:http://www.youtube.com/watch?v=v1xGYecsnX0
答案 3 :(得分:3)
真的?有些库可以进行这种转换。但坦率地说,这有点令人费解。有些库使用asm或专门的SSE命令来加速这个,这将是很快的,但它很容易在C / C ++中滚动你自己的格式转换器。 你的基本流程是:
遍历源缓冲区,解压缩每个组件,然后重新打包到目标格式,并将其写入目标缓冲区。
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,但它不应该影响函数的结果,因为它以相同的顺序重新包装到dest缓冲区。
答案 4 :(得分:2)
您也可以使用http://www.texturepacker.com进行转化。
答案 5 :(得分:0)
这是Chris'代码的优化就地转换,它应该以2倍的速度运行,但不是前进的。就地转换有助于通过降低内存峰值来避免崩溃。只是想我会分享以防任何人计划使用此代码。我已经测试过了,效果很好:
void* rgba8888_to_rgba4444( void* src, // IN, pointer to source buffer
int cb) // IN size of source buffer, in bytes
{
int i;
// compute the actual number of pixel elements in the buffer.
int cpel = cb/4;
unsigned long* psrc = (unsigned long*)src;
unsigned short* pdst = (unsigned short*)src;
// 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 = (pel << 8) & 0xf000;
unsigned g = (pel >> 4) & 0x0f00;
unsigned b = (pel >> 16) & 0x00f0;
unsigned a = (pel >> 28) & 0x000f;
// and store
pdst[i] = r | g | b | a;
}
return pdst;
}