3D фотоэффект изображения на JavaScript

В этом уроке вы узнаете, как создать иллюзию трехмерной фотографии из изображения, используя JavaScript и библиотеку Pixi.js webGL. Давайте сделаем это!

Концепция

Чтобы превратить обычную фотографию в 3D, нам нужно использовать карту глубины (или некоторые назвали бы карту смещения или карту высоты). Как и сказано в названии, карта глубины — это файл изображения, который показывает глубину для каждого пикселя в 3D пространство. Как вы можете видеть в этом примере, передняя часть автомобиля ближе к экрану, поэтому цвет ярче, в то время как остальная часть гаража темнее в зависимости от расстояния.

js3d1-3486672 Карта глубины

Передадим карту глубины для обработки и получим конечный результат, как например, этот:

js3d2-6935663 Полученный 3D эффект

Исходный код

Начнем с загрузки последней версии Pixi.js и включения ее в код страницы.

Затем создайте приложение pixi.js. Это самый быстрый способ начать использовать pixi.js. Я передаю текущую ширину и высоту экрана в качестве разрешения. Добавьте его на HTML-страницу, которую браузер увидит как элемент canvas.

let app = new PIXI.Application({width: window.innerWidth, height: window.innerHeight});
document.body.appendChild(app.view);

И вот изображение, которое мы собираемся добавить к сцене. Давайте создадим спрайт из URL-адреса изображения и установим разрешение для текущего экрана. Затем добавьте его на сцену.

js3d3-6235859 Исходное изображение

let img = new PIXI.Sprite.from("pikachu.jpg");
img.width = window.innerWidth;
img.height = window.innerHeight;
app.stage.addChild(img);

И теперь следующим шагом является создание карты глубины. Я собираюсь использовать Photoshop для его создания. Сначала откройте исходное изображение. Затем создайте новый слой, залейте его черным цветом и уменьшите непрозрачность, чтобы вы едва могли увидеть исходное изображение под ним.

js3d4-9156402 Заливка слоя

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

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

js3d5-4817875 Карта глубины

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

depthMap = new PIXI.Sprite.from("pikachu-map.jpg");
app.stage.addChild(depthMap);
        
displacementFilter = new PIXI.filters.DisplacementFilter(depthMap);
app.stage.filters = [displacementFilter];

Событие мыши

js3d-4661029

Пока вы не увидите никакого 3D-эффекта, потому что нам нужно двигать изображение движением мыши. Вы можете это легко сделать, добавив событие mousemove.

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

window.onmousemove = function(e) {
  displacementFilter.scale.x = (window.innerWidth / 2 - e.clientX) /20;
  displacementFilter.scale.y = (window.innerHeight / 2 - e.clientY) /20;
};

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

Смотрите окончательный результат в видео ниже!