Оптимизированная 2D мозаика, прокручивающая в OpenGL

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

До сих пор я попробовал:

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

  • Разделение карты в Дисплейные списки, половина размера экрана, затем отборе дисплейных списков (все еще замедляется для 2-направленной прокрутки, превышает ограничения, не эффективно),

Любой совет ценится, но в особенности я задаюсь вопросом:

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

Спасибо :)

9
задан Community 23 May 2017 в 10:27
поделиться

1 ответ

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

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

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

Для рисования статических плиток (плитки, которые составляют весь уровень) я бы использовал статический буфер (хранящийся в объекте буфера), который содержит каждую позицию плитки (x, y, слой) и индекс к данным текстуры атласа (i). Поскольку ваш атлас текстуры содержит плитки фиксированного размера 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 . Вы можете расчленить меньше данных и сэкономить память графического процессора, вычисляя атрибуты вершин в шейдере).

В любом случае лучше не дублировать данные тайлов текстуры и сохранить атлас текстуры, а также 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 для перемещения камеры по уровню, увеличения / уменьшения и т. Д. Удачи!

10
ответ дан 4 December 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: