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

В данной статье мы познакомим вас с несколькими методами оптимизации, которые хорошо зарекомендовали себя при создании интерактивных веб-приложений. Эта глава основана на презентации Soft8Soft на конференции Verge3Day Europe 2019.

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

В основе 3D-приложений лежит Геометрия, поскольку она формирует основу модели. Чтобы получить более гладкие отражения и ускорить рендеринг, необходимо, чтобы сетка была как можно более равномерной, а топология правильной. Вначале следует определиться с уровнем детализации сцены и придерживаться его на протяжении всего процесса моделирования.

Recommended topology for WebGL applications

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

Using smooth groups to implement geometry creases

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

Optimizing cylindrical models for WebGL

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

Managing level of detail for real-time

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

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

Using normal maps for optimizing WebGL scenes

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

Normal map artifacts and possible solutions

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

Recommended way to deal with normal map artifacts

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

When to use normal maps with WebGL applications

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

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

Common textures used in WebGL apps

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

Packing textures into RGBA channels of a single image

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

Packing black/white textures into alpha channel

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

Optimizing UV space for better WebGL performance

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

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

Using vertex colors to optimize WebGL performance

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

Using vertex colors in PBR pipeline

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

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

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

Replacing textures at run time with Verge3D Puzzles

Вот пример такой оптимизации. Все эти шины представлены только одним материалом и сконфигурированы путем замены его текстур.

Example of replacing textures at run time

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

Mixing shaders in WebGL

Draw Calls (вызовы отрисовки)

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

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

Reducing the number of materials for WebGL

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

Using armatures to reduce the number of draw calls in your 3D app

HDR-освещение

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

Using HDR environment texture instead of light sources for better WebGL performance

Тени

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

Comparison of dynamic and baked shadows in different cases

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

Using baked textures as replacement for ambient occlusion and shadows

Смотрите также

Ознакомьтесь с разделом Тонкости производительности, чтобы узнать, как обнаружить проблемные места в производительности вашего приложения, и с разделом Сжатие ассетов, чтобы узнать, как сделать ваши сцены еще более компактными.

Остались вопросы?

Задайте их на нашем форуме!