OpenGL. Заключительные мысли

  Дмитрий Бушуев  | 

  Обновл. 20 Дек 2020  | 

 962

 ǀ   4 

Создание игры «Breakout» дало нам представление о том, каково это — создавать в OpenGL нечто большее, нежели обычную техническую демку. Мы с нуля сделали полноценную 2D-игру, научились абстрагироваться от некоторых низкоуровневых графических концепций, использовать основные методы обнаружения столкновений, создавать частицы, и показали практический сценарий применения матрицы ортографической проекции. Всё это затрагивает идеи, принципы и представления, которые обсуждались на всех предыдущих уроках. Мы действительно не вдавались в изучение новых графических методов, а старались объединить все полученные до текущего момента знания в единое целое.

Создание небольшой игры, такой как «Breakout», может быть выполнено тысячами различных способов, и наш вариант является лишь одним из таковых. Чем игра становится больше, тем больше вы начинаете применять абстракции и шаблоны проектирования. Информацию для дальнейшего изучения применения абстракций и шаблонов проектирования приложений вы можете найти на этом замечательном сайте.

Имейте в виду, что создать игру с чрезвычайно чистым и хорошо продуманным кодом — очень трудно. Поэтому просто делайте свою игру так, как вы считаете правильным в данный момент времени. Чем больше вы практикуетесь в разработке игр, тем больше вы узнаете о новых и наиболее оптимальных подходах к решению проблем. Не позволяйте борьбе за создание идеального кода демотивировать вас; продолжайте программировать!

Оптимизация

Содержание этих уроков и законченный код игры были сфокусированы на как можно более простом объяснении используемых понятий, не вдаваясь при этом слишком глубоко в детали оптимизации. Мы перечислим некоторые из наиболее распространенных улучшений, которые вы найдете в современных 2D-играх. Они помогут вам повысить производительность приложения, когда ваша частота кадров (сокр. «fps» от англ. «frame per second») начнет падать:

   Спрайт-лист/Текстурный атлас. Вместо рендеринга спрайта с одной текстурой за один раз, мы объединяем все необходимые текстуры в одну большую текстуру (например, как в случае с растровым шрифтом) и выбираем с помощью текстурных координат нужный нам кусок. Переключение состояний текстур может быть дорогостоящим, поэтому спрайт-лист позаботится о том, чтобы мы реже переключались между текстурами; это также позволит графическому процессору более эффективно кэшировать текстуру в памяти для выполнения более быстрого поиска.

   Инстансинг. Вместо того, чтобы рендерить один прямоугольник за раз, мы могли бы сложить все подготовленные для визуализации спрайты в кучу, чтобы потом, при помощи инстансинга, отобразить их разом одним вызовом функции draw(). Это относительно легко сделать, так как каждый спрайт состоит из одних и тех же вершин, но отличается только матрицей модели; то, что мы можем легко включить в инстансированный массив. Это позволяет OpenGL визуализировать гораздо больше спрайтов за кадр. Инстансинг также можно использовать для рендеринга частиц и/или символов глифов.

   Треугольные полосы. Вместо рендеринга каждого прямоугольника в виде двух треугольников, мы могли бы рендерить их с помощью OpenGL-примитива TRIANGLE_STRIP, которому вместо 6 вершин нужно 4. Это экономит треть данных, отправляемых в графический процессор.

   Алгоритмы разбиения пространства. При проверке на наличие столкновений мы соотносим мяч с каждым из кирпичей на текущем уровне. Это пустая трата ресурсов процессора, так как мы легко можем сказать, что большинство кирпичей даже не приблизятся к мячу в текущем кадре. Используя алгоритмы разбиения пространства, такие как BSP-дерево, октодерево или k-d деревья, мы разбиваем видимое пространство на несколько меньших областей и сначала определяем, в какой области (областях) находится мяч. Затем мы проверяем столкновения между теми кирпичами, которые находятся в той же области, что и мяч, экономя при этом значительное количество проверок столкновений. Для такой простой игры, как «Breakout», это, скорее всего, будет излишним, но для более сложных игр с более сложными алгоритмами обнаружения столкновений — это значительно повысит производительность.

   Минимизация переключения состояний. Изменение состояния (например, связывание текстур или переключение шейдеров) обычно довольно дорогостоящие операции в OpenGL, поэтому нужно стараться избегать выполнения большого количества переключений состояний. Один из подходов к минимизации переключений состояний заключается в создании собственного менеджера состояний, который хранит текущее значение состояния OpenGL (например, какая текстура привязана) и переключается только в том случае, если это значение необходимо изменить; это предотвращает ненужные изменения состояний. Другой подход заключается в сортировке всех визуализируемых объектов по типу изменяемого состояния: сначала визуализируются все объекты с шейдером номер один, затем все объекты с шейдером номер два и так далее; это, конечно, может быть обобщено и для смешанных изменений состояния, текстурных связываний, переключателей фреймбуфера и т.д.

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

Будьте креативными


Теперь, когда вы увидели, как в OpenGL создается небольшая игра, вам предстоит создать свои собственные приложения. Многие из тех техник, которые мы обсуждали до сих пор (рендеринг спрайтов, обнаружение столкновений, постобработка, рендеринг текста и частиц), могут быть использованы в большинстве 2D- (и даже 3D-) игр. Теперь вам предстоит взять эти методы и комбинировать/модифицировать их в зависимости от того, как вы считаете правильным, и разработать свою собственную игру.

Удачи!

Примечание: Эти уроки являются адаптированным переводом уроков из ресурса LearnOpenGL, выполненные Дмитрием Бушуевым в качестве переводчика при содействии ресурса Ravesli. От себя лично хочу поблагодарить Дмитрия Бушуева и автора LearnOpenGL. Вы крутые ребята и делаете крутые вещи!

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (5 оценок, среднее: 5,00 из 5)
Загрузка...

Комментариев: 4

  1. Аватар Евгений:

    Дмитрий, а подскажите, пожалуйста, вот у Вас в гитхабе во многих местах есть пометки "исправление кодировки файла", как Вы это сделали? Гитхаб ломает комментарии на кириллице, а у Вас нет. И ещё, а будет туториал по git, тоже очень интересует? Спасибо за уроки =)

    1. Дмитрий Бушуев Дмитрий Бушуев:

      Открыл те файлы, кодировку которых ломал гитхаб, обычным блокнотом, далее выбрал "Сохранить как…" -> В нижней части окна сменить кодировку на "UTF-8".

      Насчет уроков по git — подумаем, спасибо за предложение 🙂

  2. Аватар ElementaryUnit:

    Поздравляю с окончанием уроков!)

    1. Дмитрий Бушуев Дмитрий Бушуев:

      Спасибо большое! 🙂

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *