Создайте приложение дополненной реальности (AR) с помощью API устройства WebXR.

В этой кодовой лаборатории рассматривается пример создания веб-приложения AR. Он использует JavaScript для визуализации 3D-моделей, которые выглядят так, как будто они существуют в реальном мире.

Вы используете API устройства WebXR , который сочетает в себе функции AR и виртуальной реальности (VR). Вы сосредотачиваетесь на расширениях AR для API устройства WebXR, чтобы создать простое приложение AR, которое работает в интерактивном Интернете.

Что такое АР?

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

AR стала широко использоваться в приложениях после выпуска Google ARCore и Apple ARKit , будь то фильтры для селфи или игры на основе AR.

Что ты построишь

В этой лаборатории кода вы создадите веб-приложение, которое помещает модель в реальный мир с использованием дополненной реальности. Ваше приложение будет:

  1. Используйте датчики целевого устройства, чтобы определять и отслеживать его положение и ориентацию в мире.
  2. Рендеринг 3D-модели, наложенной поверх изображения с камеры в реальном времени.
  3. Выполняйте тесты на попадание, чтобы размещать объекты поверх обнаруженных поверхностей в реальном мире.

Что вы узнаете

Эта лаборатория кода ориентирована на API AR. Нерелевантные концепции и блоки кода замалчиваются и предоставляются вам в соответствующем коде репозитория.

Что вам понадобится

Нажмите «Попробовать» на своем устройстве AR, чтобы попробовать первый шаг этой лаборатории кода. Если вы получаете страницу с сообщением «Ваш браузер не поддерживает функции AR», убедитесь, что на вашем устройстве Android установлены Сервисы Google Play для AR.

2. Настройте среду разработки

Загрузите код

  1. Щелкните следующую ссылку, чтобы загрузить весь код этой лаборатории кода на свою рабочую станцию:
  1. Распакуйте загруженный zip-файл. При этом будет распакована корневая папка ( ar-with-webxr-master ), которая содержит каталоги нескольких шагов этой лаборатории кода, а также все необходимые вам ресурсы.

Папки step-03 и step-04 содержат желаемое конечное состояние третьего и четвертого шагов этой лаборатории кода, а также final результат. Они здесь для справки.

Вы выполняете всю работу по кодированию в work каталоге.

Установить веб-сервер

  1. Вы можете использовать свой собственный веб-сервер. Если у вас его еще нет, в этом разделе подробно описано, как настроить веб-сервер для Chrome.
    Если это приложение еще не установлено на вашей рабочей станции, вы можете установить его из Интернет-магазина Chrome.
  1. После установки приложения «Веб-сервер для Chrome» перейдите на chrome://apps и щелкните значок «Веб-сервер»:

Значок веб-сервера

Далее вы увидите это диалоговое окно, которое позволяет вам настроить локальный веб-сервер:

Настройка веб-сервера Chrome

Перезапустите веб-сервер Chrome.

  1. Нажмите «Выбрать папку» и выберите папку ar-with-webxr-master . Это позволяет вам обслуживать свою незавершенную работу через URL-адрес, выделенный в диалоговом окне веб-сервера (в разделе URL-адреса веб-сервера ).
  2. В разделе «Параметры» (требуется перезагрузка) установите флажок «Автоматически показывать index.html» .
  3. Переключите веб-сервер в положение «Остановить» , а затем снова в положение «Запущено» .
  4. Убедитесь, что отображается хотя бы один URL-адрес веб-сервера: http://127.0.0.1:8887 — URL-адрес локального хоста по умолчанию.

Настроить переадресацию портов

Настройте свое AR-устройство так, чтобы оно имело доступ к тому же порту на вашей рабочей станции, когда вы посещаете на нем localhost:8887.

хром://проверить

  1. На рабочей станции разработки перейдите на страницу chrome://inspect и нажмите «Переадресация портов. » :
  2. Используйте диалоговое окно «Настройки переадресации портов» , чтобы перенаправить порт 8887 на локальный хост: 8887.
  3. Установите флажок Включить переадресацию портов :

Настроить переадресацию портов

Проверьте настройки

Проверьте свое соединение:

  1. Подключите устройство AR к рабочей станции с помощью USB-кабеля.
  2. На вашем AR-устройстве в Chrome введите http://localhost:8887 в адресной строке. Ваше AR-устройство должно перенаправить этот запрос на веб-сервер вашей рабочей станции разработки. Вы должны увидеть каталог файлов.
  3. На своем устройстве AR нажмите step-03 чтобы загрузить файл step-03/index.html в браузер.

Вы должны увидеть страницу с кнопкой «Начать дополненную реальность».

Однако если вы видите страницу с ошибкой «Неподдерживаемый браузер» , возможно, ваше устройство несовместимо.

ARCore поддерживается

ARCore не поддерживается

Теперь соединение с вашим веб-сервером должно работать с вашим устройством AR.

  1. Нажмите «Начать дополненную реальность» . Вам может быть предложено установить ARCore.

Установите приглашение ARCore

При первом запуске приложения AR вы увидите запрос на доступ к камере.

Chrome запрашивает разрешения камерыДиалог разрешений

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

Важно ! Из соображений безопасности API устройства WebXR может работать только в безопасных средах (HTTPS), за исключением случаев разработки на локальном хосте. Если у вас возникли проблемы с активацией WebXR, убедитесь, что вы используете защищенный документ или URL-адрес локального хоста.

С этого момента все тестирование и проверка (разделы «Проверка» на последующих этапах) требуют перехода по ссылке на вашем AR-устройстве.

3. Настройте WebXR

На этом этапе вы узнаете, как настроить сеанс WebXR и базовую сцену AR. HTML-страница снабжена стилем CSS и JavaScript для включения базовых функций AR. Это ускоряет процесс настройки, позволяя команде разработчиков сосредоточиться на функциях AR.

HTML-страница

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

Для запуска функций AR требуется жест пользователя, поэтому существуют некоторые компоненты Material Design для отображения кнопки «Запустить AR» и сообщения браузера о неподдержке.

Файл index.html , который уже находится в вашем work каталоге, должен выглядеть примерно так: Это часть фактического содержимого; не копируйте этот код в свой файл!

     Building an augmented reality application with the WebXR Device API         Start augmented reality   

Откройте ключевой код JavaScript

Отправная точка вашего приложения находится в app.js Этот файл представляет собой шаблон для настройки AR-опыта.

Этот шаблон использует асинхронные функции. Дополнительные сведения об асинхронных функциях см. в разделе Асинхронные функции — создание дружественных обещаний .

Ваш рабочий каталог также уже содержит код приложения ( app.js ).

Проверьте поддержку WebXR и AR

Прежде чем пользователь сможет работать с AR, проверьте наличие navigator.xr и необходимых функций XR. Объект navigator.xr является точкой входа для API устройства WebXR, поэтому он должен существовать, если устройство совместимо. Также убедитесь, что поддерживается режим сеанса "immersive-ar" .

Если все в порядке, нажатие кнопки «Войти в дополненную реальность» попытается создать сеанс XR. В противном случае вызывается onNoXRDevice() ( shared/utils.js ), который отображает сообщение об отсутствии поддержки AR.

Этот код уже присутствует в app.js , поэтому никаких изменений вносить не нужно.

(async function() < if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) < document.getElementById("enter-ar").addEventListener("click", activateXR) >else < onNoXRDevice(); >>)(); 

Несмотря на то, что API устройства WebXR может поддерживаться в браузере, запрошенный режим сеанса может не поддерживаться. Например, настольный браузер может реализовать API, но не иметь подключенного оборудования VR или AR для поддержки взаимодействия. Дополнительные сведения о перечислении устройств см. в спецификации WebXR Device API .

Запросить XRSession

Когда вы нажимаете «Войти в дополненную реальность» , код вызывает activateXR() . Это запускает опыт AR.

  1. Найдите функцию activateXR() в app.js Некоторый код опущен:
activateXR = async () => < // Initialize a WebXR session using "immersive-ar". this.xrSession = /* TODO */; // Omitted for brevity >

Точка входа в WebXR — через XRSystem.requestSession() . Используйте режим immersive-ar чтобы визуализированный контент можно было просматривать в реальной среде.

  1. Инициализируйте this.xrSession , используя режим "immersive-ar" :
activateXR = async () => < // Initialize a WebXR session using "immersive-ar". this.xrSession = await navigator.xr.requestSession("immersive-ar"); // . >

Инициализировать XRReferenceSpace

XRReferenceSpace описывает систему координат, используемую для объектов в виртуальном мире. 'local' режим лучше всего подходит для AR-опыта, поскольку опорное пространство находится рядом со зрителем и стабильно отслеживается.

Инициализируйте this.localReferenceSpace в onSessionStarted() с помощью следующего кода:

this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local"); 

Определить цикл анимации

  1. Используйте requestAnimationFrame XRSession , чтобы запустить цикл рендеринга, аналогично window.requestAnimationFrame .

requestAnimationFrame XRSession позволяет вам подключиться к частоте обновления собственного устройства XR. Стандартные циклы рендеринга веб-страниц рассчитаны на 60 кадров в секунду, тогда как внешние дисплеи VR могут отображать со скоростью 120 кадров в секунду. Неэксклюзивные сеансы AR по-прежнему могут работать только со скоростью 60 кадров в секунду, но информация о позе и представлении устройства доступна только в requestAnimationFrame сеанса.

В каждом кадре onXRFrame вызывается с меткой времени и XRFrame .

  1. Завершите реализацию onXRFrame . Когда кадр нарисован, поставьте в очередь следующий запрос, добавив:
// Queue up the next draw request. this.xrSession.requestAnimationFrame(this.onXRFrame); 
  1. Добавьте код для настройки графической среды. Добавьте в конец onXRFrame :
// Bind the graphics framebuffer to the baseLayer's framebuffer. const framebuffer = this.xrSession.renderState.baseLayer.framebuffer; this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer); this.renderer.setFramebuffer(framebuffer); 
  1. Чтобы определить позу зрителя, используйте XRFrame.getViewerPose() . Этот XRViewerPose описывает положение и ориентацию устройства в пространстве. Он также содержит массив XRView , который описывает каждую точку обзора, из которой должна быть визуализирована сцена, чтобы она правильно отображалась на текущем устройстве. В то время как стереоскопическая виртуальная реальность имеет два изображения (по одному для каждого глаза), устройства AR имеют только одно изображение.
    Информация в pose.views чаще всего используется для настройки матрицы обзора и матрицы проекции виртуальной камеры. Это влияет на то, как сцена отображается в 3D. Когда камера настроена, сцену можно визуализировать.
  2. Добавьте в конец onXRFrame :
// Retrieve the pose of the device. // XRFrame.getViewerPose can return null while the session attempts to establish tracking. const pose = frame.getViewerPose(this.localReferenceSpace); if (pose) < // In mobile AR, we only have one view. const view = pose.views[0]; const viewport = this.xrSession.renderState.baseLayer.getViewport(view); this.renderer.setSize(viewport.width, viewport.height); // Use the view's transform matrix and projection matrix to configure the THREE.camera. this.camera.matrix.fromArray(view.transform.matrix); this.camera.projectionMatrix.fromArray(view.projectionMatrix); this.camera.updateMatrixWorld(true); // Render the scene with THREE.WebGLRenderer. this.renderer.render(this.scene, this.camera); >

Проверьте это

Запустите приложение; на своем устройстве разработки посетите work/index.html . Вы должны увидеть изображение с камеры с плавающими в пространстве кубами, перспектива которых меняется при перемещении устройства. Чем больше вы перемещаетесь, тем лучше отслеживание, поэтому выясните, что подходит вам и вашему устройству.

Если у вас возникли проблемы с запуском приложения, проверьте разделы «Введение» и «Настройка среды разработки» .

4. Добавьте прицельную сетку

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

Понимание хит-теста

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

API устройства WebXR позволяет узнать, пересекал ли этот луч какие-либо объекты в реальном мире, что определяется базовыми возможностями AR и пониманием мира.

Объяснение теста на попадание

Запросите XRSession с дополнительными функциями

Для проведения тестов на попадание при запросе XRSession требуются дополнительные функции.

  1. В app.js найдите navigator.xr.requestSession .
  2. Добавьте функции "hit-test" и "dom-overlay" по requiredFeature . Feature следующим образом:
this.xrSession = await navigator.xr.requestSession("immersive-ar", < requiredFeatures: ["hit-test", "dom-overlay"] >); 
  1. Настройте наложение DOM. Наложите элемент document.body на вид камеры AR следующим образом:
this.xrSession = await navigator.xr.requestSession("immersive-ar", < requiredFeatures: ["hit-test", "dom-overlay"], domOverlay: < root: document.body >>); 

Добавить подсказку о движении

ARCore работает лучше всего, когда имеется адекватное понимание окружающей среды. Это достигается с помощью процесса, называемого одновременной локализацией и картографированием (SLAM), в котором визуально различные характерные точки используются для расчета изменения местоположения и характеристик окружающей среды.

Используйте "dom-overlay" из предыдущего шага, чтобы отобразить подсказку о движении поверх потока камеры.

Добавьте в index.html со stabilization идентификатора. Этот отображает пользователям анимацию, показывающую состояние стабилизации, и предлагает им перемещаться со своим устройством, чтобы улучшить процесс SLAM. Оно отображается, когда пользователь находится в AR, и скрывается, когда прицел находит поверхность, контролируемую классами .

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

  1. В app.js замените вызов DemoUtils.createCubeScene() в setupThreeJs() пустым вызовом Three.Scene() .
setupThreeJs() < // . // this.scene = DemoUtils.createCubeScene(); this.scene = DemoUtils.createLitScene(); >
  1. Заполните новую сцену объектом, который представляет точку столкновения. Предоставленный класс Reticle обрабатывает загрузку модели прицела в shared/utils.js .
  2. Добавьте Reticle в сцену в setupThreeJs() :
setupThreeJs() < // . // this.scene = DemoUtils.createCubeScene(); this.scene = DemoUtils.createLitScene(); this.reticle = new Reticle(); this.scene.add(this.reticle); >

Чтобы выполнить проверку попадания, вы используете новый XRReferenceSpace . Это опорное пространство указывает новую систему координат с точки зрения зрителя для создания луча, совмещенного с направлением просмотра. Эта система координат используется в XRSession.requestHitTestSource() , который может вычислять тесты попадания.

  1. Добавьте следующее в onSessionStarted() в app.js :
async onSessionStarted() < // . // Setup an XRReferenceSpace using the "local" coordinate system. this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local"); // Add these lines: // Create another XRReferenceSpace that has the viewer as the origin. this.viewerSpace = await this.xrSession.requestReferenceSpace("viewer"); // Perform hit testing using the viewer as origin. this.hitTestSource = await this.xrSession.requestHitTestSource(< space: this.viewerSpace >); // . > 
  1. Используя этот hitTestSource , выполняйте проверку попадания в каждом кадре:
  2. Измените onXRFrame , чтобы переместить прицельную марку:
onXRFrame = (time, frame) => < // . some code omitted . this.camera.updateMatrixWorld(true); // Add the following: const hitTestResults = frame.getHitTestResults(this.hitTestSource); if (!this.stabilized && hitTestResults.length >0) < this.stabilized = true; document.body.classList.add("stabilized"); >if (hitTestResults.length > 0) < const hitPose = hitTestResults[0].getPose(this.localReferenceSpace); // update the reticle position this.reticle.visible = true; this.reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z) this.reticle.updateMatrixWorld(true); >// More code omitted. > 

Добавить поведение при касании экрана

XRSession может генерировать события на основе взаимодействия с пользователем через событие select , которое представляет собой основное действие. В WebXR на мобильных устройствах основным действием является касание экрана.

  1. Добавьте прослушиватель событий select в нижней части onSessionStarted :
this.xrSession.addEventListener("select", this.onSelect); 

В этом примере касание экрана приводит к тому, что подсолнух помещается в прицельную сетку.

  1. Создайте реализацию onSelect в классе App :
onSelect = () => < if (window.sunflower) < const clone = window.sunflower.clone(); clone.position.copy(this.reticle.position); this.scene.add(clone); >> 

Протестируйте приложение

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

  1. При запуске приложения вы должны увидеть прицельную сетку, очерчивающую поверхность пола. Если нет, попробуйте медленно осмотреться с помощью телефона.
  2. Как только вы увидите сетку, коснитесь ее. Сверху следует разместить подсолнух. Возможно, вам придется немного передвигаться, чтобы базовая платформа AR могла лучше обнаруживать поверхности в реальном мире. Низкое освещение и поверхности без особенностей снижают качество понимания сцены и увеличивают вероятность того, что попадание не будет обнаружено. Если у вас возникнут какие-либо проблемы, ознакомьтесь с кодом step-04/app.js чтобы увидеть рабочий пример этого шага.

5. Добавляем тени

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

Освещение и тени обрабатываются three.js . Вы можете указать, какие источники света должны отбрасывать тени, какие материалы должны получать и отображать эти тени, а также какие сетки могут отбрасывать тени. Сцена этого приложения содержит источник света, отбрасывающий тень, и плоскую поверхность для рендеринга только теней.

  1. Включите тени в three.js WebGLRenderer . После создания рендерера установите следующие значения в его shadowMap :
setupThreeJs()

В этом примере используется жестко запрограммированное положение света для теней. В будущем функции AR для WebXR могут включать оценку освещенности и другие значения, чтобы тени 3D-модели также синхронизировались с реальным миром. Дополнительную информацию см. в разделе «Функция: оценка освещения AR WebXR» .

Пример сцены, созданной в DemoUtils.createLitScene() содержит объект с shadowMesh — плоскую горизонтальную поверхность, которая отображает только тени. Эта поверхность изначально имеет позицию Y , равную 10 000 единиц. После размещения подсолнуха переместите shadowMesh на ту же высоту, что и реальная поверхность, чтобы тень цветка отображалась поверх реальной земли.

  1. В onSelect после добавления clone в сцену добавьте код для изменения положения теневой плоскости:
onSelect = () => < if (window.sunflower) < const clone = window.sunflower.clone(); clone.position.copy(this.reticle.position); this.scene.add(clone); const shadowMesh = this.scene.children.find(c =>c.name === "shadowMesh"); shadowMesh.position.y = clone.position.y; > > 

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

Проверьте это

Размещая подсолнух, вы должны видеть, как он отбрасывает тень. Если у вас возникнут какие-либо проблемы, проверьте код final/app.js чтобы увидеть рабочий пример этого шага.

6. Дополнительные ресурсы

Поздравляем! Вы завершили эту лабораторную работу по дополненной реальности с помощью WebXR.

Узнать больше

Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.