15 апреля 2021

Сложный визуал в WebGL методом проб и ошибок

Наш техлид о том, как мы создавали key visual на проекте для АФК «Система»

WebGL в браузерах — уже достаточно распространённое явление.

В сети много примеров того, как разместить на экране сцену с вращающимся цветным кубом, например. Причём сделать это достаточно несложно, и это может вселить уверенность, что осталось просто «дорисовать сову».

На практике, естественно, это не совсем так.

Покажу вам это на примере нашего проекта по разработке корпоративного сайта для АФК Система. В нём мы как раз сделали ставку на ключевое визуальное сообщение, реализованное на WebGL. Теперь попробую рассказать, как мы к этому шли и что получили в результате.

Мы понимали, что у нас в руках достаточно мощный инструмент, который требует к себе особенного внимания.

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

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

Для начала попробовали реализовать программно создание и расположение тел ядра с их последующей анимацией. 

Такой путь в теории гарантировал нам полный контроль за производительностью. 

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

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

Основную работу со сценой выполнили в Cinema 4D, но оказалось, что все доступные варианты выгрузки плохо подходили нам — например, не экспортируется анимация, или такой формат не полностью поддерживается библиотекой импорта.

На помощь пришёл Blender — в него выгружали сцену из Cinema 4D, вносили некоторые изменения, связанные с разным уровнем поддержки форматов, и уже из Blender выгружали в веб в полностью совместимом формате.

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

Поэтому главное по части визуальных эффектов плюс интерактив оставалось сделать уже на WebGL.

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

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

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

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

Нам обязательно надо было придать живость картинке, которая на текущий момент состояла из простых форм, материалов и цветов. Нужен был свет, тени, рассеивание, свечение — всё то, что делает картинку живой.

Тут в игру вступает другой мощный инструмент — шейдеры. И вновь для нас это оказалось очень сложной задачей. 

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

И действительно, эффект bloom, эффект ambient occlusion дали отличное улучшение «графония», но ценой значительного ухудшения производительности. Дело в том, что эффекты постобработки накладываются на готовую картинку, и это весьма затратно. К тому же, это особенно проявлялось на HiDPI-экранах, где количество обрабатываемой информации кратно возрастало. 

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

Поэтому было принято решение оставить текущую реализацию до лучших времён и воспользоваться чем-то более доступным.

Результатом стало решение со вступительным видео и несколькими слоями png-изображений для ховера по элементам ядра и старый добрый тег map для разметки областей ховера.

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

Получилось в целом неплохо, если не знать, что мы задумывали на самом деле.

Итак, какие мы сделали для себя выводы из всей этой длинной истории:

  •  WebGL уже можно применять как дополнительный уровень вау-визуализации, в дополнение к чему-то другому, что будет реализовано на более распространённых технологиях (к обычным анимациям или видео).
  • Строить ключевой визуал на WebGL может оказаться невозможно из-за ограничений технологии, производительности или разного уровня поддержки браузерами.
  • Современные инструменты для работы с 3D-графикой позволяют объединить усилия web-разработчика и motion-дизайнера для того, чтобы максимально упростить процесс создания 3D-визуала в вебе.
  • Производительность этой технологии очень капризная и требует от разработчика большого внимания и понимания базовых механизмов работы с трёхмерной графикой, поэтому производительность нужно замерять постоянно и делать это на среднемощных устройствах.

Попробуем ли мы применить WebGL в будущих проектах? Обязательно рассмотрим такую возможность, но с учётом всех собранных граблей.

Читайте другие наши статьи