Pull to refresh

Оптимизируем ассеты для WebGL правильно

Reading time4 min
Views7.6K
Так часто бывает, что техники оптимизации, хорошо работающие для обычной десктопной или мобильной графики, не всегда дают нужный эффект в случае WebGL. В этой статье я собрал (а точнее перевёл на русский язык и изложил в текстовом виде нашу презентацию с Verge3Day) те методы повышения производительности, которые хорошо себя зарекомендовали при создании интерактивных веб-приложений.



Геометрия / Меши


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



При моделировании складок лучше использовать шейдинг-группы, а не добавлять больше полигонов.



При работе с цилиндрической моделью постарайтесь уменьшить количество полигонов ближе к центру.



Не перегружайте модель дополнительными деталями, которые пользователь все равно не увидит. Как показано на рисунке ниже, край, выделенный оранжевым цветом, определяет уровень детализации для всей модели, поэтому вы можете использовать его в качестве ориентира.



Карты нормалей


Распространенным способом оптимизации производительности WebGL является уменьшение количества полигонов путем создания карт нормалей.



Однако карты нормалей могут создавать видимые артефакты из-за ограниченной точности 8-битного изображения. Возможные решения этой проблемы показаны на картинке ниже, но их довольно сложно осуществить: использование изображения с более высокой точностью приведет к увеличению размера загружаемого файла, в то время как второй подход довольно трудоемкий и не гарантирует чистого результата. Третий подход иногда срабатывает в случае с шероховатыми поверхностями. В этом случае мы рекомендуем добавлять шум к вашим материалам, чтобы уменьшить возможные артефакты.



Исходя из нашего опыта, мы сделали вывод, что лучшим решением для глянцевых объектов является использование геометрии средней сложности с гладкими вертексными группами, причём без использования какой-либо карты нормалей.



Наконец, вот несколько случаев, когда вы можете использовать карту нормалей, а не очень подробный меш:

  • Ваш объект состоит из множества различных поверхностей.
  • У вас шероховатая поверхность, которая не дает видимых дефектов.
  • Ваши объекты такие отдаленные или маленькие, что пользователь не в состоянии заметить какие-либо артефакты.



Текстурирование


Вот типичный набор текстур, используемых в современной PBR модели освещения (и не только).



Как видите, большинство из них черно-белые. Поэтому вы можете комбинировать ч/б текстуры в RGBA-каналах одного изображения (всего до 4-х карт на одно изображение).



Если у вас есть только одна ч/б текстура, вы можете объединить ее с любой существующей текстурой RGB, упаковав ее в альфа-канал. Наконец, если у вас нет изображения для объединения, вы можете преобразовать ваше черно-белое изображение в формат jpeg со сжатием 95% и включенным режимом оттенков серого.



Еще один способ уменьшить размер текстуры — оптимизировать UV-развёртку. Чем компактнее ваша развертка, тем эффективнее ваше изображение будет использовать пространство текстуры. Это позволяет вам иметь более легковесные изображения без потери качества.



Вертексные цвета


Использование вершинных цветов вместо изображений — это эффективный способ ускорить загрузку и повысить общую производительность ваших WebGL-приложений. Единственный недостаток — вам придётся добавить несколько дополнительных ребер в вашу модель, чтобы разделить цвета одних и тех же вершин.



Вы также можете использовать цвета вершин для определения шероховатости, металличности или зеркальных поверхностей или любых других параметров. Ниже вы можете увидеть пример такого материала, в котором используются только цвета вершин.



Количество шейдеров


Очень важно, чтобы на вашей сцене было меньше разных материалов / шейдеров. Компиляция шейдеров в WebGL приводит к длительной загрузке, что особенно заметно в Windows. Кроме того, если у вас меньше шейдеров, движок будет тратить меньше времени на переключение между ними во время рендеринга, тем самым улучшая производительность.

Если у вас есть похожие материалы, которые отличаются только текстурами, вы можете использовать только один материал и загружать / менять его текстуры во время выполнения. Для этого вы можете использовать JavaScript или взять визуальный редактор логики, имеющийся в некоторых WebGL-фреймворках. Это не только оптимизирует количество шейдеров, но и уменьшит количество изображений, загружаемых при запуске приложения.



Вот пример такой оптимизации. Все четыре разновидности одной шины представлены одним материалом, и настраиваются путем замены текстур.



Чтобы уменьшить количество шейдеров, вы можете объединить 2 или более простых материала в один более сложный. Этот метод особенно эффективен, если вы планируете переключаться между этими материалами (например, создаете приложение-конфигуратор), и не просто переключаться, а плавно и красиво анимировать переход от одного материала к другому.



Draw-вызовы


Кроме того, есть еще один важный аспект — количество Draw-вызовов (они же draw calls и вызовы отрисовки). Это примерно соответствует количеству отдельных объектов, если для каждого объекта назначен только один материал, в то время как объектам с несколькими материалами требуется еще больше вызовов для их визуализации.

Поэтому вы должны стремиться объединять сетки, когда это возможно, и использовать меньше уникальных материалов, чтобы уменьшить количество вызовов отрисовки и повысить производительность.



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



HDR освещение


Это помогает значительно улучшить производительность, если вы освещаете свою сцену только с помощью изображения HDR, без использования каких-либо источников света. Файл HDR может весить менее 1 Мб.



Тени


Используйте динамические тени только тогда, когда они помогают представить ваш объект в лучшем виде. На рисунке ниже показаны динамические тени из нашей демки Industrial Robot. Поскольку в этом приложении вращается сама модель, а не камера, тени не могут скрыть какую-либо часть объекта от пользователя и отлично подчёркивают форму робота. С другой стороны, такие же тени в демке Scooter будут затенять многие детали модели.



Отсюда мы делаем вывод: если ваш объект не перемещается в приложении, вы можете запечь карты теней и ambient occlusion и назначить их на плоскость, расположенную под объектом. Такое решение будет более производительным и выглядеть качественнее, чем при использовании динамических теней.



На этом всё. Если у вас есть ещё какие-нибудь советы, которые могут помочь с производительностью WebGL, пишите в комментариях.
Tags:
Hubs:
Total votes 18: ↑17 and ↓1+16
Comments5

Articles