openGL Создание текстурного атласа во время выполнения? - PullRequest
6 голосов
/ 28 марта 2012

Итак, я настроил свой фреймворк в аккуратную маленькую систему, чтобы обернуть SDL, openGL и box2D все вместе для 2D-игры.

Теперь, как это работает, я создаю объект класса «GameObject», указываю «исходный PNG», а затем он автоматически создает текстуру openGL и тело box2d того же размера.

Теперь я беспокоюсь о том, нужно ли мне рендерить много разных текстур на экране.

Можно ли загрузить все мои листы спрайтов во время выполнения, а затем сгруппировать их все вместе в одну текстуру?Если так, то как?И что было бы хорошим способом реализовать это (чтобы мне не пришлось вручную указывать какие-либо параметры или что-либо еще).

Причина, по которой я хочу сделать это во время выполнения, а не предварительно, заключается в том, чтотак что я могу легко загрузить вместе все (или большинство) плиток, врагов и т. д. определенного уровня в одну текстуру, потому что на каждом уровне не будет одинаковых врагов.Это также облегчило бы весь процесс создания искусства.

1 Ответ

7 голосов
/ 28 марта 2012

Вероятно, существуют некоторые библиотеки для создания атласов текстур (оптимальная упаковка - нетривиальная задача) и преобразования старых координат текстуры в новые.

Однако, если вы хотите сделать это самостоятельно, вы, вероятно, сделаете что-то вроде этого:

  • Загрузка всех текстур с диска (ваш «исходный PNG») и получение буфера необработанных пикселей,
  • При необходимости, преобразовать все исходные текстуры в один и тот же формат пикселей,
  • Создайте новую текстуру, достаточно большую, чтобы вместить все существующие текстуры, вместе с соответствующим буфером для хранения данных пикселей
  • «Blit» данных пикселей из исходных изображений в новый буфер с заданным смещением (см. Ниже)
  • Создать текстуру как обычно, используя данные нового буфера.
  • При этом определите отображение из «старых» координат текстуры в «новые» координаты текстуры (должно быть просто записать смещения для каждого элемента атласа текстуры и выполнить быстрое преобразование). Вероятно, было бы также довольно легко сделать это внутри пиксельного шейдера, но некоторое профилирование потребовалось бы, чтобы посмотреть, стоит ли это накладных расходов на передачу дополнительных параметров.

Очевидно, что вы также хотите проверить, чтобы убедиться, что вы не делаете глупостей, например, дважды загружаете одну и ту же текстуру в атлас, но это не относится к этой процедуре.


Чтобы «скопировать» (скопировать) исходное изображение на целевое, вы должны сделать что-то вроде этого (при условии, что вы копируете текстуру 128x128 в текстуру атласа 512x512, начиная с (128, 0) на цели ):

unsigned char* source = new unsigned char[ 128 * 128 * 4 ]; // in reality, comes from your texture loader
unsigned char* target = new unsigned char[ 512 * 512 * 4 ];

int targetX = 128;
int targetY = 0;

for(int sourceY = 0; sourceY < 128; ++sourceY) {
    for(int sourceX = 0; sourceX < 128; ++sourceX) {
        int from = (sourceY * 128 * 4) + (sourceX * 4); // 4 bytes per pixel (assuming RGBA)
        int to = ((targetY + sourceY) * 512 * 4) + ((targetX + sourceX) * 4); // same format as source

        for(int channel = 0; channel < 4; ++channel) {
            target[to + channel] = source[from + channel];
        }
    }
}

Это очень простая реализация грубой силы: есть гораздо более быстрые, краткие и более умные способы копирования массива, но идея заключается в том, что вы в основном копируете содержимое исходной текстуры в целевую текстуру с заданной X и Y смещены. В конце концов, вы создадите новую текстуру, которая содержит старые текстуры.

Если математика индексирования не имеет для вас смысла, подумайте , как двумерный массив на самом деле индексируется в одномерном пространстве (например, в памяти компьютера).

Пожалуйста, прости любые ошибки. Это не рабочий код, а то, что я написал, не проверяя, компилируется ли он или запускается.


Поскольку вы используете SDL, я должен упомянуть, что у него есть хорошая функция, которая может вам помочь: SDL_BlitSurface. Вы можете создать SDL_Surface полностью в SDL и просто использовать SDL_BlitSurface, чтобы скопировать в него исходные поверхности, а затем преобразовать поверхность атласа в текстуру GL .

Он позаботится обо всей математике, а также может сделать преобразование формата для вас на лету.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...