Facebook недавно представил новую функцию, 3D-фотографии, или, как они называют это в своем javascript: 2.5D-фотографии. Вот как это выглядит:

Чтобы создать такую ​​фотографию, выберите «3D-фото» при публикации в Facebook и используйте новый портретный режим на iPhone. Вот и все.

Но как это работает под капотом? Мне нравится узнавать новые идеи, читая чужой код. Мне было достаточно любопытно узнать, как они реализовали этот эффект в Facebook. Вот история. Если вы просто хотите узнать о технологиях, перейдите к разделу «как все работает».

Первое предположение, фрагментный шейдер?

Существует популярный способ имитации 3D с помощью шейдера с использованием карты глубины и искажения пикселей изображения с помощью фрагментного шейдера в WebGL:

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

Еще одна идея, которую может использовать Facebook, - это смещение вершин на основе изображения, подобное тому, которое мы недавно использовали с Денисом на его сайте loveiko.com:

Есть еще несколько способов подделать это, но теперь мне нужно было знать, как они это сделали! Потому что мне любопытно, знаете ли.

Как я декомпилировал

Лучше всего начать с вкладки сети в DevTools. Все отсортировано по размеру файла, и вот что вы получите для этого кенгуру:

Скачал самый большой файл, оказался файл .glb. Это двоичная форма формата glTF, лучший выбор для 3D-моделей в Интернете.

Итак, я зашел в онлайн-программу просмотрщик glTF, загрузил этот файл и увидел следующее:

Не очень полезно, но теперь я знал, что речь идет не о смещении вершины-фрагмента, здесь речь идет о реальной 3D модели.

Итак, я пошел к исходным текстам javascript на странице Facebook (используя это расширение) и обнаружил, что они используют фреймворк Three.js для этого средства просмотра. Хорошо, я знал, как с этим справиться.

Нашел (на самом деле это самая сложная часть) объект сцены three.js и просто изменил одно значение:

material.wireframe = true;

Наконец-то я смог увидеть магию этого эффекта!

Как все это работает?

Прежде всего, когда новый iPhone делает снимок в портретном режиме, он также сохраняет данные о глубине вместе с обычным .jpg. Вот небольшое видео-объяснение того, как он его собирает:

Согласно спецификации Apple эти данные представляют собой облако точек. Не сетка.

Затем facebook на основе некоторого алгоритма интерполяции создает из нее настоящую 3D-модель с фотографией в качестве текстуры:

Теперь, когда вы загружаете страницу facebook, она запускает сцену three.js и загружает эту модель с текстурой.

Когда вы перемещаете мышь - положение камеры меняется, поэтому вы ощущаете приятный эффект 2.5D. Как мы только что выяснили, это на самом деле настоящее 3D.

В конце концов

Я не знаю, почему Facebook выбрал более сложный и технологичный способ создания этого эффекта. Может быть, потому, что у них уже есть программа для 3D-просмотра, или они планируют в ближайшее время что-то большее. Без понятия.

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

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

Также на каждую 3D-фотографию дополнительно загружается одно странное (возможно, просто тестовое) изображение:

Благодаря Майклу Фельдстайну, он раскрыл эту тайну, так что это изображение - PreMultipliedRadienceEnvironmentMap, которое threejs использует для упаковки вместо кубической карты mipmapped.

Вот и все. Надеюсь, вам понравилось это небольшое расследование. Буду признателен, если вы поделитесь своими идеями по этому поводу. Хорошего дня!

Спасибо Роману Вабищевичу за то, что разрешили мне использовать ваши фотографии!

P.S .: На самом деле я сделал много таких декомпиляций в прошлом году, 55 видео с реализованными различными интерфейсными эффектами (в основном на русском языке).