30 лет эволюции игровой графики: секреты оптимизации

Игровые миры поражают своей масштабностью и детализацией. Объём мира Minecraft, например, в семь раз превышает объём Земли! Как же разработчикам удаётся создавать такие сложные миры, не жертвуя производительностью? Ответ кроется в 30-летней эволюции разработки игр.

Frustum Culling

Начнём с простейших методов оптимизации. Мир игры наполнен объектами, визуализация которых может быть упрощена. Взгляд игрока моделируется усечённым конусом (вьюпортом или frustum). Frustum определяется шестью плоскостями: левой, правой, верхней, нижней, ближней и дальней. Они задают поле зрения, определяя, какие объекты видны, а какие — нет.

Каждый объект, сколь бы сложной ни была его форма, можно упростить, представив в виде более простой фигуры, например, сферы (из-за простоты математических вычислений) или прямоугольника (для лучшего совмещения объектов). Используя упрощённую форму объекта (Simple Bounding Volume), проверяется его пересечение с frustum. Объекты, попадающие в поле зрения, отмечаются зелёным, остальные — красным. Этот метод значительно сокращает количество отрисовываемых объектов, особенно в мирах с сотнями объектов.

Однако Frustum Culling не всегда решает проблему оптимизации. Даже в современных играх, например, City Skylines 2, использующих эту технологию, наблюдается низкая частота кадров (FPS) даже на мощном железе. Frustum Culling — лишь первый шаг к оптимизации.

Occlusion Culling

Представим: мир, камера, объекты. Frustum Culling отсекает объекты за пределами поля зрения. Окклюзия же отсекает объекты, скрытые от камеры другими непрозрачными объектами (стенами, зданиями и т. д.). Для расчёта окклюзии используются объёмы окклюзии (Occlusion Volumes).

Разработчик вручную создаёт объёмный бокс внутри объекта (автомобиля, дерева, горы). Этот бокс распознаётся системой рендеринга. В идеале бокс точно повторяет форму объекта. Далее происходит проектирование объекта на экранное пространство (отрисовка на плоскости экрана). Стороны объекта могут использоваться как плоскости для создания frustum, как и при работе с камерой.

Процесс проверки окклюзии с использованием Occlusion Volumes выглядит так:

  1. Проверка релевантности оклюдеров (объектов, создающих окклюзию) с помощью frustum culling.
  2. Выбор количества оклюдеров для проверки (компромисс между временем проверки и точностью).
  3. Простой подход (как в Just Cause 2): проверка только ближайших объектов (bfbc — brute force box culling).

Этот простой метод неидеален. Если объект частично закрыт несколькими оклюдерами, он может остаться видимым. Тем не менее, понимание этой системы — отправная точка для изучения более продвинутых техник.

Буфер глубины и иерархический Z-буфер

При отрисовке сцены создаётся буфер глубины (depth buffer). Он регистрирует глубину каждого пикселя, позволяя GPU рендерить объекты в нужном порядке и не отрисовывать скрытые. Это позволяет создавать эффекты размытия, расфокусировки и т. д.

Зная глубину, можно не отрисовывать объекты, заведомо скрытые. Для этого ограничивающий объём объекта сравнивается с буфером глубины. Если глубина объекта больше существующей в буфере, объект отбрасывается, что существенно разгружает GPU.

Иерархический Z-буфер (HZB) создаётся путём уменьшения разрешения буфера глубины, создавая цепочку карт окклюзии с различным разрешением. Это ускоряет процесс чтения и сравнения.

Ранее, из-за ограничений GPU, часто использовалась программная растеризация (преобразование объёмных данных в пиксели на экране).

Hardware Occlusion Queries

GPU гораздо эффективнее отображает информацию, чем CPU. В 2011 году появилась возможность отправлять GPU запросы на окклюзию (Hardware Occlusion Queries). Идея заключалась в том, чтобы отрисовывать главные оклюдеры и отправлять запросы на видимость более мелких объектов.

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

Современные методы: TPS Occlusion Culling

Современные методы используют подход, похожий на тот, что применяется в Unreal Engine и Unity. Объекты, видимые на предыдущем кадре, с большой вероятностью будут видны и на текущем. Они используются как оклюдеры. Для учёта новых объектов используется TPS Occlusion Culling (two-pass occlusion culling). Второй проход учитывает то, что не было отрисовано на первом. Весь процесс выполняется на GPU, используя шейдеры для вызова отрисовки.

Современные инструменты упрощают процесс оптимизации, автоматизируя многие задачи. Понимание базовых принципов, описанных выше, помогает разработчикам создавать высокопроизводительные игры. Глубокое изучение темы — долгий путь, но базовые знания позволяют эффективно использовать современные инструменты.

Что будем искать? Например,программа