Оптимизированная 2D прокрутка плитки в OpenGL - PullRequest
8 голосов
/ 29 апреля 2010

Я разрабатываю 2D-игру с боковой прокруткой, и мне нужно оптимизировать код тайлинга, чтобы получить лучшую частоту кадров. На данный момент я использую текстурный атлас и плитки 16x16 для разрешения экрана 480x320. Уровень прокручивается в обоих направлениях и значительно больше, чем 1 экран (тысячи пикселей). Я использую glTranslate для фактической прокрутки.

Пока я пробовал:

  • Рисование только экранных плиток с использованием glTriangles, 2 на квадратную плитку (слишком много накладных расходов)
  • Рисование всей карты в виде списка отображения (отлично на маленьком уровне, способ замедления на большом)

  • Разделение карты на списки отображения, равные половине размера экрана, затем отбраковка списков отображения (все еще замедляется при двунаправленной прокрутке, перерисовка неэффективна)

Любой совет приветствуется, но, в частности, мне интересно:

  • Я видел Vertex Arrays / VBO, предложенные для этого, потому что они динамические. Какой лучший способ воспользоваться этим? Если я просто сохраню 1 экран вершин плюс немного перерисовки, мне придется переписывать массив каждые несколько кадров, чтобы учесть изменение относительных координат (переместить все заново и добавить новые строки / столбцы). Если я использую больше оверрейда, это не кажется большой победой; это как идея списка отображения на половину экрана.
  • Дает ли glScissor какой-либо выигрыш, если используется на куче маленьких плиток, таких как этот, список отображения или массив вершин / VBO
  • Было бы лучше просто построить уровень из больших текстур, а затем использовать glScissor? Будет ли потеря экономии памяти мозаикой проблемой для разработки мобильных приложений, если я сделаю это (просто любопытно, я сейчас на ПК)? Этот подход был упомянут здесь

Спасибо:)

1 Ответ

9 голосов
/ 29 апреля 2010

Вот как я бы сделал для кодирования быстрого движка 2D-плиток:

Сначала я бы сделал четкое разделение между динамическими плитками (персонажами, предметами ..) и статическими (уровень).

Статические плитки:

Для рисования статических (плиток, которые формируют весь уровень), я бы использовал статический буфер (хранящийся в объекте буфера), который содержит каждую позицию тайла (x, y, слой) и индекс для текстуры атласа. данные (я). Поскольку ваш текстурный атлас содержит плитки фиксированного размера 16x16 пикселей, вы можете легко вычислить координаты текстуры вершинного шейдера для каждой вершины.

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

Это дало бы вам почти «бесплатную» отсечку тайлов, выполняемую на GPU, поскольку аппаратные средства отсечения очень быстрые. Даже если у вас есть большое количество плиток на вашем уровне, скажем, 30 * 20 (плиток / на экране) и около 50 экранов / уровень, это составит 30 000 плиток. Я думаю, что это все еще приемлемо (даже на младших графических процессорах. Кстати, вы нацеливаетесь на iPhone / Android? Если да, то в OpenGL ES 1.0 нет инстансинга / шейдеров, а OpenGL ES 2.0 не поддерживает инстансинг, но может использовать шейдеры, так что вы приходится разбирать данные экземпляра тайлов в VBO / IBO и использовать GL_TRIANGLES. Вы можете взорвать меньше данных и сэкономить память GPU, вычисляя атрибуты вершин в шейдере).

В любом случае вам лучше не дублировать данные текстурных плиток и хранить атлас текстур, а также VBO и IBO.

Динамические плитки:

Я бы использовал динамический VBO (и статический IBO, представляющий GL_TRIANGLES, то есть 0,1,2, 2,1,3, 0 + 4,1 + 4,2 + 4 ..,), представляющий позиции тайлов, Текстурные координаты, слои и обновите его с помощью видимых динамических плиток на экране с помощью glBufferSubData и рисовать эти плитки с помощью glDrawElements.

Конечно, это означает, что у вас есть максимальное количество динамических плиток, которые вы можете нарисовать за glDrawElements, поэтому, если вы наткнетесь на это ограничение, вам придется сделать второе обновление / отрисовку VBO.

Если ваша реализация OpenGL не поддерживает VBO / IBO (как в OpenGL ES 1.0), используйте вместо этого VA. Я не рекомендую использовать DL или немедленный режим (нет поддержки для OpenGL ES).

Наконец, используйте glOrtho для перемещения камеры по уровню, увеличения / уменьшения масштаба и т. Д. Удачи!

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