From 1109132f09d75da9a28b649c7677bb6ce07c40c0 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:41:45 -0500 Subject: initial commit --- files/fi/web/api/webvr_api/index.html | 250 ++++++++++++ .../api/webvr_api/using_the_webvr_api/index.html | 438 +++++++++++++++++++++ 2 files changed, 688 insertions(+) create mode 100644 files/fi/web/api/webvr_api/index.html create mode 100644 files/fi/web/api/webvr_api/using_the_webvr_api/index.html (limited to 'files/fi/web/api/webvr_api') diff --git a/files/fi/web/api/webvr_api/index.html b/files/fi/web/api/webvr_api/index.html new file mode 100644 index 0000000000..e3b73598f2 --- /dev/null +++ b/files/fi/web/api/webvr_api/index.html @@ -0,0 +1,250 @@ +--- +title: WebVR API +slug: Web/API/WebVR_API +tags: + - API + - Experimental + - Expérimental(2) + - Landing + - NeedsTranslation + - Reference + - Référence(2) + - TopicStub + - VR + - Virtual Reality + - WebVR +translation_of: Web/API/WebVR_API +--- +

{{SeeCompatTable}}{{APIRef("WebVR API")}}

+ +

WebVR -rajapinta tarjoaa tuen VR-laitteiden — kuten Oculus Rift tai HTC Vive -silmikoiden — käyttämiseen webbisovelluksille, jolloin kehittäjät voivat muuttaa silmikolta saadun sijainti- ja liiketiedon 3D-skenessä liikkumistiedoksi. Tämä mahdollistaa useita kiinnostavia sovellusmahdollisuuksia aina virtuaalisista tuote-esittelyistä ja interaktiivisista treenisovelluksista immersiivisiin FPS-räiskintäpeleihin.

+ +

Perusperiaatteet ja käyttö

+ +

Metodi {{domxref("Navigator.getVRDisplays()")}} hakee kaikki tietokoneeseen liitetyt VR-laitteet; jokaista näistä vastaa {{domxref("VRDisplay")}} -tyyppinen objekti.

+ +

Sketch of a person in a chair with wearing goggles labelled "Head mounted display (HMD)" facing a monitor with a webcam labelled "Position sensor"

+ +

{{domxref("VRDisplay")}} on perusrajapinta WebVR API:in — sen ominaisuuksien ja metodien avulla voit esimerkiksi:

+ + + +

Tyypillinen (yksinkertainen) WebVR-sovellus toimisi esimerkiksi näin:

+ +
    +
  1. {{domxref("Navigator.getVRDisplays()")}} -metodilla haetaan viittaus VR-näyttöön.
  2. +
  3. {{domxref("VRDisplay.requestPresent()")}} -metodilla käynnistetään näyttäminen.
  4. +
  5. WebVR:n omalla versiolla {{domxref("VRDisplay.requestAnimationFrame()")}} -methodista suoritetaan sovelluksen renderöintisilmukkaa näytölle sopivalla virkistystaajuudella.
  6. +
  7. Renderöintisilmukassa haetaan ruudun näyttämiseen tarvittavat tiedot ({{domxref("VRDisplay.getFrameData()")}}) -metodilla, piirretään näytettävä skene kaksi kertaa — siis kerran molemmille silmille, ja sen jälkeen toimitetaan renderöity näkymä näytölle käyttäjälle näytettäväksi metodilla ({{domxref("VRDisplay.submitFrame()")}}).
  8. +
+ +

Tämän lisäksi WebVR 1.1 lisää useita tapahtumia (event) {{domxref("Window")}} -objektiin, jolloin JavaScriptillä voidaan reagoida näytön tilan muutoksiin.

+ +

Huom: APIn toiminnasta löytyy paljon lisätietoa artikkeleista Using the WebVR API ja WebVR Concepts.

+ +

Ohjaimien käyttö: WebVR:n yhdistäminen Gamepad API:in

+ +

Useissa WebVR-laitekokoonpanoissa silmikon mukana on käytettävissä erillinen ohjain. Ohjaimia voidaan käyttää WebVR-sovelluksissa Gamepad API:n kautta, ja erityisesti Gamepad Extensions API:n, joka lisää mukaan ohjaimen asentotiedon (controller pose), tuntoperusteiset laitteet (haptic actuators) ja muita vastaavia.

+ +

Huom: Artikkeli Using VR controllers with WebVR selittää perusteet VR-ohjaimien käytöstä WebVR-sovelluksissa.

+ +

WebVR rajapinnat

+ +
+
{{domxref("VRDisplay")}}
+
Edustaa mitä tahnsa APIn tukemaa VR-laitetta. Siinä on mukana yleistiedot laittesta, kuten laitteen tunnisteet (ID) ja kuvaukset sekä metodit VR-skenen esittämisen käynnistämiseen, silmäparametrien ja näytön ominaisuuksien hakemiseen ja muut olennaiset toiminnat.
+
{{domxref("VRDisplayCapabilities")}}
+
Esittää {{domxref("VRDisplay")}}:n ominaisuudet — näillä voidaan testata, saako laitteelta esimerkiksi sijaintitietoa.
+
{{domxref("VRDisplayEvent")}}
+
Edustaa WebVR-kohtaisen tapahtuman tapahtumaobjektia (kts. {{anch("Window", "window object extensions")}} alempana).
+
{{domxref("VRFrameData")}}
+
Vastaa kaikkea tietoa, mitä yksittäisen VR-skenen ruudun renderöintiin tarvitaan; metodi {{domxref("VRDisplay.getFrameData()")}} hakee nämä tiedot.
+
{{domxref("VRPose")}}
+
Edustaa tietyllä ajanhetkellä vallitsevaa sijaintitietoa (johon kuuluvat suunta, sijainti, nopeus ja kiihtyvyys.)
+
{{domxref("VREyeParameters")}}
+
Tarjoaa pääsyn kaikkeen tietoon, joka tarvitaan skenen renderöintiin oikein kullekin silmälle, esimerkiksi näkökentän laajuuden.
+
{{domxref("VRFieldOfView")}}
+
Näkökenttätieto, joka on määritelty keskipisteestä katsottuna neljällä asteluvulla.
+
{{domxref("VRLayerInit")}}
+
Tämä on {{domxref("VRDisplay")}}-näytöllä esitettävä kuvan eräs taso (layer).
+
{{domxref("VRStageParameters")}}
+
Huoneskaalaa tukevien laitteiden kanssa käytettävissä sovelluksissa "näyttämöalueen" tiedot löytyvät tästä.
+
+ +

Laajennukset muihin rajapintoihin

+ +

WebVR API laajentaa joitakin API-rajapintoja lisäten seuraavat ominaisuudet.

+ +

Gamepad

+ +
+
{{domxref("Gamepad.displayId")}} {{readonlyInline}}
+
Palauttaa liitetyn {{domxref("VRDisplay")}} tunnisteen {{domxref("VRDisplay.displayId")}} — VRDisplay , jonka skeneä gamepad ohjaa.
+
+ + + +
+
{{domxref("Navigator.activeVRDisplays")}} {{readonlyInline}}
+
Palauttaa taulukon, jossa on mukana jokainen {{domxref("VRDisplay")}}, joka esittää parhaillaan ({{domxref("VRDisplay.ispresenting")}} on true).
+
{{domxref("Navigator.getVRDisplays()")}}
+
Palauttaa promise-objektin, joka sisältää taulukon {{domxref("VRDisplay")}} objekteja, jotka vastaavat kaikkia tietokoneeseen liitettyjä VR-näyttöjä.
+
+ +

Window-tapahtumat

+ +
+
{{domxref("Window.onvrdisplaypresentchange")}}
+
Edustaa tapahtumankäsittelijää (event handler), joka suoritetaan, kun VR_näytön esittämistila muuttuu — esimerkiksi tilasta 'esittää' tilaan 'ei esitä' tai päinvastoin (kun tapahtuma {{event("vrdisplaypresentchange")}} signaloidaan).
+
{{domxref("Window.onvrdisplayconnect")}}
+
Tämä tapahtumankäsittelijä suoritetaan, kun yhteensopiva VR-näyttö on kytketty tietokoneeseen (tapahtuma {{event("vrdisplayconnect")}} ).
+
{{domxref("Window.onvrdisplaydisconnect")}}
+
Tämä tapahtumankäsittelijä suoritetaan, kun yhteensopiva VR-näyttö irrotetaan tietokoneesta (kun tapahtuma {{event("vrdisplaydisconnect")}} signaloidaan).
+
{{domxref("Window.onvrdisplayactivate")}}
+
Edustaa taphtumaa, joka suoritetaan, kun näyttö on valmis esittämään sisältöä (tapahtuma {{event("vrdisplayactivate")}} ),esimerkiksi kun silmikko aktivoituu virransäästötilasta tai puetaan päälle.
+
{{domxref("Window.onvrdisplaydeactivate")}}
+
Tämä tapahtumankäsittelijä suoritetaan, kun näytölle ei voi enää esittää sisältöä (kun tapahtuma {{event("vrdisplaydeactivate")}} signaloidaan), esimerkiksi syystä, että silmikkonäyttö on siirtynyt virransäästötilaan käyttämättömyyden vuoksi.
+
+ +

Window:n tapahtumat, jotka eivät ole käytettävissä

+ +

Seuraavat tapahtumat löytyvät APIn määrittelystä, mutta niiden toteutusta ei tunnu vielä löytyvän mistään selaimista.

+ +
+
{{domxref("Window.onvrdisplayblur")}}
+
Edustaa tapahtumankäsittelijää, joka suoritetaan kun selain, käyttöjärjestelmä tai VR-laitteisto on keskeyttänyt esittämisen näytölle jostain syystä (tapahtuman {{event("vrdisplayblur")}} johdosta) — esimerkiksi käytettäessä järjestelmän valikkoa tai selainta. Tarkoitus on estää seurantaa tai VR-kokemuksen menetystä.
+
{{domxref("Window.onvrdisplayfocus")}}
+
Tämä tapahtumankäsittelijä suoritetaan, kun esittäminen näytöllä palautuu edellisen tapahtuman jälkeen (tapahtumasta {{event("vrdisplayfocus")}} ).
+
+ +

Esimerkkejä

+ +

Näiltä sivustoilta töydät useita esimerkkejä:

+ + + +

Spesifikaatiot

+ + + + + + + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName("GamepadExtensions")}}{{Spec2("GamepadExtensions")}}Määrittää Experimental Gamepad extensions.
{{SpecName('WebVR 1.1')}}{{Spec2('WebVR 1.1')}}Alkuperäinen
+ +

Selainyhteensopivuus

+ +

{{CompatibilityTable}}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OminaisuusChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari (WebKit)
Perus{{CompatNo}}[1]{{CompatVersionUnknown}}{{CompatGeckoDesktop(55)}}[2]{{CompatNo}}{{CompatNo}}{{CompatNo}}
Gamepad -laajennukset{{CompatNo}}{{CompatNo}}{{CompatNo}}[4]{{CompatNo}}{{CompatNo}}{{CompatNo}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidEdgeFirefox Mobile (Gecko)IE PhoneOpera MobileSafari MobileChrome for AndroidSamsung Internet for GearVR
Basic support{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatVersionUnknown}}[3]{{CompatVersionUnknown}}
+  
Gamepad extensions{{CompatNo}}{{CompatNo}}{{CompatNo}}[4]{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
+ +

[1] API käytettävissä (Available) kaikilla alustoilla lipulla, mutta tällä hetkellä toimii ainoastaan kokeellisessa työpöytäversiossa (experimental version of Chrome) (muut versiot eivät palauta yhtään laitetta metodia {{domxref("Navigator.getVRDisplays()")}} kutsuttaessa).

+ +

[2] Tällä hetkellä ainoastaan Windows ja Mac OSX tuki on oletuksena päällä.

+ +

[3] Nyt ainoastaan laitteella Google Daydream.

+ +

[4] Päällä Firefox Nightly ja Beta -versioissa 55 ja uudempi. Käytetään valinnalla dom.gamepad-extensions.enabled.

+ +

Katso myös

+ + diff --git a/files/fi/web/api/webvr_api/using_the_webvr_api/index.html b/files/fi/web/api/webvr_api/using_the_webvr_api/index.html new file mode 100644 index 0000000000..b4cf17e315 --- /dev/null +++ b/files/fi/web/api/webvr_api/using_the_webvr_api/index.html @@ -0,0 +1,438 @@ +--- +title: Using the WebVR API +slug: Web/API/WebVR_API/Using_the_WebVR_API +translation_of: Web/API/WebVR_API/Using_the_WebVR_API +--- +
{{APIRef("WebVR API")}}
+ +

WebVR API on hieno lisä webkehittäjän työkaluihin. Sen avulla WebGL- näkymä (scene) voidaan esittää Oculus Riftin and HTC Viven tapaisissa VR-näytöissä. Mutta miten pääset alkuun VR appsien tekemiseen webbiin? Tämä juttu opastaa sinut perusteisiin.

+ +
+

Huom: WebVR APIn vakain versio — 1.1 — on vasta implementoitu Firefox 55:een (Windowsin release-versio, Mac OS X :ssa vain 'Nightly'), ja sen saa myös Chrome:en käytettäessä Google Daydream -laitteistoa. Speksistä on myös tuoreempi versio — 2.0 — mutta se on kovin keskeneräinen. Lisätietoja viimeisimmästä speksistä löytyy linkistä WebVR Spec Version List.

+
+ +

Aloitus

+ +

Päästäksesi alkuun tarvitset:

+ + + +

Kun laitteisto ja ohjelmistot on asennettu, voit testata, toimiiko kokoonpanosi WebVR:n kanssa tästä linkistä - simple A-Frame demo, ja näet, saadaanko näkymä näkyviin ja pääsetkö VR-moodiin oikean alareunan painikkeella.

+ +

A-Frame on paras vaihtoehto päästä tekemään nopeasti WebVR-yhteensopivia 3D-näkymiä, ilman että tarvitsee ymmärtää rivikaupalla uutta JavaScript -koodia. Se ei kuitenkaan opeta, kuinka raaka WebVR API toimii ja siihen paneudummekin seuraavaksi.

+ +

Demon esittely

+ +

WebVR API :n toiminnan esdittelemiseksi tutustumme puhtaasti webgl:ää sisältävään esimerkkiimme, joka näyttää vähän tältä:

+ +

+ +
+

Huom: Demon lähdekoodi - source code - löytyy GitHubista ja livelinkki siihen on tässä: view it live.

+
+ +
+

Huom: Ellei WebVR ei ala toimia selaimessa, varmista, että sitä ajetaan grafiikkakortin kautta. Esimerkiksi NVIDIA :lla sen omassa ohjauspaneelissa on pikavalikkovalinta Firefox, josta valitaan Run with graphics processor > High-performance NVIDIA processor.

+
+ +

Demossa on kaikkien WebGL-demojen äiti — pyörivä  3D-kuutio. Toteutimme sen puhtaasti WebGL API :n koodilla. Tässä ei käsitellä perus JavaScriptiä tai WebGL:ää, vaan pelkästään WebVR osia.

+ +

Demosta löytyy myös:

+ + + +

Kun tutustut lähdekoodin päätiedostoon - main JavaScript file - löydät WebVR-osat koodista kommenttien "WebVR" tekstien avulla.

+ +
+

Huom: JavaScriptin ja WebGL:n perusteista lisätietoja löytyy tutoriaaleista JavaScript learning material ja WebGL Tutorial.

+
+ +

Miten se toimii?

+ +

Tässä vaiheessa katsotaan koodin WebVR-osien toiminta.

+ +

Tyypillinen (yksinkertainen) WebVR sovellus toimii näin:

+ +
    +
  1. {{domxref("Navigator.getVRDisplays()")}} hakee viittauksen VR-näyttöösi.
  2. +
  3. {{domxref("VRDisplay.requestPresent()")}} :ä käytetään käynnistämään esittäminen VR-näytölle.
  4. +
  5. WebVR:n omaa {{domxref("VRDisplay.requestAnimationFrame()")}} -metodia käytetään suorittamaan sovelluksen renderöintisilmukkaa näytölle sopivalla virkistystaajuudella.
  6. +
  7. Renderöintisilmukassa haet ruudun näyttämiseen vaaditun datan ({{domxref("VRDisplay.getFrameData()")}}), piirrät näytettävän skenen kahdesti — molemmille silmille — ja toimitat renderöidyn näkymän näytölle käyttäjälle näytettäväksi metodilla ({{domxref("VRDisplay.submitFrame()")}}).
  8. +
+ +

Alla olevissa kappaleissa tutustutaan webgl-demoihimme yksityiskohtaisemmin ja nähdään tarkemmin, missä edellä mainittuja ominaisuuksia käytetään.

+ +

Aloitetaan muuttujilla

+ +

Ensimmäinen esimerkki WebVR:n käytöstä näkyy alla olevassa koodissa:

+ +
// 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;
+ +

Lyhyet selitykset ovat siis tarpeen:

+ + + +

VR-näytön hakeminen

+ +

Koodimme tärkeimpiä metodeja on start() — tämä suoritetaan, kun sivun body-osa on ladattu valmiiksi:

+ +
// start
+//
+// Called when the body has loaded is created to get the ball rolling.
+
+document.body.onload = start;
+ +

Aluksistart() hakee webbisivumme - our HTML - {{htmlelement("canvas")}} -osaan renderöitävään 3D-grafiikkaan tarvitun WebGL -ympäristön. Sitten tarkistetaan, että gl -ympäristö on käytettävissä — jos on, suoritetaan muutama metodi näytettävän skenen alustamiseksi.

+ +
function start() {
+  canvas = document.getElementById("glcanvas");
+
+  initWebGL(canvas);      // Initialize the GL context
+
+  // WebGL setup code here
+ +

Seuraavaksi aloitetaan varsinainen näyttöprosessi. Siinä asetetaan canvas-elementti näyttämään selaimen koko näytettävä ala ja suorittamalla renderöintisilmukka(drawScene()) ensimmäisen kerran. Tässä siis ei-WebVR osuus— se normaali renderöintisilmukka.

+ +
    // 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();
+ +

Seuraavaksi tulee sitten ensimmäinen pala WebVR-koodia. Aluksi tarkistetaan, onko VR-näyttöjä edes käytettävissä {{domxref("Navigator.getVRDisplays")}}  — tästä alkaa API:n käyttö ja tämä on hyvä paikka WebVR:n ominaisuuksien tarkistamiseen. Koodilohkon lopussa (else -osassa) näkyy, että ellei sopivia näyttöjä ole, näytetään viesti, ettei selain tue WebVR 1.1 :ää.

+ +
    // WebVR: Check to see if WebVR is supported
+    if(navigator.getVRDisplays) {
+      console.log('WebVR 1.1 supported');
+ +

if() { ... } koodilohkossa suoritetaan {{domxref("Navigator.getVRDisplays()")}} metodi. Tämä palauttaa promise-olion, jonka sisältönä on lista tietokoneeseen kytketyistä VR-näytöistä. Se on tyhjä, ellei näyttöjä ole..

+ +
      // Then get the displays attached to the computer
+      navigator.getVRDisplays().then(function(displays) {
+ +

Promise-olion then() -lohkossa tarkistetaan, että listan pituus on suurempi kuin 0; näin ollessa asetetaan vrDisplay -muuttujamme arvoksi listan ensimmäisen -indeksistä 0 löytyvän - alkion arvo. vrDisplay sisältää nyt {{domxref("VRDisplay")}} olion, joka vastaa laitteeseen liitettyä näyttöä!

+ +
        // If a display is available, use it to present the scene
+        if(displays.length > 0) {
+          vrDisplay = displays[0];
+          console.log('Display found');
+ +
+

Huom: On epätavallista, että tietokoneeseen olisi kytketty useita VR-näyttöjä, joten tätä yksinkertaista demoa varten usean näytön vaihtoehtoa ei huomioida.

+
+ +

VR-esityksen käynnistys ja pysäytys

+ +

Nyt kun käytössä on {{domxref("VRDisplay")}} olio, sen avulla voidaan tehdä useita juttuja. Seuraavaksi haluamme käynnistää toiminnot WebGL-sisällön näyttämisen aloittamiseksi ja lopettamiseksi.

+ +

Jatkaaksemme edellisestä koodilohkosta, lisäämme käynnistys/pysäytys -painikkeeseemme (btn) tapahtumankuuntelijan (event listener) — ja painiketta klikattaessa halutaan tarkistaa, joko esitys näytölle on käynnissä (toteutus tälle on hieman kökkö ja perustuu painikkeen tekstin, textContent, tutkimiseen).

+ +

Ellei esitys näyttöön ole vielä käynnissä, käytetään {{domxref("VRDisplay.requestPresent()")}} -metodia pyytämään selainta käynnistämään esitys näytölle. Parametrinä metodille annetaan lista {{domxref("VRLayerInit")}} olioita, jotka vastaavat näytettäväksi haluttuja näyttötasoja.

+ +

Koska tällä hetkellä on mahdollista esittää vain yksi näyttötaso, ja ainoa vaadittu olion jäsen on {{domxref("VRLayerInit.source")}} -ominaisuus (joka viittaa tuossa näyttötasossa näytettäväksi tarkoitettuun {{htmlelement("canvas")}} :iin; annetaan muille parametreille järkevät oletusarvot — kts. {{domxref("VRLayerInit.leftBounds", "leftBounds")}} ja {{domxref("VRLayerInit.rightBounds", "rightBounds")}})), parametri on yksinkertaisesti [{ source: canvas }].

+ +

requestPresent() palauttaa promise-olion, joka saa sisällön, kun esittäminen käynnistyy onnistuneesti.

+ +
          // 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');
+ +

Nyt kun esittämispyyntö oli ok, halutaan seuraavaksi asettaa renderöintisisältö esitettäväksi VR-näytölle. Aivan ensimmäiseksi asetetaan canvas samankokoiseksi VR-näytön näyttöalueen kanssa. Tämä onnistuu hakemalla {{domxref("VREyeParameters")}} molemmille silmille käyttäen metodia {{domxref("VRDisplay.getEyeParameters()")}}.

+ +

Sen jälkeen lasketaan yksinkertaisesti VR-näytön kokonaisala silmän ominaisuuksien {{domxref("VREyeParameters.renderWidth")}} ja {{domxref("VREyeParameters.renderHeight")}} avulla.

+ +
                // 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);
+ +

Seuraavaksi pysäytetään renderöintisilmukka {{domxref("Window.cancelAnimationFrame()", "cancel the animation loop")}}, joka aiemmin käynnistyi {{domxref("Window.requestAnimationFrame()")}} kutsulla drawScene() -metodista ja sen sijaan kutsutaandrawVRScene():ä. Tämä metodi renderöi saman skenen kuin aiempikin käyttäen nyt VR-kohtaisia temppuja. Tämän renderöintisilmukan hallinta on nyt vastaavalla WebVR-versiolla, {{domxref("VRDisplay.requestAnimationFrame")}} -metodilla.

+ +
                // stop the normal presentation, and start the vr presentation
+                window.cancelAnimationFrame(normalSceneFrame);
+                drawVRScene();
+ +

Lopuksi päivitetään painikkeen teksti, jolloin seuraavalla klikkauskerralla painike tuleekin pysäyttämään esityksen VR-näytöllä.

+ +
                btn.textContent = 'Exit VR display';
+              });
+ +


+ VR-näytöllä esittämisen pysäyttämiseksi painikkeen seuraavalla klikkauksella kutsutaan {{domxref("VRDisplay.exitPresent()")}} -metodia. Painikkeen teksti vaihdetaan taas toiseksi ja requestAnimationFrame -kutsut vaihdetaan taas keskenään. Tästä näkyy, että käytetään metodia {{domxref("VRDisplay.cancelAnimationFrame")}} VR-renderöintisilmukan pysäyttämiseen ja normaalin skenen renderöinti käynnistyy drawScene()-metodilla.

+ +
            } 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.');
+    }
+  }
+}
+ +

Kun esittäminen käynnistyy, selaimessa näkyy stereoskooppinen näkymä:

+ +

+ +

Seuraavasta opitaan, miten stereonäkymä varsinaisesti tehdään.

+ +

Miksi WebVR:llä on oma requestAnimationFrame()?

+ +

Tämä on hyvä kysymys. Perussyy on sulava renderöinti VR-näytössä, joka saadaan aikaan käyttämällä VR-näytön omaa näytönpäivitysnopeutta eikä tietokoneen. VR-näytön päivitysnopeudet ovat tietokonetta suurempia, yleisesti jopa  90fps. Tämä poikkeaa tietokoneen peruspäivitysnopeudesta.

+ +

Huomaa, että kun VR-näytössä ei esitetä, {{domxref("VRDisplay.requestAnimationFrame")}} toimii identtisesti {{domxref("Window.requestAnimationFrame")}}:n kanssa, joten halutessasi voisit käyttää vain yhtä renderöintisilmukkaa tekemämme sovelluksen kahden silmukan sijaan. Sovelluksessa käytetään kahta, koska VR-esityksen ollessa päällä halutaan tehdä hieman eri asioita kuin ilman sitä, ja nämä halutaan selkeyden vuoksi erottaa.

+ +

Renderöinti ja näyttäminen

+ +

Tässä vaiheessa on nähty kaikki koodi, mikä tarvitaan VR-laitteiston hakemiseen, skenen näyttöpyynnön lähettämiseen ja renderöintisilmukan käynnistämiseen. Seuraavaksi kurkataan renderöintisilmukan sisälle ja selitetään, miten sen WebVR-spesifiset osat toimivat.

+ +

Aluksi tarkastellaan renderöintisilmukkametodin  — drawVRScene() määrittelyä. Ensimmäinen tehtävä on kutsua {{domxref("VRDisplay.requestAnimationFrame()")}} -metodia silmukan toiston jatkamiseksi ensimmäisen kutsukerran jälkeen (tämä tehtiin aiemmin koodissa, kun VR-näytölle esittäminen aloitettiin). Tämä metodikutsu asetetaan globaalin vrSceneFrame -muuttujan arvoksi, jotta silmukka saadaan keskeytettyä {{domxref("VRDisplay.cancelAnimationFrame()")}} -metodilla, kun VR-esitys loppuu.

+ +
function drawVRScene() {
+  // WebVR: Request the next frame of the animation
+  vrSceneFrame = vrDisplay.requestAnimationFrame(drawVRScene);
+ +

Seuraavaksi kutsutaan metodia {{domxref("VRDisplay.getFrameData()")}}, joka saa parametriksi muuttujanimen, johon ruudun tiedot halutaan. Tämähän alustettiin jo aiemmin nimellä  frameData. Metodin suorittamisen jälkeen tässä muuttujassa on tarpeelliset tiedot seuraavan ruudun renderöintiin VR -laitteelle pakattuna {{domxref("VRFrameData")}} -olioon. Mukana on tieto projektio- ja näkymämatriiseista, joiden avulla skene saadaan renderöityä oikein vasemmalle ja oikealle silmälle sekä ajantasainen {{domxref("VRPose")}} -olio, jossa on mm. VR-näytön suunta- ja sijaintitiedot.

+ +

Tätä tulee kutsua joka ruudun kohdalla, jotta renderöity näkymä olisi ajantasainen.

+ +
  // Populate frameData with the data of the next frame to display
+  vrDisplay.getFrameData(frameData);
+ +

Seuraavaksi haetaan senhetkinen {{domxref("VRPose")}} ominaisuudesta {{domxref("VRFrameData.pose")}}, tallennetaan sijainti ja suunta myöhempää käyttöä varten ja lähetetään pose-tieto näytettäväksi sivun tilatietoruutuun, siis mikäli poseStatsDisplayed -muuttuja on saanut arvon true.

+ +
  // 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);
+  }
+ +

  Seuraavaksi canvas:in sisältö tyhjennetään ennen uuden piirron aloittamista, jotta seuraava ruutu piirrettäisiin puhtaalle pohjalle, eikä aiempi ruutu olisi alla sotkemassa:

+ +
  // Clear the canvas before we start drawing on it.
+
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ +

Nyt renderöidään molempien silmien näkymä. Aluksi tarvitaan projektion ja näkymän sijainti renderöintiä varten. Nämä ovat {{domxref("WebGLUniformLocation")}} -olioita, jotka on luotu {{domxref("WebGLRenderingContext.getUniformLocation()")}} -metodilla käyttäen parametreinä shader-ohjelman tunnusta ja nimitunnistetta.

+ +
  // 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");
+ +

Seuraava renderöintivaihe sisältää:

+ + + +
  // 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();
+ +

Ja sama oikealle silmälle:

+ +
  // 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();
+ +

Seuraavaksi määritelläändrawGeometry() funktio. Suurin osa siitä koostuu tavallisesta WebGL -koodista, jolla saadaan piirrettyä 3D-kuutio. WebVR-spesifisiä osia löytyy mvTranslate() jamvRotate() funktiokutsuista — ne välittävät matriisit WebGL-ohjelmalle, joka määrittää sen hetkiselle ruudulle kuution sijainnin ja kierron.

+ +

Kuten huomaat, näitä arvoja muokataan {{domxref("VRPose")}} -oliolta saaduilla VR-näytön sijainti- (curPos) ja kiertotiedoilla (curOrient). Sen seurauksena esimerkiksi päätä vasemmalle käännettäessä kuvassa näkyvä kuutio siirtyy aivan odotetustikin oikealle, kun  x-sijaintitieto (curPos[0]) ja y-kiertotieto ([curOrient[1]) lisätään x-translaatioarvoon.

+ +

Tämä on 'quick and dirty' -tapa käyttää VR pose-tietoa, mutta se näyttänee kuitenkin perusidean.

+ +
  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();
+  }
+
+ +

Seuraava koodipalanen ei liity mitenkään WebVR:ään — siinä vain kierretään kuutiota joka ruudun osalta:

+ +
  // 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;
+ +

Renderöintisilmukan viimeiseen osaan kuuluu {{domxref("VRDisplay.submitFrame()")}} -metodin kutsuminen — kaikki tarpeellinen on nyt tehty ja näyttö on renderöity {{htmlelement("canvas")}} :iin, tämä metodi sitten toimittaa ruudun VR-näytölle, jolloin se ruutu näkyy myös siinä.

+ +
  // WebVR: Indicate that we are ready to present the rendered frame to the VR display
+  vrDisplay.submitFrame();
+}
+ +

Pose (sijainti, kierto, ym.) -tiedon näyttäminen

+ +

Tässä osassa tutustutaan displayPoseStats() -funktioon, joka näyttää kunkin ruudun päivitetyt pose-tiedot. Kyseinen funktio on melko yksinkertainen.

+ +

Aluksi tallennetaan {{domxref("VRPose")}}-oliolta saadut kuusi ominaisuutta omiin muuttujiin — ne ovat tyyppiä {{domxref("Float32Array")}}.

+ +
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;
+ +

Sitten tiedot kirjoitetaan tietolaatikkoon ja päivitetään ne joka ruudun kohdalla. Arvot on pyöristetty toFixed() -metodilla luettavuuden vuoksi.

+ +

Huomaa ehtolause lineaarisen ja kulmakiihtyvyyden vektorien arvojen tarkastamisessa - siinä varmistetaan ennen näyttämistä, että arvot on tosiaan saatu luettua. Useimmilta VR-laitteistolta näitä arvoja ei vielä saada, joten ilman tarkistamista seuraisi virhetoiminta (ellei arvoja saada, vektorien arvoksi tulee 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 -tapahtumat

+ +

The WebVR spesifikaatiossa on määritetty useita liipaistavia tapahtumia (event), ja näin koodilla voidaan reagoida VR-näytön tilan muutoksiin (vrt. Window events). Esimerkiksi:

+ + + +

Demossa on seuraava esimerkki tapahtumista:

+ +
window.addEventListener('vrdisplaypresentchange', function(e) {
+  console.log('Display ' + e.display.displayId + ' presentation has changed. Reason given: ' + e.reason + '.');
+});
+ +

Kuten näet {{domxref("VRDisplayEvent", "event object")}} tarjoaa kaksi hyödyllistä ominaisuutta — {{domxref("VRDisplayEvent.display")}}, joka viittaa {{domxref("VRDisplay")}} tapahtuman tuottajaan, ja {{domxref("VRDisplayEvent.reason")}}, jossa on selkokielinen syy tapahtumaan.

+ +

Tämä on hyvin käyttökelpoinen tapahtuma; sitä voidaan käyttää huomaan yllättävä näytön irrotus, joka estäää tarpeettomat virheviestit ja kertoo tilanteen käyttäjälle. Googlen Webvr.info -esitysdemossa tapahtumaa käytetään suorittamaan onVRPresentChange() funktio, joka päivittää käyttöliittymän kontrollit tilannetta vastaaviksi ja muuttaa canvasin kokoa.

+ +

Yhteenveto

+ +

Tässä artikkelissa kerrottiin hyvin yksinkertaisen WebVR 1.1 sovelluksen tekemisestä, jonka avulla pääset alkuun sovellusten kehittämisessä.

-- cgit v1.2.3-54-g00ecf