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