Использование API WebVR
Устарело: Эта функция больше не рекомендуется. Хотя некоторые браузеры могут ее все еще поддерживать, она может быть удалена из соответствующих веб-стандартов, находится в процессе удаления или поддерживается только для совместимости. Избегайте ее использования и, если возможно, обновите существующий код; см. таблицу совместимости внизу этой страницы для принятия решения. Имейте в виду, что эта функция может перестать работать в любое время.
Примечание: API WebVR заменен на API WebXR. WebVR никогда не был ратифицирован как стандарт, был реализован и включен по умолчанию в очень небольшом количестве браузеров и поддерживал небольшое количество устройств.
API WebVR — замечательное дополнение к набору инструментов веб-разработчика, позволяющее представлять сцены WebGL в дисплеях виртуальной реальности, таких как Oculus Rift и HTC Vive. Но как начать разработку приложений VR для Web? Эта статья проведет вас по основам.
Начало работы
Для начала вам нужно:
-
Поддерживающее оборудование VR.
- Самый бюджетный вариант — использовать мобильное устройство, поддерживающий браузер и крепление (например, Google Cardboard). Это не будет столь же хорошим опытом, как специализированное оборудование, но вам не нужно покупать мощный компьютер или специализированный дисплей VR.
- Специализированное оборудование может быть дорогостоящим, но оно обеспечивает лучший опыт. На данный момент наиболее совместимое с WebVR оборудование — HTC VIVE и Oculus Rift. На главной странице webvr.info есть дополнительная полезная информация о доступном оборудовании и поддержке браузеров.
-
Компьютер с достаточной мощностью для обработки рендеринга/отображения сцен VR с помощью вашего специализированного оборудования VR, если требуется. Чтобы получить представление о необходимых характеристиках, обратитесь к соответствующему руководству для приобретаемого VR-оборудования (например, VIVE READY компьютеры).
-
Установленный поддерживающий браузер — последние версии Firefox Nightly или Chrome — сейчас лучшие варианты, как на настольных, так и на мобильных устройствах.
После того, как все собрано, вы можете проверить, работает ли ваша настройка с WebVR, перейдя на нашу простую демонстрацию A-Frame и посмотрите, рендерится ли сцена и можно ли войти в режим отображения VR, нажав кнопку в правом нижнем углу.
A-Frame — безусловно, лучший вариант, если вы хотите быстро создать совместимую со WebVR 3D-сцену без необходимости понимать много нового кода JavaScript. Однако он не объясняет, как работает API WebVR в чистом виде, и именно этому мы посвятим следующий раздел.
Представление нашей демонстрации
Чтобы продемонстрировать работу API WebVR, мы рассмотрим наш пример raw-webgl-example, который выглядит примерно так:
Примечание: Вы можете найти исходный код нашей демонстрации на GitHub и просмотреть ее онлайн.
Примечание: Если WebVR не работает в вашем браузере, возможно, вам нужно убедиться, что он работает через вашу графическую карту. Например, для карт NVIDIA, если у вас успешно настроена панель управления NVIDIA, будет доступен пункт контекстного меню — щелкните правой кнопкой мыши по Firefox и выберите «Запустить с графическим процессором > Высокопроизводительный процессор NVIDIA».
Наша демонстрация демонстрирует «святой Грааль» демонстраций WebGL — вращающийся 3D куб. Мы реализовали это с помощью кода API WebGL в чистом виде. Мы не будем объяснять основы JavaScript или WebGL, а только части WebVR.
Наша демонстрация также включает:
- Кнопку для запуска (и остановки) отображения сцены в дисплее VR.
- Кнопку для отображения (и скрытия) данных о положении VR, т. е. позиции и ориентации шлема, обновляемых в реальном времени.
Когда вы просмотрите исходный код основного файла JavaScript нашей демонстрации, вы легко найдете части, специфичные для WebVR, поискав строку «WebVR» в предшествующих комментариях.
Примечание: Чтобы узнать больше об основах JavaScript и WebGL, обратитесь к нашим материалам по изучению JavaScript и нашему уроку по WebGL.
Как это работает?
На этом этапе давайте посмотрим, как работают части WebVR в коде.
Типичное (простое) приложение WebVR работает следующим образом:
-
Navigator.getVRDisplays()используется для получения ссылки на ваш дисплей VR. -
VRDisplay.requestPresent()используется для начала презентации на дисплее VR. - Специальный метод
VRDisplay.requestAnimationFrame()WebVR используется для запуска цикла рендеринга приложения с правильной частотой обновления для дисплея. - Внутри цикла рендеринга вы получаете данные, необходимые для отображения текущего кадра (
VRDisplay.getFrameData()), отрисовываете отображаемую сцену дважды — один раз для каждого глаза — затем отправляете отрисованный вид на дисплей для отображения пользователю с помощью (VRDisplay.submitFrame()).
В следующих разделах мы подробно рассмотрим нашу демонстрацию raw-webgl, чтобы увидеть, где именно используются вышеперечисленные функции.
Начинаем с некоторых переменных
Первый код, связанный с WebVR, который вы встретите, — это следующий блок:
// WebVR variables
const frameData = new VRFrameData();
let vrDisplay;
const btn = document.querySelector(".stop-start");
let normalSceneFrame;
let vrSceneFrame;
const poseStatsBtn = document.querySelector(".pose-stats");
const poseStatsSection = document.querySelector("section");
poseStatsSection.style.visibility = "hidden"; // hide it initially
const posStats = document.querySelector(".pos");
const orientStats = document.querySelector(".orient");
const linVelStats = document.querySelector(".lin-vel");
const linAccStats = document.querySelector(".lin-acc");
const angVelStats = document.querySelector(".ang-vel");
const angAccStats = document.querySelector(".ang-acc");
let poseStatsDisplayed = false;
Давайте кратко объясним эти:
-
frameDataсодержит объектVRFrameData, созданный с помощью конструктораVRFrameData(). Изначально он пуст, но позже будет содержать данные, необходимые для рендеринга каждого кадра для отображения на дисплее VR, постоянно обновляясь по мере работы цикла рендеринга. -
vrDisplayинициализирован не заданным значением, но позже он будет содержать ссылку на наш VR-шлем (VRDisplay— центральный объект управления API). -
btnиposeStatsBtnсодержат ссылки на две кнопки, используемые для управления нашим приложением. -
normalSceneFrameиvrSceneFrameинициализируются не заданным значением, но позже будут содержать ссылки на вызовыWindow.requestAnimationFrame()иVRDisplay.requestAnimationFrame()— они инициируют запуск обычного цикла рендеринга и специального цикла рендеринга WebVR; мы объясним разницу между ними позже. - Другие переменные хранят ссылки на различные части области отображения данных положения VR, которую вы можете видеть в правом нижнем углу пользовательского интерфейса.
Получение ссылки на наш VR-дисплей
Одна из основных функций в нашем коде — start() — мы запускаем эту функцию, когда тело завершило загрузку:
// start // // Called when the body has loaded is created to get the ball rolling. document.body.onload = start;
В начале start() извлекает контекст WebGL, который будет использоваться для рендеринга 3D-графики в элемент <canvas> в нашем HTML. Затем мы проверяем, доступен ли контекст gl — если да, то выполняем ряд функций для настройки сцены для отображения.
function start() {
canvas = document.getElementById("gl-canvas");
initWebGL(canvas); // Initialize the GL context
// WebGL setup code here
Далее, мы запускаем процесс фактического рендеринга сцены на холсте, установив холст для заполнения всего просмотра браузера и запустив цикл рендеринга (drawScene()) в первый раз. Это цикл рендеринга без WebVR — стандартный.
// draw the scene normally, without WebVR - for those who don't have it and want to see the scene in their browser canvas.width = window.innerWidth; canvas.height = window.innerHeight; drawScene();
Теперь перейдем к первому коду, специфичному для WebVR. Прежде всего, мы проверяем, существует ли Navigator.getVRDisplays — это точка входа в API, а значит, хорошее базовое обнаружение WebVR. Вы увидите в конце блока (внутри else), что если это не существует, мы выведем сообщение, указывающее, что браузер не поддерживает WebVR 1.1.
// WebVR: Check to see if WebVR is supported
if (navigator.getVRDisplays) {
console.log('WebVR 1.1 supported');
Внутри нашего if () { } блока мы запускаем функцию Navigator.getVRDisplays(). Она возвращает промис, который выполняется с массивом, содержащим все устройства VR-дисплеев, подключенных к компьютеру. Если ни одного не подключено, массив будет пустым.
// Then get the displays attached to the computer
navigator.getVRDisplays().then((displays) => {
Внутри блока промиса then() мы проверяем, является ли длина массива больше 0; если да, мы устанавливаем значение нашей переменной vrDisplay на элемент с индексом 0 в массиве. vrDisplay теперь содержит объект VRDisplay, представляющий наше подключенное устройство!
// If a display is available, use it to present the scene
if (displays.length > 0) {
vrDisplay = displays[0];
console.log('Display found');
Примечание: Вероятность того, что у вас будет несколько VR-дисплеев, подключенных к вашему компьютеру, невелика, и это просто демонстрация, поэтому этого пока достаточно.
Запуск и остановка презентации VR
Теперь у нас есть объект VRDisplay, и мы можем использовать его для выполнения ряда действий. Следующее, что мы хотим сделать, — это подключить функциональность для запуска и остановки отображения содержимого WebGL на дисплее.
Продолжая предыдущий блок кода, мы добавляем обработчик событий к нашей кнопке запуска/остановки (btn) — при нажатии этой кнопки мы хотим проверить, уже отображается ли что-либо на дисплее (мы делаем это довольно примитивно, проверяя, что содержит текст кнопки textContent).
Если на дисплее ничего ещё не отображается, мы используем метод VRDisplay.requestPresent(), чтобы запросить у браузера начать отображение содержимого на дисплее. В качестве параметра передаётся массив объектов VRLayerInit, представляющих слои, которые вы хотите отобразить на дисплее.
Поскольку максимальное количество отображаемых слоёв в настоящее время равно 1, и единственным необходимым элементом объекта является свойство VRLayerInit.source (которое является ссылкой на <canvas>, который вы хотите отобразить в этом слое; другие параметры заданы по умолчанию — см. leftBounds и rightBounds)), параметр имеет вид [{ source: canvas }].
requestPresent() возвращает промис, который выполняется, когда отображение успешно начинается.
// Starting the presentation when the button is clicked: It can only be called in response to a user gesture
btn.addEventListener('click', () => {
if (btn.textContent === 'Start VR display') {
vrDisplay.requestPresent([{ source: canvas }]).then(() => {
console.log('Presenting to WebVR display');
После успешного запроса отображения мы хотим начать настройку для рендеринга содержимого для отображения на VRDisplay. Во-первых, мы устанавливаем размер холста (canvas) равным размеру области отображения VR. Для этого мы получаем параметры VREyeParameters для обоих глаз с помощью VRDisplay.getEyeParameters().
Затем мы выполняем простые вычисления для расчёта общей ширины области рендеринга VRDisplay на основе ширины и высоты рендеринга VREyeParameters.renderWidth и VREyeParameters.renderHeight каждого глаза.
// Set the canvas size to the size of the vrDisplay viewport
const leftEye = vrDisplay.getEyeParameters("left");
const rightEye = vrDisplay.getEyeParameters("right");
canvas.width = Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2;
canvas.height = Math.max(leftEye.renderHeight, rightEye.renderHeight);
Далее, мы отменяем цикл анимации, ранее запущенный вызовом Window.requestAnimationFrame() внутри функции drawScene(), и вместо этого вызываем drawVRScene(). Эта функция рендерит ту же сцену, что и раньше, но с использованием специальной магии WebVR. Цикл в этой функции поддерживается специальным методом WebVR VRDisplay.requestAnimationFrame.
// stop the normal presentation, and start the vr presentation window.cancelAnimationFrame(normalSceneFrame); drawVRScene();
Наконец, мы обновляем текст кнопки, чтобы при следующем нажатии она остановила отображение на VR-дисплее.
btn.textContent = 'Exit VR display';
});
Для остановки отображения VR при последующем нажатии кнопки мы вызываем VRDisplay.exitPresent(). Мы также меняем текст кнопки и меняем вызовы requestAnimationFrame. Здесь видно, что мы используем VRDisplay.cancelAnimationFrame для остановки цикла рендеринга VR и возобновления обычного цикла рендеринга, вызвав drawScene().
} else {
vrDisplay.exitPresent();
console.log('Stopped presenting to WebVR display');
btn.textContent = 'Start VR display';
// Stop the VR presentation, and start the normal presentation
vrDisplay.cancelAnimationFrame(vrSceneFrame);
drawScene();
}
});
}
});
} else {
console.log('WebVR API not supported by this browser.');
}
}
После запуска отображения вы сможете увидеть стереоскопическое изображение, отображаемое в браузере:
Ниже вы узнаете, как на самом деле создаётся стереоскопическое изображение.
Почему у WebVR есть свой requestAnimationFrame()?
Хороший вопрос. Причина в том, что для плавного рендеринга внутри VR-дисплея необходимо отображать содержимое с частотой обновления дисплея, а не компьютера. Частоты обновления VR-дисплеев выше, чем частоты обновления компьютеров, обычно до 90 кадров в секунду. Значение будет отличаться от основной частоты обновления компьютера.
Обратите внимание, что когда VR-дисплей не отображает, VRDisplay.requestAnimationFrame работает так же, как и Window.requestAnimationFrame, поэтому, если хотите, можете использовать только один цикл рендеринга вместо двух, которые мы используем в нашем приложении. Мы использовали два, чтобы выполнять немного разные действия в зависимости от того, отображает ли VR-дисплей, и чтобы сохранить разделение для большей понятности.
Рендеринг и отображение
На данном этапе мы увидели весь код, необходимый для доступа к VR-оборудованию, запроса отображения нашей сцены на оборудовании и запуска цикла рендеринга. Теперь давайте рассмотрим код цикла рендеринга и объясним, как работают специфичные для WebVR части.
Сначала мы начинаем определение нашей функции цикла рендеринга — drawVRScene(). Первое, что мы делаем внутри неё, — это вызов VRDisplay.requestAnimationFrame() для продолжения цикла после его первого вызова (это произошло ранее в нашем коде, когда мы начали отображение на VR-дисплее). Этот вызов устанавливается в качестве значения глобальной переменной vrSceneFrame, поэтому мы можем отменить цикл с помощью вызова VRDisplay.cancelAnimationFrame() после выхода из отображения VR.
function drawVRScene() {
// WebVR: Request the next frame of the animation
vrSceneFrame = vrDisplay.requestAnimationFrame(drawVRScene);
Далее мы вызываем VRDisplay.getFrameData(), передавая ему имя переменной, в которой мы хотим хранить данные кадра. Мы инициализировали её ранее — frameData. После выполнения вызова эта переменная будет содержать данные, необходимые для рендеринга следующего кадра для VR-устройства, упакованные в виде объекта VRFrameData. Он содержит такие вещи, как проекционные и видовые матрицы для правильного рендеринга сцены для левого и правого глаза, а также текущий объект VRPose, содержащий данные о VR-дисплее, такие как ориентация, положение и т. д.
Это необходимо вызывать на каждом кадре, чтобы рендеринг изображения всегда был актуальным.
// Populate frameData with the data of the next frame to display vrDisplay.getFrameData(frameData);
Теперь мы извлекаем текущее значение VRPose из свойства VRFrameData.pose, сохраняем положение и ориентацию для последующего использования и передаём текущее положение в поле отображения информации о положении, если переменная poseStatsDisplayed имеет значение true.
// You can get the position, orientation, etc. of the display from the current frame's pose
const curFramePose = frameData.pose;
const curPos = curFramePose.position;
const curOrient = curFramePose.orientation;
if (poseStatsDisplayed) {
displayPoseStats(curFramePose);
}
Теперь мы очищаем холст (canvas) перед началом отрисовки, чтобы следующий кадр был чётко виден, и не были видны ранее отрисованные кадры:
// Clear the canvas before we start drawing on it. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
Теперь мы рендерим изображение для обоих глаз. Сначала нам нужно создать проекционные и видовые координаты для использования в рендеринге. Это объекты WebGLUniformLocation, созданные с помощью метода WebGLRenderingContext.getUniformLocation(), которому передаются идентификатор программы шейдера и имя в качестве параметров.
// WebVR: Create the required projection and view matrix locations needed // for passing into the uniformMatrix4fv methods below const projectionMatrixLocation = gl.getUniformLocation( shaderProgram, "projMatrix", ); const viewMatrixLocation = gl.getUniformLocation(shaderProgram, "viewMatrix");
Следующий шаг рендеринга включает:
- Установка размера области просмотра для левого глаза с помощью
WebGLRenderingContext.viewport— логически это первая половина ширины холста и полная высота. - Установка значений видовой и проекционной матриц для рендеринга левого глаза — это делается с помощью метода
WebGLRenderingContext.uniformMatrix4fv, которому передаются полученные выше значения местоположений и левые матрицы, полученные из объектаVRFrameData. - Вызов функции
drawGeometry(), которая рендерит фактическую сцену — из-за того, что мы указали на предыдущих двух шагах, мы будем рендерить её только для левого глаза.
// WebVR: Render the left eye's view to the left half of the canvas gl.viewport(0, 0, canvas.width * 0.5, canvas.height); gl.uniformMatrix4fv( projectionMatrixLocation, false, frameData.leftProjectionMatrix, ); gl.uniformMatrix4fv(viewMatrixLocation, false, frameData.leftViewMatrix); drawGeometry();
Теперь мы делаем то же самое, но для правого глаза:
// WebVR: Render the right eye's view to the right half of the canvas gl.viewport(canvas.width * 0.5, 0, canvas.width * 0.5, canvas.height); gl.uniformMatrix4fv( projectionMatrixLocation, false, frameData.rightProjectionMatrix, ); gl.uniformMatrix4fv(viewMatrixLocation, false, frameData.rightViewMatrix); drawGeometry();
Далее мы определяем функцию drawGeometry(). Большая часть кода — это просто код WebGL, необходимый для отрисовки нашего 3D куба. Вы увидите некоторые специфичные для WebVR части в вызовах mvTranslate() и mvRotate() — эти вызовы передают матрицы в программу WebGL, которые определяют перевод и вращение куба для текущего кадра.
Вы увидите, что мы изменяем эти значения на основании положения (curPos) и ориентации (curOrient) VR-дисплея, полученного из объекта VRPose. В результате, например, при перемещении или повороте головы влево, значение x-положения (curPos[0]) и значение y-поворота ([curOrient[1]) добавляются к значению x-перевода, что означает, что куб будет перемещаться вправо, как и ожидается, когда вы смотрите на что-то и затем перемещаете/поворачиваете голову влево.
Это быстрый и простой способ использования данных о положении VR, но он иллюстрирует основной принцип.
function drawGeometry() {
// Establish the perspective with which we want to view the
// scene. Our field of view is 45 degrees, with a width/height
// ratio of 640:480, and we only want to see objects between 0.1 units
// and 100 units away from the camera.
perspectiveMatrix = makePerspective(45, 640.0 / 480.0, 0.1, 100.0);
// Set the drawing position to the "identity" point, which is
// the center of the scene.
loadIdentity();
// Now move the drawing position a bit to where we want to start
// drawing the cube.
mvTranslate([
0.0 - curPos[0] * 25 + curOrient[1] * 25,
5.0 - curPos[1] * 25 - curOrient[0] * 25,
-15.0 - curPos[2] * 25,
]);
// Save the current matrix, then rotate before we draw.
mvPushMatrix();
mvRotate(cubeRotation, [0.25, 0, 0.25 - curOrient[2] * 0.5]);
// Draw the cube by binding the array buffer to the cube's vertices
// array, setting attributes, and pushing it to GL.
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
// Set the texture coordinates attribute for the vertices.
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer);
gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
// Specify the texture to map onto the faces.
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);
// Draw the cube.
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
// Restore the original matrix
mvPopMatrix();
}
Следующий фрагмент кода не связан с WebVR — он просто обновляет вращение куба в каждом кадре:
// Update the rotation for the next draw, if it's time to do so.
let currentTime = new Date().getTime();
if (lastCubeUpdateTime) {
const delta = currentTime - lastCubeUpdateTime;
cubeRotation += (30 * delta) / 1000.0;
}
lastCubeUpdateTime = currentTime;
Последняя часть цикла рендеринга включает вызов VRDisplay.submitFrame() — теперь вся работа выполнена, и мы отрисовали отображение на <canvas>, этот метод затем отправляет кадр на VR-дисплей, чтобы он также отображался на нём.
// WebVR: Indicate that we are ready to present the rendered frame to the VR display vrDisplay.submitFrame(); }
Отображение данных о положении (позиции, ориентации и т. д.)
В этом разделе мы обсудим функцию displayPoseStats(), которая отображает обновлённые данные о позе на каждом кадре. Функция довольно проста.
Прежде всего, мы сохраняем шесть различных значений свойств, доступных из объекта VRPose, в своих переменных — каждое из них является Float32Array.
function displayPoseStats(pose) {
const pos = pose.position;
const orient = pose.orientation;
const linVel = pose.linearVelocity;
const linAcc = pose.linearAcceleration;
const angVel = pose.angularVelocity;
const angAcc = pose.angularAcceleration;
Затем мы записываем данные в информационную область, обновляя её на каждом кадре. Мы округлили каждое значение до трёх десятичных знаков с помощью toFixed(), так как в противном случае значения трудно читаемы.
Следует отметить, что мы использовали условное выражение для проверки, успешно ли возвращены массивы линейного и углового ускорения, прежде чем отобразить данные. Эти значения пока не сообщаются большинством VR-оборудования, поэтому код выдаст ошибку, если мы этого не сделаем (массивы возвращают null если они не возвращаются успешно).
posStats.textContent = `Position: ` +
`x ${pos[0].toFixed(3)}, ` +
`y ${pos[1].toFixed(3)}, ` +
`z ${pos[2].toFixed(3)}`;
orientStats.textContent = `Orientation: ` +
`x ${orient[0].toFixed(3)}, ` +
`y ${orient[1].toFixed(3)}, ` +
`z ${orient[2].toFixed(3)}`;
linVelStats.textContent = `Linear velocity: ` +
`x ${linVel[0].toFixed(3)}, ` +
`y ${linVel[1].toFixed(3)}, ` +
`z ${linVel[2].toFixed(3)}`;
angVelStats.textContent = `Angular velocity: ` +
`x ${angVel[0].toFixed(3)}, ` +
`y ${angVel[1].toFixed(3)}, ` +
`z ${angVel[2].toFixed(3)}`;
if (linAcc) {
linAccStats.textContent = `Linear acceleration: ` +
`x ${linAcc[0].toFixed(3)}, ` +
`y ${linAcc[1].toFixed(3)}, ` +
`z ${linAcc[2].toFixed(3)}`;
} else {
linAccStats.textContent = 'Linear acceleration not reported';
}
if (angAcc) {
angAccStats.textContent = `Angular acceleration: ` +
`x ${angAcc[0].toFixed(3)}, ` +
`y ${angAcc[1].toFixed(3)}, ` +
`z ${angAcc[2].toFixed(3)}`;
} else {
angAccStats.textContent = 'Angular acceleration not reported';
}
}
События WebVR
Спецификация WebVR включает в себя ряд событий, которые срабатывают, позволяя коду нашего приложения реагировать на изменения состояния VR-дисплея (см. События окна). Например:
-
vrdisplaypresentchange— Срабатывает, когда состояние презентации VR-дисплея изменяется — то есть переходит от презентации к непроизводству или наоборот. -
vrdisplayconnect— Срабатывает, когда совместимый VR-дисплей подключён к компьютеру. -
vrdisplaydisconnect— Срабатывает, когда совместимый VR-дисплей отключён от компьютера.
Чтобы продемонстрировать, как они работают, наша простая демонстрация включает в себя следующий пример:
window.addEventListener("vrdisplaypresentchange", (e) => {
console.log(
`Display ${e.display.displayId} presentation has changed. Reason given: ${e.reason}.`,
);
});
Как вы можете видеть, объект VRDisplayEvent предоставляет две полезные свойства — VRDisplayEvent.display, которое содержит ссылку на VRDisplay, в ответ на которое было сгенерировано событие, и VRDisplayEvent.reason, которое содержит удобочитаемое объяснение причины срабатывания события.
Это очень полезное событие; вы можете использовать его для обработки случаев, когда дисплей неожиданно отключается, предотвращая возникновение ошибок и информируя пользователя о ситуации. В демонстрации презентации webvr.info от Google это событие используется для запуска функции onVRPresentChange(), которая обновляет элементы управления пользовательского интерфейса соответствующим образом и переизмеряет холст.
Резюме
В этой статье вы получили основные сведения о создании простого приложения WebVR 1.1, чтобы помочь вам начать работу.
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/WebVR_API/Using_the_WebVR_API