aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/api/webvr_api
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/api/webvr_api
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/web/api/webvr_api')
-rw-r--r--files/ru/web/api/webvr_api/index.html246
-rw-r--r--files/ru/web/api/webvr_api/using_the_webvr_api/index.html440
2 files changed, 686 insertions, 0 deletions
diff --git a/files/ru/web/api/webvr_api/index.html b/files/ru/web/api/webvr_api/index.html
new file mode 100644
index 0000000000..ee513c37d0
--- /dev/null
+++ b/files/ru/web/api/webvr_api/index.html
@@ -0,0 +1,246 @@
+---
+title: WebVR API
+slug: Web/API/WebVR_API
+translation_of: Web/API/WebVR_API
+---
+<div>{{SeeCompatTable}}{{APIRef("WebVR API")}}</div>
+
+<p class="summary">WebVR обеспечивает поддержку для использования устройств виртуальной реальности — например, шлемы виртуальной реальности, таких как Oculus Rift или HTC Vive — для веб-приложений, позволяя разработчикам передавать  информацию о местоположении и движения с дисплея в движение вокруг 3D-сцены. Это имеет множество интересных приложений, от виртуальных туров продукта и интерактивных обучающих приложений до захватывающих игр от первого лица.</p>
+
+<h2 id="Концепция_и_использование">Концепция и использование</h2>
+
+<p>Любые VR-устройства, подключенные к вашему компьютеру, будут возвращены методом {{domxref("Navigator.getVRDisplays()")}}; каждое из которых будет представлено  {{domxref("VRDisplay")}} объектом.</p>
+
+<p><img alt='Sketch of a person in a chair with wearing goggles labelled "Head mounted display (HMD)" facing a monitor with a webcam labelled "Position sensor"' src="https://mdn.mozillademos.org/files/11035/hw-setup.png" style="display: block; height: 78px; margin: 0px auto; width: 60%;"></p>
+
+<p>{{domxref("VRDisplay")}} является центральным интерфейсом в API WebVR - с помощью его свойств и методов вы получить доступ к функциям:</p>
+
+<ul>
+ <li>Получить полезную информацию, чтобы мы могли идентифицировать дисплей, какие возможности он имеет, контроллеры, связанные с ним и многое другое.</li>
+ <li>Получить {{domxref("VRFrameData", "frame data")}} для каждого кадра контента, который вы хотите представить на дисплее, и отправьте эти кадры для отображения с постоянной скоростью.</li>
+ <li>Начать и прекратить подачу на дисплей.</li>
+</ul>
+
+<p>Типичное (простое) WebVR приложение будет работать так:</p>
+
+<ol>
+ <li>{{domxref("Navigator.getVRDisplays()")}} используется для получения ссылки на ваш VR-дисплей.</li>
+ <li>{{domxref("VRDisplay.requestPresent()")}} используется для начала представления на дисплей VR.</li>
+ <li>Выделенный {{domxref("VRDisplay.requestAnimationFrame()")}}  WebVR's используется для запуска цикла рендеринга приложения с правильной частотой обновления для отображения.</li>
+ <li>Внутри цикла рендеринга берутся данные, необходимые для отоброжения текущего кадра  ({{domxref("VRDisplay.getFrameData()")}}), дважды нарисуйте отображаемую сцену - один раз для просмотра в каждом глазу, затем отправьте отображаемый вид на дисплей, чтобы показать пользовотелю ({{domxref("VRDisplay.submitFrame()")}}).</li>
+</ol>
+
+<p>Кроме того, WebVR 1.1 добавляет ряд событий {{domxref("Window")}} объекту, чтобы JavaScript мог реагировать на изменения состояния дисплея.</p>
+
+<div class="note">
+<p><strong>Примечание</strong>: Вы можете найте намого больше о том, как работает API в <a href="/en-US/docs/Web/API/WebVR_API/Using_the_WebVR_API">Using the WebVR API</a> и <a href="/en-US/docs/Web/API/WebVR_API/Concepts">WebVR Concepts</a> статьях.</p>
+</div>
+
+<h3 id="Использование_контроллеров_Объединение_WebVR_с_API-интерфейсом_геймпада">Использование контроллеров: Объединение WebVR с API-интерфейсом геймпада</h3>
+
+<p>Многие аппаратные настройки WebVR оснащены контроллерами, которые сочетаются с гарнитурой. Они могут быть использованы в WebVR приложениях через <a href="/en-US/docs/Web/API/Gamepad_API">Gamepad API</a>, и, в частности, <a href="/en-US/docs/Web/API/Gamepad_API#Experimental_Gamepad_extensions">Gamepad расширения API</a>, которые добавляют API функции для доступа к <a href="/en-US/docs/Web/API/GamepadPose">позе контроллера</a>, <a href="/en-US/docs/Web/API/GamepadHapticActuator">haptic actuators</a>, и многоe другое.</p>
+
+<div class="note">
+<p><strong>Примечание</strong>: Наша <a href="/en-US/docs/Web/API/WebVR_API/Using_VR_controllers_with_WebVR">Using VR controllers with WebVR</a> статья объясняет основы использования VR-контроллеров в приложениях WebVR.</p>
+</div>
+
+<h2 id="WebVR_Интерфейс">WebVR Интерфейс</h2>
+
+<dl>
+ <dt>{{domxref("VRDisplay")}}</dt>
+ <dd>Представляет любое устройство VR, поддерживаемое этим API. VRDisplay включает в себя общую информацию, такую как идентификаторые устройств и  описания, а также методы для начала представления сцены VR, получения параметров глаз и возможностей отображения и других важных функций.</dd>
+ <dt>{{domxref("VRDisplayCapabilities")}}</dt>
+ <dd>описывает возможности {{domxref("VRDisplay")}} — его функции могут использоваться для тестирования возможностей устройства VR, например, может ли он возвращать информацию о местоположении.</dd>
+ <dt>{{domxref("VRDisplayEvent")}}</dt>
+ <dd>Возвращает объект события (event) связанного с WebVR-событием (см. {{anch("Window", "window object extensions")}} , перечисленны ниже).</dd>
+ <dt>{{domxref("VRFrameData")}}</dt>
+ <dd>Представляет всю информацию, необходимую для создания одного кадра сцены VR; созданный от  {{domxref("VRDisplay.getFrameData()")}}.</dd>
+ <dt>{{domxref("VRPose")}}</dt>
+ <dd>Предстовляет состояние позиции на заданной временой отметке (которая включает в себя ориентацию, положение, скорость и ускорение).</dd>
+ <dt>{{domxref("VREyeParameters")}}</dt>
+ <dd>Предоставляет доступ ко все информации, необзходимой для корректного отображения сцены для каждого задного глаза, включая информацию о поле зрения.</dd>
+ <dt>{{domxref("VRFieldOfView")}}</dt>
+ <dd>Представляет поле зрения, определенное четырьмя различными значениями степени, описывающими представление из центральной точки.</dd>
+ <dt>{{domxref("VRLayerInit")}}</dt>
+ <dd>Представляет слой, который должен быть представлен в {{domxref("VRDisplay")}}.</dd>
+ <dt>{{domxref("VRStageParameters")}}</dt>
+ <dd>Представляет значения, описывающие область сцены для устройств, поддерживающих опыт в помещении.</dd>
+</dl>
+
+<h3 id="Расширения_для_других_интерфейсов">Расширения для других интерфейсов</h3>
+
+<p>WebVR API асширяет следующие API, добавляя перечисленные функции.</p>
+
+<h4 id="Геймпад">Геймпад</h4>
+
+<dl>
+ <dt>{{domxref("Gamepad.displayId")}} {{readonlyInline}}</dt>
+ <dd><dfn>Возвращает {{domxref("VRDisplay.displayId")}} связанного с  {{domxref("VRDisplay")}} — <code>VRDisplay</code> , которым гейпад управляет отображаемой сценой.</dfn></dd>
+</dl>
+
+<h4 id="Навигатор">Навигатор</h4>
+
+<dl>
+ <dt>{{domxref("Navigator.activeVRDisplays")}} {{readonlyInline}}</dt>
+ <dd>Возвращает массив, содержащий каждый {{domxref("VRDisplay")}} объект, который в настоящее время отображается ({{domxref("VRDisplay.ispresenting")}} является <code>true</code>).</dd>
+ <dt>{{domxref("Navigator.getVRDisplays()")}}</dt>
+ <dd>Возвращает обещание, которое преобразуется в массив {{domxref("VRDisplay")}} объектов,  представляющих любые доступные VR-дисплеи, подключенные к компьютеру.</dd>
+</dl>
+
+<h4 id="Window_события">Window события</h4>
+
+<dl>
+ <dt>{{domxref("Window.onvrdisplaypresentchange")}}</dt>
+ <dd>Представляет обработчик событий, который будет выполняться, при изменении состояния отображения VR-дисплея — т.е. идёт от отображения до неотображения, или наоброт (когда {{event("vrdisplaypresentchange")}} событие срабатывает).</dd>
+ <dt>{{domxref("Window.onvrdisplayconnect")}}</dt>
+ <dd>Представляет обработчик событий, который будет запускаться, когда к компьютеру подключен совместимый VR-дисплей (когда {{event("vrdisplayconnect")}} событие срабатывает).</dd>
+ <dt>{{domxref("Window.onvrdisplaydisconnect")}}</dt>
+ <dd>Представляет обработчик событий, который будет зпускаться, когда совместимый VR-дисплей был отключён от компьютера (когда {{event("vrdisplaydisconnect")}} событие срабатывает).</dd>
+ <dt>{{domxref("Window.onvrdisplayactivate")}}</dt>
+ <dd>Представляет обработчик событий, который будет выполняться, когда дисплей может быть представлен (когда {{event("vrdisplayactivate")}}событие срабатывает), например, HMD (Head Mounted Display) был перемещён, чтобы вывести его из режима ожидания, или проснулся, будучи перемещенным.</dd>
+ <dt>{{domxref("Window.onvrdisplaydeactivate")}}</dt>
+ <dd>Представляет обработчик событий, который будет запускаться, когда дисплей больше не будет отображаться (когда {{event("vrdisplaydeactivate")}} событие срабатывает), например, HMD (Head Mounted Display) перешёл в режим ожидания или спящий режим из-за периода бездействия.</dd>
+</dl>
+
+<h4 id="Невыполненные_window_события">Невыполненные window события</h4>
+
+<p>Следующие события перечислены в спецификации, but do not currently seem to be implemented anywhere as yet.</p>
+
+<dl>
+ <dt>{{domxref("Window.onvrdisplayblur")}}</dt>
+ <dd>Представляет обработчик событий, который будет выполняться, когда презентация на дисплей была преостановлена по какой-то причине в браузере, ОС или оборудованием VR (когда  {{event("vrdisplayblur")}} событие срабатывает) — например, в то время как пользователь взаимодействует с системным меню или браузером, чтобы предотвратить отслеживание или потерю опыта.</dd>
+ <dt>{{domxref("Window.onvrdisplayfocus")}}</dt>
+ <dd>Представляет обработчик событий, который будет выполняться, когда презентация на дисплей возобновляется после потери фокуса (когда {{event("vrdisplayfocus")}} событие срабатывает).</dd>
+</dl>
+
+<h2 id="Примеры">Примеры</h2>
+
+<p>Вы можете найти несколько примеров в этих местах:</p>
+
+<ul>
+ <li><a href="https://github.com/mdn/webvr-tests">webvr-tests</a> — очень простые примеры для сопровождения MDM WebVR документации.</li>
+ <li><a href="https://github.com/facebook/Carmel-Starter-Kit">Carmel starter kit</a> — простые, хорошо прокомментированные примеры, которые идут вместе с Carmel,браузером WebVR от Facebook's .</li>
+ <li><a href="https://webvr.info/samples/">WebVR.info samples</a> — несколько более подробных примеров плюс исходный код</li>
+ <li><a href="https://webvr.rocks/firefox#demos">WebVR.rocks Firefox demos</a> — демонстрация примеров</li>
+ <li><a href="https://aframe.io/">A-Frame homepage</a> — примеры использования A-Frame</li>
+</ul>
+
+<h2 id="Спецификация">Спецификация</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Спецификация</th>
+ <th scope="col">Статус</th>
+ <th scope="col">Комментарий</th>
+ </tr>
+ <tr>
+ <td>{{SpecName("GamepadExtensions")}}</td>
+ <td>{{Spec2("GamepadExtensions")}}</td>
+ <td>
+ <p>Определяет <a href="/en-US/docs/Web/API/Gamepad_API#Experimental_Gamepad_extensions">Experimental Gamepad extensions</a>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>{{SpecName('WebVR 1.1')}}</td>
+ <td>{{Spec2('WebVR 1.1')}}</td>
+ <td>Первоначальное определение</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Совместимость_с_брауезерами">Совместимость с брауезерами</h2>
+
+<p>{{CompatibilityTable}}</p>
+
+<div id="compat-desktop">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Chrome</th>
+ <th>Edge</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari (WebKit)</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{CompatVersionUnknown}}</td>
+ <td>{{CompatGeckoDesktop(55)}}<sup>[2]</sup></td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ <tr>
+ <td>Gamepad extensions</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}<sup>[3]</sup></td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div id="compat-mobile">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Android Webview</th>
+ <th>Chrome for Android</th>
+ <th>Edge</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>IE Phone</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ <th>Samsung Internet for GearVR</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatVersionUnknown}}<br>
+  </td>
+ </tr>
+ <tr>
+ <td>Gamepad extensions</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}<sup>[3]</sup></td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<p>[1] <a href="https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/explainer.md">Origin trials only</a>.</p>
+
+<p>[2] В настоящее время только в Windows и Mac OSX поддержка включена по умолчанию.</p>
+
+<p>[3] Включено в Firefox Nightly и Beta, версии 55 и выше. Включено / отключено с помощью  <code>dom.gamepad-extensions.enabled</code> pref.</p>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li><a href="https://vr.mozilla.org">vr.mozilla.org</a> — Основная посадочная площадка Mozilla для WebVR с демонстрационными материалами, утилитами и другой информацией.</li>
+ <li><a href="https://aframe.io/">A-Frame</a> — Веб-платформа с открытым исходным кодом для создания опыта VR.</li>
+ <li><a href="https://webvr.info">webvr.info</a> — Актуальная информация о WebVR, настройке браузера и сообществе.</li>
+ <li><a href="http://mozvr.com/">MozVr.com</a> — Демонстрации, загрузки и другие ресурсы от команды Mozilla VR.</li>
+ <li><a href="https://github.com/MozVR/vr-web-examples/tree/master/threejs-vr-boilerplate">threejs-vr-boilerplate</a> — Полезный стартовый шаблон для написания приложений WebVR.</li>
+ <li><a href="https://github.com/googlevr/webvr-polyfill/">Web VR polyfill</a> — JavaScript-реализация WebVR.</li>
+</ul>
diff --git a/files/ru/web/api/webvr_api/using_the_webvr_api/index.html b/files/ru/web/api/webvr_api/using_the_webvr_api/index.html
new file mode 100644
index 0000000000..78aed3b7b7
--- /dev/null
+++ b/files/ru/web/api/webvr_api/using_the_webvr_api/index.html
@@ -0,0 +1,440 @@
+---
+title: Использование WebVR API
+slug: Web/API/WebVR_API/Using_the_WebVR_API
+translation_of: Web/API/WebVR_API/Using_the_WebVR_API
+---
+<div>{{APIRef("WebVR API")}}</div>
+
+<p class="summary">WebVR API - фантастическое дополнение к набору инструментов веб-разработчика, позволяющее отображать WebGL сцены на устройствах виртуальной реальности, таких как Oculus Rift и HTC Vive. Но как же начать разработку VR для Веба? Эта статья познакомит Вас с основами.</p>
+
+<div class="note">
+<p><strong>Обратите внимание</strong>: Наиболее стабильная версия WebVR API — 1.1 — была недавно реализована в Firefox 55 (для Windows в релизной версии, для Mac OS X только в Nightly версии). Так же она доступна в Chrome при использовании Google Daydream. Существует спецификация для следующей версии — 2.0 — но процесс разработки всё ещё находится на ранней стадии. Последнюю информацию можно найти на <a href="https://w3c.github.io/webvr/">WebVR Spec Version List</a>.</p>
+</div>
+
+<h2 id="С_чего_начать">С чего начать</h2>
+
+<p>Для начала Вам понадобится:</p>
+
+<ul>
+ <li>Устройство с поддержкой VR.
+ <ul>
+ <li>Самым дешевым вариантом будет использовать мобильное устройство, какое-нибудь крепление (например, Google Cardboard) и подходящий браузер. Ощущения будут не такие яркие, как от специализированного устройства, но зато Вам не понадобится приобретать мощный компьютер или отдельный VR дисплей.</li>
+ <li>Специализированное устройство может быть дорогим, но зато ощущения будут лучше. Наиболее WebVR-совместимые устройства на данный момент: HTC VIVE, The Oculus Rift. Дополнительную информацию о доступных устройствах и их поддержке браузерами можно найти на <a href="https://webvr.info/">webvr.info</a>.</li>
+ </ul>
+ </li>
+ <li>Компьютер с мощностью, достаточной для соответствующего рендеринга/отображения VR сцен, если вы всё-таки решите воспользоваться специализированным устройством. Чтобы получить некоторое представление о системных требованиях, поищите соответствующие руководства для VR платформы, которую Вы думаете использовать. В качестве примера: <a href="https://www.vive.com/us/ready/">VIVE READY Computers</a>.</li>
+ <li>Подходящий браузер. Последние версии <a href="https://www.mozilla.org/en-US/firefox/channel/desktop/">Firefox Nightly</a> и <a href="https://www.google.com/chrome/index.html">Chrome</a> на данные момент являются лучшими вариантами, как для ПК, так и для мобильных устройств.</li>
+</ul>
+
+<p>После того, как Вы всё подготовили, можете проверить всё ли работает как следует. Для этого надо открыть <a href="https://mdn.github.io/webvr-tests/aframe-demo/">простой A-Frame пример</a> и убедиться, что сцена отображается и что можно перейти в VR режим по нажатию на кнопку в правом нижнем углу.</p>
+
+<p>Фреймворк <a href="https://aframe.io/">A-Frame</a> является лучшим вариантом, если Вы хотите быстро создать WebVR-совместимую сцену, не углубляясь в огромное количество JavaScript кода. Однако, пользуясь им, Вы не узнаете о работе с чистым WebVR API, а именно этим мы сейчас и займемся.</p>
+
+<h2 id="Introducing_our_demo">Introducing our demo</h2>
+
+<p>Рассмотрим как работает WebVR API на примере, проекте raw-webgl-example, который выглядит похожим образом:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15121/Capture1.png" style="display: block; height: 761px; margin: 0px auto; width: 1341px;"></p>
+
+<div class="note">
+<p><strong>Обратите внимание</strong>: Вы можете найти <a href="https://github.com/mdn/webvr-tests/tree/master/raw-webgl-example">исходный код примера</a> на GitHub, а так же <a href="https://mdn.github.io/webvr-tests/raw-webgl-example/">посмотреть как он работает прямо в браузере</a>.</p>
+
+<p>Примечание: если Вы решили просто посмотреть на этот пример, не подключая VR устройство и не используя Firefox , то есть вероятность, что он не будет корректно отображаться при том, что <a href="https://mdn.github.io/webvr-tests/aframe-demo/">простой A-Frame пример</a> работает. В таком случае установите одну из последних версий Firefox, и пример должен отобразиться как на рисунке выше, плюс должна присутствовать анимация.</p>
+</div>
+
+<div class="note">
+<p><strong>Обратите внимание</strong>: Если WebVR не работает в Вашем браузере, то возможно Вам следует убедиться, что работа идёт через видеокарту. Например, для видеокарт фирмы NVIDIA, если у Вас успешно установлена панель управления NVIDIA, по клику правой кнопки на ярлык Firefox появится контекстное меню, в котором можно будет выбрать <em>Run with graphics processor &gt; High-performance NVIDIA processor</em>.</p>
+</div>
+
+<p>Наш пример это своеобразный святой Грааль примеров WebGL  — вращающийся куб в 3D. Реализован этот пример с помощью чистого <a href="/ru/docs/Web/API/WebGL_API">WebGL API</a>. Мы не будем объяснять основы JavaScript или WebGL, а только то, что касается WebVR.</p>
+
+<p>Так же в нашем примере присутствуют:</p>
+
+<ul>
+ <li>Кнопка для начала (и окончания) отображения сцены на VR дисплее.</li>
+ <li>Кнопка, показывающая и скрывающая обновляемые в реальном времени данные о положении и направлении VR устройства.</li>
+</ul>
+
+<p>При просмотре исходного кода <a href="https://github.com/mdn/webvr-tests/blob/master/raw-webgl-example/webgl-demo.js">основного JavaScript файла нашего примера</a>, Вы легко сможете найти части, относящиеся к WebVR, по предваряющим их комментариям. Просто забейте в строку поиска по документу строчку "WebVR".</p>
+
+<div class="note">
+<p><strong>Обратите внимание</strong>: Чтобы узнать больше об основах JavaScript и WebGL, обратитесь к нашим <a href="/ru/docs/Learn/JavaScript">учебным материалам по JavaScript</a> и нашему <a href="/ru/docs/Web/API/WebGL_API/Tutorial">руководству по WebGL</a>.</p>
+</div>
+
+<h2 id="Как_это_работает">Как это работает?</h2>
+
+<p>Пока что, давайте взглянем на части кода, связанные с WebVR.</p>
+
+<p>Типичное (простое) WebVR приложение работает следующим образом:</p>
+
+<ol>
+ <li>{{domxref("Navigator.getVRDisplays()")}} используется для получения ссылки на ваше VR устройство.</li>
+ <li>{{domxref("VRDisplay.requestPresent()")}} используется для начала отображения сцены на VR устройстве.</li>
+ <li>{{domxref("VRDisplay.requestAnimationFrame()")}} используется при создании цикла отображения кадров анимации с правильной для выбранного устройства частотой обновления.</li>
+ <li>Внутри цикла сначала, для получения данных необходимых для отображения кадра, используется ({{domxref("VRDisplay.getFrameData()")}}). Затем сцена отрисовывается дважды (по разу для каждого глаза в соответствующей ему области видимости), а потом отображается с помощью функции ({{domxref("VRDisplay.submitFrame()")}}).</li>
+</ol>
+
+<p>In the below sections we'll look at our raw-webgl-demo in detail, and see where exactly the above features are used.</p>
+
+<h3 id="Starting_with_some_variables">Starting with some variables</h3>
+
+<p>The first WebVR-related code you'll meet is this following block:</p>
+
+<pre class="brush: js">// WebVR variables
+
+var frameData = new VRFrameData();
+var vrDisplay;
+var btn = document.querySelector('.stop-start');
+var normalSceneFrame;
+var vrSceneFrame;
+
+var poseStatsBtn = document.querySelector('.pose-stats');
+var poseStatsSection = document.querySelector('section');
+poseStatsSection.style.visibility = 'hidden'; // hide it initially
+
+var posStats = document.querySelector('.pos');
+var orientStats = document.querySelector('.orient');
+var linVelStats = document.querySelector('.lin-vel');
+var linAccStats = document.querySelector('.lin-acc');
+var angVelStats = document.querySelector('.ang-vel');
+var angAccStats = document.querySelector('.ang-acc');
+var poseStatsDisplayed = false;</pre>
+
+<p>Let's briefly explain these:</p>
+
+<ul>
+ <li><code>frameData</code> contains a {{domxref("VRFrameData")}} object, created using the {{domxref("VRFrameData.VRFrameData", "VRFrameData()")}} constructor. This is initially empty, but will later contain the data required to render each frame to show in the VR display, updated constantly as the rendering loop runs.</li>
+ <li><code>vrDisplay</code> starts uninitialized, but will later on hold a reference to our VR headset ({{domxref("VRDisplay")}} — the central control object of the API).</li>
+ <li><code>btn</code> and <code>poseStatsBtn</code> hold references to the two buttons we are using to control our app.</li>
+ <li><code>normalSceneFrame</code> and <code>vrSceneFrame</code> start uninitialized, but later on will hold references to {{domxref("Window.requestAnimationFrame()")}} and {{domxref("VRDisplay.requestAnimationFrame()")}} calls — these will initiate the running of a normal rendering loop, and a special WebVR rendering loop; we'll explain the difference between these two later on.</li>
+ <li>The other variables store references to different parts of the VR pose data display box, which you can see in the bottom right hand corner of the UI.</li>
+</ul>
+
+<h3 id="Getting_a_reference_to_our_VR_display">Getting a reference to our VR display</h3>
+
+<p>One of the major functions inside our code is <code>start()</code> — we run this function when the body has finished loading:</p>
+
+<pre class="brush: js">// start
+//
+// Called when the body has loaded is created to get the ball rolling.
+
+document.body.onload = start;</pre>
+
+<p>To begin with, <code>start()</code> retrieves a WebGL context to use to render 3D graphics into the {{htmlelement("canvas")}} element in <a href="https://github.com/mdn/webvr-tests/blob/master/raw-webgl-example/index.html">our HTML</a>. We then check whether the <code>gl</code> context is available — if so, we run a number of functions to set up the scene for display.</p>
+
+<pre class="brush: js">function start() {
+ canvas = document.getElementById("glcanvas");
+
+ initWebGL(canvas); // Initialize the GL context
+
+ // WebGL setup code here</pre>
+
+<p>Next, we start the process of actually rendering the scene onto the canvas, by setting the canvas to fill the entire browser viewport, and running the rendering loop (<code>drawScene()</code>) for the first time. This is the non-WebVR — normal — rendering loop.</p>
+
+<pre class="brush: js"> // 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();</pre>
+
+<p>Now onto our first WebVR-specific code. First of all, we check to see if {{domxref("Navigator.getVRDisplays")}} exists — this is the entry point into the API, and therefore good basic feature detection for WebVR. You'll see at the end of the block (inside the <code>else</code> clause) that if this doesn't exist, we log a message to indicate that WebVR 1.1 isn't supported by the browser.</p>
+
+<pre class="brush: js"> // WebVR: Check to see if WebVR is supported
+ if(navigator.getVRDisplays) {
+ console.log('WebVR 1.1 supported');</pre>
+
+<p>Inside our <code>if() { ... }</code> block, we run the {{domxref("Navigator.getVRDisplays()")}} function. This returns a promise, which is fulfilled with an array containing all the VR display devices connected to the computer. If none are connected, the array will be empty.</p>
+
+<pre class="brush: js"> // Then get the displays attached to the computer
+ navigator.getVRDisplays().then(function(displays) {</pre>
+
+<p>Inside the promise <code>then()</code> block, we check whether the array length is more than 0; if so, we set the value of our <code>vrDisplay</code> variable to the 0 index item inside the array. <code>vrDisplay</code> now contains a {{domxref("VRDisplay")}} object representing our connected display!</p>
+
+<pre class="brush: js"> // If a display is available, use it to present the scene
+ if(displays.length &gt; 0) {
+ vrDisplay = displays[0];
+ console.log('Display found');</pre>
+
+<div class="note">
+<p><strong>Note</strong>: It is unlikely that you'll have multiple VR displays connected to your computer, and this is just a simple demo, so this will do for now.</p>
+</div>
+
+<h3 id="Starting_and_stopping_the_VR_presentation">Starting and stopping the VR presentation</h3>
+
+<p>Now we have a {{domxref("VRDisplay")}} object, we can use it do a number of things. The next thing we want to do is wire up functionality to start and stop presentation of the WebGL content to the display.</p>
+
+<p>Continuing on with the previous code block, we now add an event listener to our start/stop button (<code>btn</code>) — when this button is clicked we want to check whether we are presenting to the display already (we do this in a fairly dumb fashion, by checking what the button <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> contains).</p>
+
+<p>If the display is not already presenting, we use the {{domxref("VRDisplay.requestPresent()")}} method to request that the browser start presenting content to the display. This takes as a parameter an array of the {{domxref("VRLayerInit")}} objects representing the layers you want to present in the display.</p>
+
+<p>Since the maximum number of layers you can display is currently 1, and the only required object member is the {{domxref("VRLayerInit.source")}} property (which is a reference to the {{htmlelement("canvas")}} you want to present in that layer; the other parameters are given sensible defaults — see {{domxref("VRLayerInit.leftBounds", "leftBounds")}} and {{domxref("VRLayerInit.rightBounds", "rightBounds")}})), the parameter is simply [{ source: canvas }].</p>
+
+<p><code>requestPresent()</code> returns a promise that is fulfilled when the presentation begins successfully.</p>
+
+<pre class="brush: js"> // Starting the presentation when the button is clicked: It can only be called in response to a user gesture
+ btn.addEventListener('click', function() {
+ if(btn.textContent === 'Start VR display') {
+ vrDisplay.requestPresent([{ source: canvas }]).then(function() {
+ console.log('Presenting to WebVR display');</pre>
+
+<p>With our presentation request successful, we now want to start setting up to render content to present to the VRDisplay. First of all we set the canvas to the same size as the VR display area. We do this by getting the {{domxref("VREyeParameters")}} for both eyes using {{domxref("VRDisplay.getEyeParameters()")}}.</p>
+
+<p>We then do some simple math to calculate the total width of the VRDisplay rendering area based on the eye {{domxref("VREyeParameters.renderWidth")}} and {{domxref("VREyeParameters.renderHeight")}}.</p>
+
+<pre class="brush: js"> // Set the canvas size to the size of the vrDisplay viewport
+
+ var leftEye = vrDisplay.getEyeParameters('left');
+ var rightEye = vrDisplay.getEyeParameters('right');
+
+ canvas.width = Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2;
+ canvas.height = Math.max(leftEye.renderHeight, rightEye.renderHeight);</pre>
+
+<p>Next, we {{domxref("Window.cancelAnimationFrame()", "cancel the animation loop")}} previously set in motion by the {{domxref("Window.requestAnimationFrame()")}} call inside the <code>drawScene()</code> function, and instead invoke <code>drawVRScene()</code>. This function renders the same scene as before, but with some special WebVR magic going on. The loop inside here is maintained by WebVR's special {{domxref("VRDisplay.requestAnimationFrame")}} method.</p>
+
+<pre class="brush: js"> // stop the normal presentation, and start the vr presentation
+ window.cancelAnimationFrame(normalSceneFrame);
+ drawVRScene();</pre>
+
+<p>Finally, we update the button text so that the next time it is pressed, it will stop presentation to the VR display.</p>
+
+<pre class="brush: js"> btn.textContent = 'Exit VR display';
+ });</pre>
+
+<p><br>
+ To stop the VR presentation when the button is subsequently pressed, we call {{domxref("VRDisplay.exitPresent()")}}. We also reverse the button's text content, and swap over the <code>requestAnimationFrame</code> calls. You can see here that we are using {{domxref("VRDisplay.cancelAnimationFrame")}} to stop the VR rendering loop, and starting the normal rendering loop off again by calling <code>drawScene()</code>.</p>
+
+<pre class="brush: js"> } 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.');
+ }
+ }
+}</pre>
+
+<p>Once the presentation starts, you'll be able to see the stereoscopic view displayed in the browser:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15123/Capture2.png" style="display: block; margin: 0 auto;"></p>
+
+<p>You'll learn below how the stereoscopic view is actually produced.</p>
+
+<h3 id="Why_does_WebVR_have_its_own_requestAnimationFrame()">Why does WebVR have its own requestAnimationFrame()?</h3>
+
+<p>This is a good question. The reason is that for smooth rendering inside the VR display, you need to render the content at the display's native refresh rate, not that of the computer. VR display refresh rates are greater than PC refresh rates, typically up to 90fps. The rate will be differ from the computer's core refresh rate.</p>
+
+<p>Note that when the VR display is not presenting, {{domxref("VRDisplay.requestAnimationFrame")}} runs identically to {{domxref("Window.requestAnimationFrame")}}, so if you wanted, you could just use a single rendering loop, rather than the two we are using in our app. We have used two because we wanted to do slightly different things depending on whether the VR display is presenting or not, and keep things separated for ease of comprehension.</p>
+
+<h3 id="Rendering_and_display">Rendering and display</h3>
+
+<p>At this point, we've seen all the code required to access the VR hardware, request that we present our scene to the hardware, and start running the rending loop. Let's now look at the code for the rendering loop, and explain how the WebVR-specific parts of it work.</p>
+
+<p>First of all, we begin the definition of our rendering loop function — <code>drawVRScene()</code>. The first thing we do inside here is make a call to {{domxref("VRDisplay.requestAnimationFrame()")}} to keep the loop running after it has been called once (this occurred earlier on in our code when we started presenting to the VR display). This call is set as the value of the global <code>vrSceneFrame</code> variable, so we can cancel the loop with a call to {{domxref("VRDisplay.cancelAnimationFrame()")}} once we exit VR presenting.</p>
+
+<pre class="brush: js">function drawVRScene() {
+ // WebVR: Request the next frame of the animation
+ vrSceneFrame = vrDisplay.requestAnimationFrame(drawVRScene);</pre>
+
+<p>Next, we call {{domxref("VRDisplay.getFrameData()")}}, passing it the name of the variable that we want to use to contain the frame data. We initialized this earlier on — <code>frameData</code>. After the call completes, this variable will contain the data need to render the next frame to the VR device, packaged up as a {{domxref("VRFrameData")}} object. This contains things like projection and view matrices for rendering the scene correctly for the left and right eye view, and the current {{domxref("VRPose")}} object, which contains data on the VR display such as orientation, position, etc.</p>
+
+<p>This has to be called on every frame so the rendered view is always up-to-date.</p>
+
+<pre class="brush: js"> // Populate frameData with the data of the next frame to display
+ vrDisplay.getFrameData(frameData);</pre>
+
+<p>Now we retrieve the current {{domxref("VRPose")}} from the {{domxref("VRFrameData.pose")}} property, store the position and orientation for use later on, and send the current pose to the pose stats box for display, if the <code>poseStatsDisplayed</code> variable is set to true.</p>
+
+<pre class="brush: js"> // You can get the position, orientation, etc. of the display from the current frame's pose
+
+ var curFramePose = frameData.pose;
+ var curPos = curFramePose.position;
+ var curOrient = curFramePose.orientation;
+ if(poseStatsDisplayed) {
+ displayPoseStats(curFramePose);
+ }</pre>
+
+<p>  We now clear the canvas before we start drawing on it, so that the next frame is clearly seen, and we don't also see previous rendered frames:</p>
+
+<pre class="brush: js"> // Clear the canvas before we start drawing on it.
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);</pre>
+
+<p>We now render the view for both the left and right eyes. First of all we need to create projection and view locations for use in the rendering. these are {{domxref("WebGLUniformLocation")}} objects, created using the {{domxref("WebGLRenderingContext.getUniformLocation()")}} method, passing it the shader program's identifier and an identifying name as parameters.</p>
+
+<pre class="brush: js"> // WebVR: Create the required projection and view matrix locations needed
+ // for passing into the uniformMatrix4fv methods below
+
+ var projectionMatrixLocation = gl.getUniformLocation(shaderProgram, "projMatrix");
+ var viewMatrixLocation = gl.getUniformLocation(shaderProgram, "viewMatrix");</pre>
+
+<p>The next rendering step involves:</p>
+
+<ul>
+ <li>Specifying the viewport size for the left eye, using {{domxref("WebGLRenderingContext.viewport")}} — this is logically the first half of the canvas width, and the full canvas height.</li>
+ <li>Specifying the view and projection matrix values to use to render the left eye — this is done using the {{domxref("WebGLRenderingContext.uniformMatrix", "WebGLRenderingContext.uniformMatrix4fv")}} method, which is passed the location values we retrieved above, and the left matrices obtained from the {{domxref("VRFrameData")}} object.</li>
+ <li>Running the <code>drawGeometry()</code> function, which renders the actual scene — because of what we specified in the previous two steps, we will render it for the left eye only.</li>
+</ul>
+
+<pre class="brush: js"> // 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();</pre>
+
+<p>We now do exactly the same thing, but for the right eye:</p>
+
+<pre class="brush: js"> // 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();</pre>
+
+<p>Next we define our <code>drawGeometry()</code> function. Most of this is just general WebGL code required to draw our 3D cube. You'll see some WebVR-specific parts in the <code>mvTranslate()</code> and <code>mvRotate()</code> function calls — these pass matrices into the WebGL program that define the translation and rotation of the cube for the current frame</p>
+
+<p>You'll see that we are modifying these values by the position (<code>curPos</code>) and orientation (<code>curOrient</code>) of the VR display we got from the {{domxref("VRPose")}} object. The result is that, for example, as you move or rotate your head left, the x position value (<code>curPos[0]</code>) and y rotation value (<code>[curOrient[1]</code>) are added to the x translation value, meaning that the cube will move to the right, as you'd expect when you are looking at something and then move/turn your head left.</p>
+
+<p>This is a quick and dirty way to use VR pose data, but it illustrates the basic principle.</p>
+
+<pre class="brush: js"> 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();
+ }
+</pre>
+
+<p>The next bit of the code has nothing to do with WebVR — it just updates the rotation of the cube on each frame:</p>
+
+<pre class="brush: js"> // Update the rotation for the next draw, if it's time to do so.
+
+ var currentTime = (new Date).getTime();
+ if (lastCubeUpdateTime) {
+ var delta = currentTime - lastCubeUpdateTime;
+
+ cubeRotation += (30 * delta) / 1000.0;
+ }
+
+ lastCubeUpdateTime = currentTime;</pre>
+
+<p>The last part of the rendering loop involves us calling {{domxref("VRDisplay.submitFrame()")}} — now all the work has been done and we've rendered the display on the {{htmlelement("canvas")}}, this method then submits the frame to the VR display so it is displayed on there as well.</p>
+
+<pre class="brush: js"> // WebVR: Indicate that we are ready to present the rendered frame to the VR display
+ vrDisplay.submitFrame();
+}</pre>
+
+<h3 id="Displaying_the_pose_(position_orientation_etc.)_data">Displaying the pose (position, orientation, etc.) data</h3>
+
+<p>In this section we'll discuss the <code>displayPoseStats()</code> function, which displays our updated pose data on each frame. The function is fairly simple.</p>
+
+<p>First of all, we store the six different property values obtainable from the {{domxref("VRPose")}} object in their own variables — each one is a {{domxref("Float32Array")}}.</p>
+
+<pre class="brush: js">function displayPoseStats(pose) {
+ var pos = pose.position;
+ var orient = pose.orientation;
+ var linVel = pose.linearVelocity;
+ var linAcc = pose.linearAcceleration;
+ var angVel = pose.angularVelocity;
+ var angAcc = pose.angularAcceleration;</pre>
+
+<p>We then write out the data into the information box, updating it on every frame. We've clamped each value to three decimal places using <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed">toFixed()</a></code>, as the values are hard to read otherwise.</p>
+
+<p>You should note that we've used a conditional expression to detect whether the linear acceleration and angular acceleration arrays are successfully returned before we display the data. These values are not reported by most VR hardware as yet, so the code would throw an error if we did not do this (the arrays return <code>null</code> if they are not successfully reported).</p>
+
+<pre class="brush: js"> 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';
+ }
+}</pre>
+
+<h2 id="WebVR_events">WebVR events</h2>
+
+<p>The WebVR spec features a number of events that are fired, allowing our app code to react to changes in the state of the VR display (see <a href="/en-US/docs/Web/API/WebVR_API#Window_events">Window events</a>). For example:</p>
+
+<ul>
+ <li>{{event("vrdisplaypresentchange")}} — Fires when the presenting state of a VR display changes — i.e. goes from presenting to not presenting, or vice versa.</li>
+ <li>{{event("vrdisplayconnect")}} — Fires when a compatible VR display has been connected to the computer.</li>
+ <li>{{event("vrdisplaydisconnect")}} — Fires when a compatible VR display has been disconnected from the computer.</li>
+</ul>
+
+<p>To demonstrate how they work, our simple demo includes the following example:</p>
+
+<pre class="brush: js">window.addEventListener('vrdisplaypresentchange', function(e) {
+ console.log('Display ' + e.display.displayId + ' presentation has changed. Reason given: ' + e.reason + '.');
+});</pre>
+
+<p>As you can see, the {{domxref("VRDisplayEvent", "event object")}} provides two useful properties — {{domxref("VRDisplayEvent.display")}}, which contains a reference to the {{domxref("VRDisplay")}} the event was fired in response to, and {{domxref("VRDisplayEvent.reason")}}, which contains a human-readable reason why the event was fired.</p>
+
+<p>This is a very useful event; you could use it to handle cases where the display gets disconnected unexpectedly, stopping errors from being thrown and making sure the user is aware of the situation. In Google's Webvr.info presentation demo, the event is used to run an <a href="https://github.com/toji/webvr.info/blob/master/samples/03-vr-presentation.html#L174"><code>onVRPresentChange()</code> function</a>, which updates the UI controls as appropriate and resizes the canvas.</p>
+
+<h2 id="Summary">Summary</h2>
+
+<p>This article has given you the very basics of how to create a simple WebVR 1.1 app, to help you get started.</p>