Создание и загрузка .pngs в RGBA4444 RGBA5551 для openGL - PullRequest
2 голосов
/ 05 января 2010

Я создаю игру openGL и до сих пор я использовал .pngs в формате RGBA8888 в качестве листов текстур, но они слишком требовательны к памяти, и мое приложение часто падает. Я читал на сайте Apple, что такой формат можно использовать только тогда, когда требуется слишком высокое качество, и рекомендую вместо этого использовать RGBA4444 и RGBA5551 (я уже конвертировал свои текстуры в PVR, но потеря качества в большинстве листов спрайтов слишком велика).

Мне нужно использовать только GL_UNSIGNED_SHORT_5_5_5_1 или GL_UNSIGNED_SHORT_4_4_4_4 в моем вызове glTexImage2D внутри моего загрузчика текстур, чтобы загрузить свои текстуры, но мне нужно преобразовать мои листы текстур в RGBA4444 и RGBA5551, и я могу понять это.

Ответы [ 6 ]

5 голосов
/ 05 января 2010

Вы можете рассмотреть возможность использования PVRTexTool для Windows в Imagination. Это специально для создания текстур PVR в каждом поддерживаемом цветовом формате. Он может создавать как сжатые текстуры PVRTC (то, что вы называете «PVR»), так и несжатые текстуры в 8888, 5551, 4444 и т. Д.

Однако, он не выводит PNG (только PVR), поэтому ваш код загрузки мог бы измениться. Кроме того, иногда PVR намного больше, чем PNG, потому что пиксели в PNG сжимаются с использованием сжатия с выдуванием.

Поскольку вы, скорее всего, используете OS X, вы можете использовать Darwine (теперь WineBottler) для запуска его (и других программ Windows) в OS X.

Вам нужно будет зарегистрироваться в качестве разработчика Imagination , прежде чем вы сможете скачать PVRTexTool. Регистрация и инструмент бесплатны.

После того, как вы его настроите, он станет довольно безболезненным и даст вам приличный графический интерфейс для работы с PVR.

5 голосов
/ 05 января 2010

Используя ImageMagick , вы можете создавать файлы PNG RGBA4444, выполнив:

convert source.png -depth 4 destination.png

Вы можете получить ImageMagick от MacPorts .

4 голосов
/ 21 августа 2011

Вы также можете посмотреть, как оптимизировать RGBA8888 для преобразования в RGBA4444 с использованием дизеринга Флойд-Штайнберга в GIMP: http://www.youtube.com/watch?v=v1xGYecsnX0

3 голосов
/ 06 января 2010

Серьезно? Есть библиотеки для такого рода конвертации. Но, честно говоря, это немного сложновато. Существуют библиотеки, использующие 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, но это не должно влиять на результат функции, поскольку она перепаковывает в том же порядке в буфер dest.

2 голосов
/ 20 ноября 2010

Вы также можете использовать http://www.texturepacker.com для конвертации.

0 голосов
/ 07 ноября 2012

Вот оптимизированное на месте преобразование кода Криса, которое должно выполняться в 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...