Подсчёт draw calls и способы сокращения

Draw call — это команда, которую графическая система отправляет видеокарте для отрисовки объекта. В контексте работы с графикой, включая PixiJS, количество draw calls может существенно повлиять на производительность приложения. Зачастую их количество увеличивается с ростом сложности сцены, что может привести к замедлению работы.

Для эффективного использования PixiJS важно минимизировать количество draw calls, потому что каждый draw call приводит к дополнительному времени на обработку, обмен данными между CPU и GPU, а также может создавать лишнюю нагрузку на видеокарту.

Что влияет на количество draw calls?

  1. Число объектов в сцене Каждый объект, отрисовываемый с уникальными текстурами или материалами, потребует отдельного draw call. Таким образом, если в сцене присутствуют сотни объектов с различными текстурами, их количество увеличивает нагрузку на систему.

  2. Использование различных текстур Разные текстуры, используемые на объектах, могут привести к созданию отдельных draw calls, даже если геометрия этих объектов идентична. Если объекты используют одну и ту же текстуру, они могут быть отрисованы за один draw call.

  3. Состояния рендеринга Изменения состояний, таких как изменения blend mode, цвета или прозрачности, также могут приводить к созданию дополнительных draw calls. Если сцена имеет множество таких изменений, то она может быть перерисована несколько раз.

  4. Использование фильтров и эффектов Применение фильтров или сложных эффектов также может увеличить количество draw calls, поскольку каждый эффект требует дополнительных вычислений и, следовательно, дополнительных команд для отрисовки.

Как сократить количество draw calls в PixiJS?

  1. Использование спрайтоватчей (sprite batching) PixiJS поддерживает технику спрайтоватчинга (batching), которая позволяет комбинировать несколько спрайтов, использующих одинаковые текстуры, в один draw call. Спрайтоватчинг — это процесс, при котором PixiJS собирает все объекты, использующие одну текстуру, и отрисовывает их за один вызов.

    Для этого необходимо использовать Container для группировки объектов, применяющих одинаковую текстуру. PixiJS автоматически объединит их в один draw call, если все объекты в контейнере используют одинаковую текстуру.

  2. Использование атласов текстур Атласы текстур — это объединённые изображения, которые включают в себя несколько текстур. Вместо того, чтобы загружать несколько текстур в память и выполнять отдельные draw calls для каждого из объектов, можно объединить их в один атлас, который используется всеми объектами.

    Это значительно уменьшает количество draw calls, так как все спрайты, использующие одинаковый атлас текстур, могут быть отрисованы за один вызов. В PixiJS можно легко загрузить атлас с помощью Texture.from() и затем использовать его для всех объектов.

  3. Использование тесселяции В случае, когда на сцене присутствует большое количество объектов с одинаковой геометрией, имеет смысл объединить эти объекты в один более сложный объект с помощью тесселяции. Это позволит сократить количество draw calls, поскольку все подобные объекты будут отрисованы за один раз.

    Для создания таких объектов можно использовать Graphics и объединить геометрию нескольких спрайтов в одну. Вместо того чтобы создавать отдельные объекты для каждого элемента, можно отрисовать сразу несколько объектов за один draw call.

  4. Использование фильтров и эффектов на уровне контейнера Применение фильтров и эффектов можно оптимизировать, применяя их на уровне контейнера, а не на каждом объекте в сцене. Когда фильтры применяются к отдельным объектам, каждый объект с фильтром потребует дополнительного draw call, но если фильтры применяются к контейнеру с несколькими объектами, их количество можно сократить.

  5. Использование mesh** объектов для оптимизации рендеринга** Mesh-объекты представляют собой более гибкие элементы, чем обычные спрайты, и могут быть использованы для рендеринга более сложных объектов. Вместо использования большого количества простых объектов (спрайтов), которые отрисовываются за отдельные draw calls, можно объединить их в один mesh, который будет отрисован за один вызов. Это особенно полезно, когда объекты на сцене имеют одинаковую текстуру и форму.

  6. Использование наложений и масок Иногда для того, чтобы уменьшить количество draw calls, можно использовать маски и наложения. Вместо того чтобы рисовать все элементы на сцене отдельно, можно создать единую маску, которая будет скрывать части объектов, оставляя видимыми только нужные части.

    Это позволяет уменьшить количество draw calls, так как маска будет применяться ко всем объектам одновременно, а не для каждого объекта в отдельности.

  7. Отсечение невидимых объектов PixiJS предоставляет встроенные механизмы для отсечения невидимых объектов (например, те, которые находятся за пределами камеры). Использование этих механизмов позволяет избежать лишних отрисовок, сокращая количество draw calls для объектов, которые не видны на экране.

    В PixiJS это достигается за счёт автоматической оптимизации с помощью frustum culling (отсечения объектов, не попадающих в поле зрения камеры).

Рекомендации для оптимизации производительности

  1. Использование объекта Renderer Для эффективного контроля за количеством draw calls, рекомендуется использовать объект Renderer и настраивать его параметры. В PixiJS можно использовать renderer.render() для рендеринга только тех объектов, которые должны быть отрисованы в данный момент, минимизируя нагрузку на систему.

  2. Профилирование производительности Для оценки количества draw calls и производительности приложения в PixiJS полезно использовать инструменты для профилирования, такие как PixiJS Stats. Он помогает отслеживать количество draw calls, частоту кадров и другие важные параметры, что помогает разработчику в оптимизации приложения.

  3. Оптимизация текстур и материалов Минимизация использования различных текстур и материалов помогает снизить количество draw calls. Чем меньше различных текстур используется на сцене, тем легче для рендерера сгруппировать объекты в один draw call.

  4. Избегание частых изменений состояний рендерера Частые изменения blend modes, прозрачности, фильтров и других параметров рендерера увеличивают количество draw calls. Поэтому необходимо минимизировать такие изменения, если это возможно.

Заключение

Оптимизация количества draw calls в PixiJS является важным аспектом работы с графикой в браузере. Снижение их числа не только улучшает производительность, но и повышает плавность работы приложения. Важным шагом к оптимизации является использование методов группировки объектов, таких как спрайтоватчинг, атласы текстур, а также применение фильтров и эффектов на уровне контейнера.