1. Прежде чем начать
В этом практическом занятии рассматривается пример создания веб-приложения дополненной реальности. В нем используется JavaScript для рендеринга 3D-моделей, которые выглядят так, как будто существуют в реальном мире.
You use the WebXR Device API that combines AR and virtual-reality (VR) functionality. You focus on AR extensions to the WebXR Device API to create a simple AR app that runs on the interactive web.

Что такое дополненная реальность?
AR — это термин, обычно используемый для описания смешения компьютерной графики с реальным миром. В случае AR на основе мобильных телефонов это означает убедительное наложение компьютерной графики на видеопоток с камеры в реальном времени. Для того чтобы этот эффект оставался реалистичным по мере перемещения телефона в окружающем мире, устройство с поддержкой AR должно понимать окружающий мир и определять свое положение (ориентацию) в трехмерном пространстве. Это может включать обнаружение поверхностей и оценку освещения окружающей среды.
После выхода ARCore от Google и ARKit от Apple дополненная реальность получила широкое распространение в приложениях, будь то фильтры для селфи или игры на основе дополненной реальности.
Что вы построите
В этом практическом занятии вы создадите веб-приложение, которое разместит модель в реальном мире с помощью дополненной реальности. Ваше приложение будет:
- Используйте датчики целевого устройства для определения и отслеживания его положения и ориентации в окружающем мире.
- Визуализация 3D-модели, наложенной на изображение с камеры в реальном времени.
- Выполните проверки на попадание, чтобы разместить объекты на обнаруженных поверхностях в реальном мире.
Что вы узнаете
- Как использовать API устройств WebXR
- Как настроить базовую сцену дополненной реальности
- Как найти поверхность с помощью тестов на попадание в дополненной реальности
- Как загрузить и отрендерить 3D-модель, синхронизированную с видеопотоком с реальной камеры?
- Как отрисовать тени на основе 3D-модели
Данный практический урок посвящен API дополненной реальности. Несущественные концепции и фрагменты кода будут кратко рассмотрены и предоставлены в соответствующем репозитории.
Что вам понадобится
- Рабочая станция для кодирования и размещения статического веб-контента.
- Устройство Android с поддержкой ARCore, работающее под управлением Android 8.0 Oreo.
- Google Chrome
- Установлены сервисы Google Play для дополненной реальности (Chrome автоматически предлагает установить их на совместимых устройствах).
- Веб-сервер на ваш выбор
- USB-кабель для подключения вашего устройства дополненной реальности к рабочей станции.
- Пример кода
- Текстовый редактор
- Базовые знания HTML, CSS, JavaScript и инструментов разработчика Google Chrome.
Нажмите «Попробовать на вашем устройстве дополненной реальности», чтобы выполнить первый шаг этого практического занятия. Если вы видите страницу с сообщением «В вашем браузере отсутствуют функции дополненной реальности», убедитесь, что на вашем устройстве Android установлены сервисы Google Play для дополненной реальности.
2. Настройте среду разработки.
Скачать код
- Чтобы загрузить весь код для этого практического занятия на свой рабочий компьютер, перейдите по следующей ссылке:
- Распакуйте загруженный zip-файл. В результате будет распакована корневая папка (
ar-with-webxr-master), содержащая каталоги нескольких этапов этого практического занятия, а также все необходимые ресурсы.
Папки step-03 и step-04 содержат желаемый конечный результат третьего и четвертого шагов этого практического задания, а также final результат. Они предназначены для справки.
Всю работу по программированию вы выполняете в work директории.
Установите веб-сервер
- Вы можете использовать собственный веб-сервер. Если у вас его ещё нет, в этом разделе подробно описано, как настроить веб-сервер для Chrome.
Если у вас еще не установлено это приложение на рабочем компьютере, вы можете установить его из интернет-магазина Chrome.
- После установки приложения «Веб-сервер для Chrome» перейдите по адресу
chrome://appsи нажмите на значок «Веб-сервер»:
![]()
Далее вы увидите диалоговое окно, позволяющее настроить локальный веб-сервер:

- Нажмите «Выбрать папку» и выберите папку
ar-with-webxr-master. Это позволит вам запускать разрабатываемый проект через URL-адрес, выделенный в диалоговом окне веб-сервера (в разделе «URL-адреса веб-сервера» ). - В разделе «Параметры» (требуется перезапуск) установите флажок «Автоматически показывать index.html» .
- Переведите веб-сервер в положение «Остановлен» , а затем обратно в положение «Запущен» .

- Убедитесь, что отображается хотя бы один URL-адрес веб-сервера: http://127.0.0.1:8887 — URL-адрес localhost по умолчанию.
Настройте переадресацию портов.
Настройте ваше AR-устройство таким образом, чтобы оно обращалось к тому же порту на вашей рабочей станции при посещении localhost:8887.
- На рабочей станции разработчика перейдите по адресу chrome://inspect и нажмите «Переадресация портов...» :

- Используйте диалоговое окно настроек переадресации портов , чтобы перенаправить порт 8887 на localhost:8887.
- Установите флажок «Включить переадресацию портов» :

Проверьте свою конфигурацию.
Проверьте соединение:
- Подключите устройство дополненной реальности к рабочей станции с помощью USB-кабеля.
- На вашем устройстве дополненной реальности в браузере Chrome введите http://localhost:8887 в адресную строку. Ваше устройство дополненной реальности должно перенаправить этот запрос на веб-сервер вашей рабочей станции разработки. Вы должны увидеть каталог файлов.
- На вашем устройстве дополненной реальности нажмите
step-03, чтобы загрузить файлstep-03/index.htmlв ваш браузер.
Вы должны увидеть страницу, содержащую кнопку « Запустить дополненную реальность». | Однако, если вы видите страницу с ошибкой «Неподдерживаемый браузер» , ваше устройство, вероятно, несовместимо. |
|
|
Теперь подключение к вашему веб-серверу должно работать с вашим устройством дополненной реальности.
- Нажмите «Начать дополненную реальность» . Возможно, вам будет предложено установить ARCore.

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

3. Настройка WebXR
На этом этапе вы узнаете, как настроить сессию WebXR и базовую сцену дополненной реальности. HTML-страница снабжена CSS-стилями и JavaScript для включения основных функций дополненной реальности. Это ускоряет процесс настройки, позволяя сосредоточиться на функциях дополненной реальности.
HTML-страница
Вы интегрируете AR-технологию в традиционную веб-страницу, используя существующие веб-технологии. В этом случае используется полноэкранный холст для отрисовки, поэтому HTML-файл не должен быть слишком сложным.
Для активации функций дополненной реальности требуется жест пользователя, поэтому для отображения кнопки «Запустить AR» и сообщения о неподдерживаемом браузере используются некоторые компоненты Material Design .
Файл index.html , который уже находится в вашей work директории, должен выглядеть примерно так. Это лишь часть фактического содержимого; не копируйте этот код в свой файл!
<!-- Don't copy this code into your file! -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building an augmented reality application with the WebXR Device API</title>
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<!-- three.js -->
<script src="https://unpkg.com/three@0.123.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.123.0/examples/js/loaders/GLTFLoader.js"></script>
<script src="../shared/utils.js"></script>
<script src="app.js"></script>
</head>
<body>
<!-- Information about AR removed for brevity. -->
<!-- Starting an immersive WebXR session requires user interaction. Start the WebXR experience with a simple button. -->
<a onclick="activateXR()" class="mdc-button mdc-button--raised mdc-button--accent">
Start augmented reality
</a>
</body>
</html>
Откройте ключевой код JavaScript.
Отправной точкой для вашего приложения является файл app.js Этот файл содержит шаблон для настройки AR-приложения.
В вашей рабочей директории уже содержится код приложения ( app.js ).
Проверьте наличие поддержки WebXR и AR.
Прежде чем пользователь сможет работать с дополненной реальностью, необходимо убедиться в наличии файла navigator.xr и необходимых функций XR. Объект navigator.xr является точкой входа для WebXR Device API, поэтому он должен существовать, если устройство совместимо. Также убедитесь, что поддерживается режим сессии "immersive-ar" .
Если все в порядке, нажатие кнопки «Войти в дополненную реальность» пытается создать сессию XR. В противном случае вызывается onNoXRDevice() (в shared/utils.js ), который отображает сообщение об отсутствии поддержки дополненной реальности.
Этот код уже присутствует в app.js , поэтому никаких изменений вносить не нужно.
(async function() {
if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) {
document.getElementById("enter-ar").addEventListener("click", activateXR)
} else {
onNoXRDevice();
}
})();
Запросить XRSession
При нажатии кнопки «Войти в дополненную реальность» код вызывает функцию activateXR() . Это запускает работу дополненной реальности.
- Найдите функцию
activateXR()вapp.jsЧасть кода опущена:
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = /* TODO */;
// Omitted for brevity
}
Вход в WebXR осуществляется через XRSystem.requestSession() . Используйте режим immersive-ar , чтобы отображаемый контент можно было просматривать в реальной среде.
- Инициализируйте
this.xrSession, используя режим"immersive-ar":
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = await navigator.xr.requestSession("immersive-ar");
// ...
}
Инициализация пространства XRReferenceSpace
Объект XRReferenceSpace описывает систему координат, используемую для объектов в виртуальном мире. 'local' режим лучше всего подходит для дополненной реальности, поскольку в нем используется опорное пространство с началом координат, близким к наблюдателю, и обеспечивается стабильное отслеживание.
Инициализируйте this.localReferenceSpace в onSessionStarted() следующим кодом:
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
Определите цикл анимации
- Используйте
requestAnimationFrameизXRSessionдля запуска цикла рендеринга, аналогично методуwindow.requestAnimationFrame.
На каждом кадре вызывается onXRFrame , передающий метку времени и объект XRFrame .
- Завершите реализацию метода
onXRFrame. Когда кадр отрисован, поставьте в очередь следующий запрос, добавив:
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
- Добавьте код для настройки графической среды. Добавьте его в конец
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);
- Для определения положения зрителя используйте
XRFrame.getViewerPose(). ЭтотXRViewerPoseописывает положение и ориентацию устройства в пространстве. Он также содержит массив объектовXRView, описывающих все точки обзора, с которых должна отображаться сцена для корректного отображения на текущем устройстве. В то время как стереоскопическая VR имеет два ракурса (по одному для каждого глаза), устройства дополненной реальности имеют только один ракурс.
Информация вpose.viewsчаще всего используется для настройки матрицы вида и матрицы проекции виртуальной камеры. Это влияет на то, как сцена располагается в 3D. После настройки камеры можно выполнить рендеринг сцены. - Добавить в конец
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. Добавить прицельную сетку.
После настройки базовой сцены дополненной реальности пора начать взаимодействовать с реальным миром, используя проверку попадания. В этом разделе вы запрограммируете проверку попадания и используете её для поиска поверхности в реальном мире.
Разберитесь в проверке попадания.
Проверка попадания — это, как правило, способ построить прямую линию из точки в пространстве в каком-либо направлении и определить, пересекается ли она с какими-либо интересующими объектами. В этом примере вы направляете устройство на точку в реальном мире. Представьте, что луч исходит из камеры вашего устройства и направляется прямо в физический мир перед ним.
API WebXR Device позволяет узнать, пересекся ли луч с какими-либо объектами в реальном мире, что определяется базовыми возможностями дополненной реальности и пониманием окружающего мира.

Запросите XRSession с дополнительными функциями.
Для проведения тестов на попадание в цель при запросе XRSession требуются дополнительные функции.
- В
app.jsнайдитеnavigator.xr.requestSession. - Добавьте функции
"hit-test"и"dom-overlay"в качествеrequiredFeatureфункций следующим образом:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"]
});
- Настройте наложение 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 элемент <div> с ID stabilization . Этот <div> отображает пользователям анимацию, представляющую статус стабилизации, и предлагает им перемещаться с помощью устройства для улучшения процесса SLAM. Анимация отображается, когда пользователь находится в режиме дополненной реальности, и скрывается, когда прицел находит поверхность, и управляется классами <body> .
<div id="stabilization"></div>
</body>
</html>
Добавить прицельную сетку
Используйте прицельную сетку, чтобы указать, куда направлено поле зрения устройства.
- В
app.jsзамените вызовDemoUtils.createCubeScene()вsetupThreeJs()пустымThree.Scene().
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
}
- Заполните новую сцену объектом, представляющим точку столкновения. Предоставленный класс
Reticleотвечает за загрузку модели прицела вshared/utils.js. - Добавьте
Reticleв сцену в функцииsetupThreeJs():
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
this.reticle = new Reticle();
this.scene.add(this.reticle);
}
Для выполнения проверки попадания используется новый объект XRReferenceSpace . Это опорное пространство задает новую систему координат с точки зрения наблюдателя для создания луча, выровненного по направлению обзора. Эта система координат используется в XRSession.requestHitTestSource() , которая может вычислять проверки попадания.
- Добавьте следующий код в
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 });
// ...
}
- Используя этот
hitTestSource, выполняйте проверку попадания каждый кадр:- Если результаты проверки попадания отсутствуют, значит, ARCore не успел сформировать представление об окружающей среде. В этом случае предложите пользователю переместить устройство, используя стабилизацию
<div>. - Если результаты получены, переместите прицельную сетку в это место.
- Если результаты проверки попадания отсутствуют, значит, ARCore не успел сформировать представление об окружающей среде. В этом случае предложите пользователю переместить устройство, используя стабилизацию
- Измените параметр
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 на мобильных устройствах основным действием является касание экрана.
- Добавьте обработчик события
selectв конец вызоваonSessionStarted:
this.xrSession.addEventListener("select", this.onSelect);
В этом примере касание экрана приводит к размещению подсолнуха в прицеле.
- Создайте реализацию метода
onSelectв классеApp:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
}
}
Протестируйте приложение
Вы создали прицельную сетку, с помощью которой можете наводиться на устройство, используя тесты на попадание. При касании экрана вы должны иметь возможность разместить подсолнух в указанном прицельной сеткой месте.
- При запуске приложения вы должны видеть прицельную сетку, отслеживающую поверхность пола. Если этого не происходит, попробуйте медленно осмотреться с помощью телефона.
- Как только вы увидите прицел, коснитесь его. На него должен попасть подсолнух. Возможно, вам придётся немного подвигаться, чтобы базовая платформа дополненной реальности лучше распознавала поверхности в реальном мире. Низкое освещение и поверхности без каких-либо особенностей снижают качество понимания сцены и увеличивают вероятность того, что совпадение не будет обнаружено. Если у вас возникнут какие-либо проблемы, посмотрите код
step-04/app.jsчтобы увидеть рабочий пример этого шага.

5. Добавьте тени.
Создание реалистичной сцены включает в себя такие элементы, как правильное освещение и тени на цифровых объектах, которые добавляют реализма и погружения в сцену.
Освещение и тени обрабатываются с помощью three.js . Вы можете указать, какие источники света должны отбрасывать тени, какие материалы должны получать и отображать эти тени, и какие сетки могут отбрасывать тени. Сцена этого приложения содержит источник света, отбрасывающий тень, и плоскую поверхность для отображения только теней.
- Включите тени для
WebGLRendererиз библиотекиthree.js. После создания рендерера установите следующие значения для егоshadowMap:
setupThreeJs() {
...
this.renderer = new THREE.WebGLRenderer(...);
...
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
...
}
В примере сцены, созданном с помощью DemoUtils.createLitScene() содержится объект shadowMesh — плоская горизонтальная поверхность, которая отображает только тени. Изначально эта поверхность имеет координату Y , равную 10 000 единицам. После размещения подсолнуха переместите shadowMesh на ту же высоту, что и реальная поверхность, так чтобы тень от цветка отображалась поверх реальной земли.
- В
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.

