在RGBA4444 RGBA5551中为openGL创建和加载.pngs

Jos*_*el. 2 iphone textures opengl-es

我正在创建一个openGL游戏,到目前为止,我一直在使用RGBA8888格式的.pngs作为纹理表,但那些内存太多,我的应用程序经常崩溃.我在Apple的网站上看到,只要需要太多质量就可以使用这种格式,并建议使用RGBA4444和RGBA5551(我已经将纹理转换为PVR,但在大多数精灵表中质量损失太大).

我只需要在我的纹理加载器类中的glTexImage2D调用中使用GL_UNSIGNED_SHORT_5_5_5_1或GL_UNSIGNED_SHORT_4_4_4_4来加载我的纹理,但是我需要将纹理表转换为RGBA4444和RGBA5551,我对如何实现这一点毫无头绪.

pgb*_*pgb 5

使用ImageMagick,您可以通过运行以下命令创建RGBA4444 PNG文件:

convert source.png -depth 4 destination.png
Run Code Online (Sandbox Code Playgroud)

你可以从MacPorts获得ImageMagick .


Jon*_*ric 5

您可以考虑使用Imagination的PVRTexTool for Windows.它专门用于以每种支持的颜色格式创建PVR纹理.它可以在8888,5551,4444等中创建PVRTC压缩纹理(您称之为"PVR")以及未压缩纹理.

但是,它不输出PNG(仅PVR),因此您的加载代码会发生变化.此外,有时PVR比PNG大得多,因为PNG中的像素通过放气压缩进行压缩.

由于您最有可能运行OS X,因此可以使用Darwine(现在的WineBottler)在OS X上运行它(以及其他Windows程序).

在下载PVRTexTool之前,您需要注册为Imagination开发人员.注册和工具都是免费的.

一旦你设置它,它是非常轻松的,它为你提供了一个体面的GUI来处理PVR.


Chr*_*cke 5

严重地?有库可以进行这种转换。但坦率地说,这有点扯。有一些库使用 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;
    } 
    
    Run Code Online (Sandbox Code Playgroud)

我所做的实际转换循环非常浪费,可以在一次通过中提取、转换和重新打包组件,从而生成更快的代码。我这样做是为了使转换明确且易于更改。另外,我不确定我是否以正确的方式获得了组件订单。所以它可能是 b、r、g、a,但它不应该影响函数的结果,因为它以相同的顺序重新打包到 dest 缓冲区中。