1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
|
---
title: WebVR APIの使い方
slug: Web/API/WebVR_API/Using_the_WebVR_API
translation_of: Web/API/WebVR_API/Using_the_WebVR_API
---
<p>{{draft("この WebVR API ドキュメントは現在v1.0の仕様への対応作業の途中です.従って、ここにある情報のいくつかは最新ではありません。この作業について質問がある場合は ~~chrisdavidmills へ連絡をとってください.")}}</p>
<p class="summary"><a href="/ja/docs/Web/API/WebVR_API">WebVR API</a> はウェブ開発者のツールキットへのすばらしい追加機能で、<a href="https://developer.oculus.com/">Oculus Rift</a> のようなバーチャルリアリティハードウェアへのアクセスが可能となります。そして出力された動きや向きはウェブアプリの描画更新に変換されます。しかし VR アプリを開発はどのようにやればいいのでしょうか? この記事では、それに関する基礎的な解説を行います。</p>
<div class="note">
<p><span style="font-size: 14px; line-height: 21px;"><strong>注記</strong></span>: WebVR は現在実験的な段階にあります(<a href="http://mozvr.github.io/webvr-spec/webvr.html">最新の仕様はこちら</a>にあります); 今の段階でもっとも正常に動作するのは Firefox Nightly/Developer Edition で、一部の機能は Google Chrome でも動作します。詳細は Brandon Jonesの <a class="external external-icon" href="http://blog.tojicode.com/2014/07/bringing-vr-to-chrome.html">Bringing VR to Chrome</a> を参照してください。</p>
</div>
<h2 id="始めるには">始めるには</h2>
<p>WebVRを始めるには,VRハードウェアのマニュアルに従ったセットアップと、<a href="/ja/docs/Web/API/WebVR_API/WebVR_environment_setup">WebVR environment setup</a> に示されているコンピュータへの設定が必要になります、スムースな動作には専用GPUが推奨されます。</p>
<p><a href="https://nightly.mozilla.org/">Firefox Nightly</a> (または <a href="https://www.mozilla.org/en-US/firefox/developer/">Developer Edition</a>) のインストールと合わせて <a href="http://www.mozvr.com/downloads/webvr-addon-0.1.0.xpi">WebVR Enabler Add-on</a> も必要となります。</p>
<p>いちど環境が設定できたら、テストのために私たちの <a href="http://mozvr.com/projects/">MozVR projects</a> を開いて、[Enter VR<strong>]</strong> ボタンをクリックすることを試してください。</p>
<div class="note">
<p><strong>注記</strong>: より深い情報のために,<a href="/ja/docs/Web/API/WebVR_API/WebVR_environment_setup">WebVR environment setup</a> をチェックしてください。</p>
</div>
<div class="note">
<p><strong>注記</strong>: モバイルデバイスを HMD として用いるような安価な選択肢もあります。この場合,位置センサは利用できませんので、代わりに <a href="/ja/Apps/Build/gather_and_modify_data/responding_to_device_orientation_changes">deviceorientation API</a> を用いて擬似的な向きデータを使う必要があるかもしれません。</p>
</div>
<h2 id="簡単なデモ">簡単なデモ</h2>
<p>WebVR のデモは <a href="https://github.com/MozVR/">MozVR team repo</a> や <a href="https://github.com/mdn/webvr-tests">MDN webvr-tests repo</a> にたくさんありますが、この記事では、主に<a href="https://github.com/mdn/webvr-tests/tree/gh-pages/positionsensorvrdevice">positionsensorvrdevice</a> について (<a href="http://mdn.github.io/webvr-tests/positionsensorvrdevice/">動作しているデモ</a>) を例に解説します。</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10797/vrpositionsensor-demo.png" style="display: block; height: 396px; margin: 0px auto; width: 800px;"></p>
<p>これは簡単な 2.5D のデモで,<a href="/ja/docs/Web/HTML/Element/canvas">HTML5 Canvas</a> にレンダリングされた Firefox ロゴが右目と左目のビューに表示されるものです.VR HMDでデモを見ているときにキャンバスをクリックすると、デモはフルスクリーンになり、Firefox ロゴに近づけるようになります。あなたが動くと頭の動きに合わせて上下左右や回転してリアルに動きます。</p>
<p>あなたが WebVR のコードがどう動いているかを簡単に確認できるように、デモは意図的にシンプルになるよう保持されています。API は十分シンプルであるため,単純な DOM ベースインターフェイスでも複雑な WebGL シーンでも、好きなアプリに WebVR 制御の移動を簡単に適用できます。</p>
<h2 id="アプリはどう動く">アプリはどう動く?</h2>
<p>このセクションでは、アプリを動作させるために必要なコードの変更箇所を通じて、基礎的なレベルで何が必要かを知ることができます。</p>
<h3 id="VRデバイスへのアクセス">VRデバイスへのアクセス</h3>
<p>最初にコンピュータに接続中のVRハードウェアへのプログラム的な参照を取得します。それには接続中の全 VR デバイスの配列へと解決できるプロミスを返す {{domxref("Navigator.getVRDevices")}} を使います。</p>
<p>返される可能性のあるオブジェクトが2種類あります:</p>
<ul>
<li>{{domxref("PositionSensorVRDevice")}}: 位置センサカメラ。</li>
<li>{{domxref("HMDVRDevice")}}: VRヘッドマウントディスプレイ。</li>
</ul>
<p> <a href="https://github.com/mdn/webvr-tests/tree/gh-pages/vrdevice">vrdevice demo</a> で基本的なデバイス情報を表示するための非常に簡単なコードを見ることができます。</p>
<p>本当に欲しいものはデバイスのペアを取得するものです (将来のマルチプレイヤVRゲームでは複数のペアになるかもですが)。WebVR 仕様からもってきた(そして <a href="https://github.com/mdn/webvr-tests/tree/gh-pages/positionsensorvrdevice">positionsensorvrdevice</a> デモでも使っている)次のコードはかなりよく使うトリックです:</p>
<pre class="brush: js">var gHMD, gPositionSensor;
navigator.getVRDevices().then(function(devices) {
for (var i = 0; i < devices.length; ++i) {
if (devices[i] instanceof HMDVRDevice) {
gHMD = devices[i];
break;
}
}
if (gHMD) {
for (var i = 0; i < devices.length; ++i) {
if (devices[i] instanceof PositionSensorVRDevice && devices[i].hardwareUnitId === gHMD.hardwareUnitId) {
gPositionSensor = devices[i];
break;
}
}
}
});</pre>
<p>最初に見つかった {{domxref("HMDVRDevice")}} のインスタンスを取得し、それを <code>gHMD</code> 変数へ保存します.次に見つかった {{domxref("PositionSensorVRDevice")}} のインスタンスを取得して <code>gPositionSensor</code> 変数に代入していますが,それは先ほど取得した <code>gHMD</code> オブジェクトの {{domxref("VRDevice.hardWareUnitId")}} プロパティが一致するものだけを対象にしています。同一のハードウェアは複数のデバイスとして取得されますが、それらはハードウェアユニットIDを共有しています — これは取得した 2 つのデバイスの参照がマッチングしているかをチェックする方法です。</p>
<h3 id="アプリの初期化">アプリの初期化</h3>
<p>シーンを描画する {{htmlelement("canvas")}} 要素を次のように作成し、配置します:</p>
<pre class="brush: js">var myCanvas = document.createElement('canvas');
var ctx = myCanvas.getContext('2d');
var body = document.querySelector('body');
body.appendChild(myCanvas);</pre>
<p>次に、新しい <a href="/ja/docs/Web/API/HTMLImageElement">image</a> を作成し、アプリの <a href="/ja/docs/Games/Anatomy#Building_a_main_loop_in_JavaScript">main loop</a> である<code>draw()を実行する前に </code>image が <code>ロードされているかをチェックするために</code> {{event("load")}} イベントを使います:</p>
<pre class="brush: js">var image = new Image();
image.src = 'firefox.png';
image.onload = draw;</pre>
<h3 id="メインループ">メインループ</h3>
<p><code>draw()</code> は次のように実装します:</p>
<pre class="brush: js">function draw() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
lCtrOffset = WIDTH*0.25;
rCtrOffset = WIDTH*0.25;
myCanvas.width = WIDTH;
myCanvas.height = HEIGHT;
setView();
drawImages();
drawCrosshairs();
requestAnimationFrame(draw);
}</pre>
<p><a href="/ja/docs/Web/API/Window">window</a> の <code>WIDTH</code> と <code>HEIGHT</code> は各フレームでリサンプリングされ,次の設定に使われます:</p>
<ul>
<li>左右の目のビュー中心からの相対的に描画される画像を維持するのに使われる左右のオフセット値です。半分の幅のシーンのコピーを描画するので、各コピーの中心はそれぞれ、エッジの端から端までのキャンバス全体幅のちょうど1/4の幅になります。</li>
<li>キャンバスの <a href="/ja/docs/Web/API/HTMLCanvasElement/width">width</a> と <a href="/ja/docs/Web/API/HTMLCanvasElement/height">height</a>。</li>
</ul>
<p>これによってブラウザウィンドウがリサイズされたとしても、シーンが正しくリサイズされます。</p>
<p>次にメインループの中で3つの関数を実行しています:</p>
<ul>
<li><code>setView()</code> は,VR ハードウェアから位置と向きの情報を受け取り,シーン内の更新された画像位置の描画に使用する準備をします。</li>
<li><code>drawImages()</code> はシーンを更新された位置で実際に描画します。</li>
<li><code>drawCrosshairs()</code> は常にシーンの中央にある十字線を描画します。</li>
</ul>
<p>これらの詳細は、後ほど解説します。</p>
<p>ループの最後に <a href="/ja/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame(draw)</a> を実行し<code>、draw()</code> ループが連続して呼び出されるようにします。</p>
<h3 id="位置と向き情報の受取り">位置と向き情報の受取り</h3>
<p>では <code>setView()</code> 関数の詳細を見ていきましょう。コードの各部分を順に追って、そこで何をしているかを説明します:</p>
<pre class="brush: js">function setView() {
var posState = gPositionSensor.getState();</pre>
<p>位置センサへの参照を使って {{domxref("PositionSensorVRDevice.getState")}} を呼び出します。このメソッドは、あなたが知りたい現在のHMDの状態のすべてを返します — {{domxref("VRPositionState")}} オブジェクトへのアクセスを通じて — 位置、向き、そして速度/ 加速度や角速度 / 角加速度のようなより高度な情報を含んでいます。</p>
<pre class="brush: js"> if(posState.hasPosition) {
posPara.textContent = 'Position: x' + roundToTwo(posState.position.x) + " y"
+ roundToTwo(posState.position.y) + " z"
+ roundToTwo(posState.position.z);
xPos = -posState.position.x * WIDTH * 2;
yPos = posState.position.y * HEIGHT * 2;
if(-posState.position.z > 0.01) {
zPos = -posState.position.z;
} else {
zPos = 0.01;
}
}</pre>
<p>HMDのスイッチがOFFにされたり位置センサを向いていなかったりした場合など、アプリがエラーになったり停止したりしないように、 {{domxref("VRPositionState.hasPosition")}} を使って HMD の正常な位置情報が利用可能かを確認する方法をチェックします。</p>
<p>そして通知を目的として、アプリのUI内のパラグラフへ現在の位置情報を出力します。読みやすくするために、カスタム関数を使って小数点以下 2 桁に丸めています。</p>
<p>最後に {{domxref("VRPositionState.position")}} に格納されている位置情報に関して、<code>xPos</code>、 <code>yPos</code>、<code>zPos</code> 変数に代入します。<code>zPos</code> の値を 0.01 以上にするのに <code>if ... else</code> ブロックが利用されていることに気付くでしょう — このアプリは0以下になると例外を投げていました。</p>
<pre class="brush: js"> if(posState.hasOrientation) {
orientPara.textContent = 'Orientation: x' + roundToTwo(posState.orientation.x) + " y"
+ roundToTwo(posState.orientation.y) + " z"
+ roundToTwo(posState.orientation.z);
xOrient = posState.orientation.x * WIDTH;
yOrient = -posState.orientation.y * HEIGHT * 2;
zOrient = posState.orientation.z * 180;
}</pre>
<p>次に同じような処理をして、HMDの向きに応じてシーンの更新処理をします — {{domxref("VRPositionState.hasOrientation")}} を使って有効な向きデータかをチェックして,向きのデータを通知用のUIに表示し、<code>xOrient</code>、<code>yOrient</code>、<code>zOrient</code> の値を {{domxref("VRPositionState.orientation")}} に格納されている値から設定します.</p>
<pre> timePara.textContent = 'Timestamp: ' + Math.floor(posState.timeStamp);
}</pre>
<p>最後に {{domxref("VRPositionState.timeStamp")}} に格納されている現在のタイムスタンプを通知 UI に出力します。この値は位置データが更新済みか、どんな順序で更新が発生したかを判断するのに役立ちます。</p>
<h3 id="シーンの更新">シーンの更新</h3>
<p><code>setView()</code> で取得された <code>xPos</code>、<code>yPos</code>、<code>zPos</code>、<code>xOrient</code>、<code>yOrient</code>、<code>zOrient</code> の値は、<code>drawImages() </code>で行われるシーン病がの更新のための変更値として使用されます。どうやっているかを見ていきますが、左目のビューの描画コードだけをウォークスルーしていきます。右目については、右にオーバーシフトしている以外はほぼ同じです:</p>
<pre class="brush: js">function drawImages() {
ctx.fillStyle = 'white';
ctx.fillRect(0,0,WIDTH,HEIGHT);</pre>
<p>最初に次のフレームが描画される前にシーンをクリアするため、白い {{domxref("CanvasRenderingContext2D.fillRect","fillRect()")}} を描画します。</p>
<pre class="brush: js"> ctx.save();
ctx.beginPath();
ctx.translate(WIDTH/4,HEIGHT/2);
ctx.rect(-(WIDTH/4),-(HEIGHT/2),WIDTH/2,HEIGHT);</pre>
<p>次に左目のビューを別の画像として扱って右目のビューに影響を与えないコードにするので、 {{domxref("CanvasRenderingContext2D.save","save()")}} でコンテキスト状態を保存します。</p>
<p>そして {{domxref("CanvasRenderingContext2D.beginPath","pathを開始し")}}, {{domxref("CanvasRenderingContext2D.translate","canvasを変換します")}}、これによって原点を左目の中心(全体の1/4幅で半分の高さ)に移動させます。回転を正しく動かすためにもこれは必要です。回転はcanvasの原点が中心となります。そして左目のビュー全体を覆うように {{domxref("CanvasRenderingContext2D.rect","rect()")}} を描画します。</p>
<p><code>rect()</code> はマイナスの 1/4 幅,マイナスの1/2 高さから描画し始めていることに注意してください。これは原点が既に移動しているためです。</p>
<pre> ctx.clip();</pre>
<p>canvas を {{domxref("CanvasRenderingContext2D.clip","clip()")}} します。<code>rect()</code> が描画された直後にこれを呼ぶので、キャンバス上に対して行うことは <code>rect() の内側に制限され</code>、<code>restore()</code> が呼び出されるまですべてのオーバーフローは隠蔽されます(後述)。これは左ビュー全体が右ビューから独立したままであることを保証します。</p>
<pre class="brush: js"> ctx.rotate(zOrient * Math.PI / 180);</pre>
<p>頭の回転と同じようにシーンを回転させるために、zOrientの値に従った回転が画像に適用します。</p>
<pre class="brush: js"> ctx.drawImage(image,-(WIDTH/4)+lCtrOffset-((image.width)/(2*(1/zPos)))+xPos-yOrient,-((image.height)/(2*(1/zPos)))+yPos+xOrient,image.width*zPos,image.height*zPos);</pre>
<p>実際に画像を描画しましょう! この少し厄介なコードを、ここでは引数ごとに分解してみましょう:</p>
<ul>
<li><code>image</code>: 描画する画像</li>
<li>
<p><code>-(WIDTH/4)+lCtrOffset-((image.width)/(2*(1/zPos)))+xPos-yOrient</code>: 画像原点の水平座標。前に行った平行移動を打ち消すために <code>WIDTH/4</code> を引きます.そして中心に戻すために左中心オフセットを加えて,画像幅を <code>zPos</code> の逆数の2倍で割ったものを引きます— 描画する画像が小さい(大きい)ほど減算値が小さい(大きい)くなり,画像中心が保持されます.最後に,HMD の水平方向の動きや回転にあわせて画像位置を更新するために <code>xPos</code> を加えて,<code>yOrient</code> を引きます(y軸周りの回転が画像を水平方向に移動します)。</p>
</li>
<li><code>-((image.height)/(2*(1/zPos)))+yPos+xOrient</code>: 画像原点の垂直方向の座標です。これはIn this case the "HEIGHT/2の減算"と"右中心オフセットの追加"は、ちょうどお互いにキャンセルされるので、計算式から取り除きます。計算式の残りは上と同じように、zPos の逆数の 2 倍で画像幅を割ったものを減算することによる画像中心を保持と、<code>yPos</code> と <code>xOrient </code>による描画位置の修正です。</li>
<li><code>image.width*zPos</code>: 画像を描画する幅; 近いものほど大きく描画されるように <code>zPos</code> で修正します。</li>
<li><code>image.height*zPos</code>: 画像を描画する高さ; 近いものほど大きく描画されるように <code>zPos</code> で修正します。</li>
</ul>
<pre class="brush: js"> ctx.strokeStyle = "black";
ctx.stroke();</pre>
<p>左目ビューの周囲に黒い {{domxref("CanvasRenderingContext2D.stroke","stroke()")}} を描画します。これはビューの分離をちょっとだけわかりやすくする手助けとなります。</p>
<pre class="brush: js"> ctx.restore();</pre>
<p>右目ビューの描画の実施に移行するため、キャンバスの復元を {{domxref("CanvasRenderingContext2D.restore","restore()")}} で行います。</p>
<pre class="brush: js"> ...
}</pre>
<div class="note">
<p><span style="font-size: 14px; line-height: 21px;"><strong>注記</strong></span>: ここである種のチートをしていて,2D キャンバスを使って3Dシーンを擬似的に表現しています。学習目的の場合、物事を簡単にすることができます。WEBテクノロジで作成された任意のアプリで、ビューレンダリングを修正するために上述した位置と向きのデータを使うことができます。例えば <a href="https://github.com/mdn/webvr-tests/tree/gh-pages/3Dpositionorientation">3Dpositionorientation</a> デモでは、<a href="http://threejs.org/">Three.js</a> を使って作成されたWebGLシーンのビューを制御するために上述の方法と非常によく似たコードを使っています。</p>
</div>
<div class="note">
<p><span style="font-size: 14px; line-height: 21px;"><strong>注記</strong></span>: <a href="https://github.com/mdn/webvr-tests/blob/gh-pages/positionsensorvrdevice/index.html#L106-L119"><code>drawCrosshairs() のコード</code></a> は <code>drawImages()と比較して</code>非常にシンプルですので、もし興味があるなら自分自身で勉強することをおすすめします!</p>
</div>
<h3 id="フルスクリーン表示">フルスクリーン表示</h3>
<p>VRエフェクトはアプリを <a href="/ja/docs/Web/Guide/API/DOM/Using_full_screen_mode">フルスクリーンモード</a> で実行すると非常に効果的です。ディスプレイのダブルクリックやボタンの押下のような、特定のイベントが発生した時に {{htmlelement("canvas")}} 要素をフルスクリーンにするための一般的な設定を説明します。</p>
<p>シンプルさを保つために、ここではキャンバスのクリック時に <code>fullScreen()</code> 関数を実行します:</p>
<pre class="brush: js">myCanvas.addEventListener('click',fullScreen,false);</pre>
<p><code>fullScreen()</code> 関数は、できるだけ互換性を保つために、ブラウザによって異なるキャンバスに実装されている <code>requestFullscreen()</code> メソッドのバージョンをチェックして、見つかった適切な関数を呼び出します:</p>
<pre class="brush: js">function fullScreen() {
if (myCanvas.requestFullscreen) {
myCanvas.requestFullscreen();
} else if (myCanvas.msRequestFullscreen) {
myCanvas.msRequestFullscreen();
} else if (myCanvas.mozRequestFullScreen) {
myCanvas.mozRequestFullScreen();
} else if (myCanvas.webkitRequestFullscreen) {
myCanvas.webkitRequestFullscreen();
}
}</pre>
<h2 id="FOV_とデバイスのキャリブレーション">FOV とデバイスのキャリブレーション</h2>
<p>現在のデモではあまり考えませんでしたが,商用アプリでは,ユーザが持っているVRハードウェアを正しく動作させるためにユーザキャリブレーションをする必要があるでしょう.WebVR API はそれを手助けする多くの機能があります。</p>
<p>HMDの位置と姿勢をリセットするために {{domxref("PositionSensorVRDevice.resetSensor")}} メソッドを利用できます。実行すると、現在のヘッドセットの位置/向きが 0 にセットされます。実行前に,ヘッドセットが検知可能な位置にあることを保証する必要があります。positionsensorvrdevice demo*** では、[Reset Sensor] ボタンでそれを実行することができます:</p>
<pre class="brush: html"><button>Reset Sensor</button></pre>
<pre class="brush: js">document.querySelector('button').onclick = function() {
gPositionSensor.resetSensor();
}</pre>
<p>他にもヘッドセットの視野角 (FOV) を、シーン内で上,右,下,左方向に見える範囲がどの程度かキャリブレーションします。それぞれの目のパラメータを別々に返す {{domxref("HMDVRDevice.getEyeParameters")}} メソッドを呼ぶと、両目それぞれの情報を個別に受け取ることができます。なお左目用パラメータで 1 回、右目用で 1 回の計 2 回の呼出しが必要です。それぞれの目用に {{domxref("VREyeParameters")}} オブジェクトを返します。</p>
<p>一例として、 {{domxref("VREyeParameters.currentFieldOfView")}} を用いて片目分の現在のFOV を受け取れます。これは次の 4 つのプロパティを持つ {{domxref("VRFieldOfView")}} オブジェクトを返します:</p>
<ul>
<li>{{domxref("VRFieldOfViewReadOnly.upDegrees","upDegrees")}}: FOVの上方向へ広がる角度の値.</li>
<li>{{domxref("VRFieldOfViewReadOnly.rightDegrees","rightDegrees")}}: FOVの右方向へ広がる角度の値.</li>
<li>{{domxref("VRFieldOfViewReadOnly.downDegrees","downDegrees")}}: FOVの下方向へ広がる角度の値.</li>
<li>{{domxref("VRFieldOfViewReadOnly.leftDegrees","leftDegrees")}}: FOVの左方向へ広がる角度の値.</li>
</ul>
<p>FOVは眼を頂点としたピラミッド形になっています.</p>
<p>あなたのアプリに適切なFOVをユーザが持っているかをチェックし,もしそうでないなら {{domxref("HMDVRDevice.setFieldOfView")}} メソッドを使って新しいFOVを設定します.これを扱う簡単な関数は次のような感じです:</p>
<pre class="brush: js">function setCustomFOV(up,right,down,left) {
var testFOV = new VRFieldOfView(up,right,down,left);
gHMD.setFieldOfView(testFOV,testFOV,0.01,10000.0);
}</pre>
<p>この関数は引数として4つの角度を受け取り、VRFieldOfView() コンストラクタを用いて新しい {{domxref("VRFieldOfView")}} オブジェクトを作成します。これを <code>setFieldOfView()</code> の最初の2つの引数(左目と右目のFOV)として渡します。第 3、4 引数は,FOV のオブジェクト可視領域を定義する眼からの最短、最大距離を示す <code>zNear</code> と <code>zFar</code> です.</p>
|