-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.bs
748 lines (562 loc) · 38.4 KB
/
index.bs
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
<pre class="metadata">
Shortname: webvr
Title: WebVR
Group: webvr
Status: ED
ED: https://w3c.github.io/webvr/
Repository: w3c/webvr
Level: 1
Mailing List Archives: https://lists.w3.org/Archives/Public/public-webvr/
Mailing List: [email protected]
!Participate: <a href="https://github.com/w3c/webvr/issues/new">File an issue</a> (<a href="https://github.com/w3c/webvr/issues">open issues</a>)
!Participate: <a href="https://lists.w3.org/Archives/Public/public-webvr/">Mailing list archive</a>
!Participate: <a href="irc://irc.w3.org:6665/">W3C's #webvr IRC</a>
!Archive: <a href="archive/">Previous spec versions</a>
Editor: Vladimir Vukicevic, Mozilla https://mozilla.org/, [email protected]
Editor: Brandon Jones, Google http://google.com/, [email protected]
Editor: Kearwood Gilbert, Mozilla https://mozilla.org/, [email protected]
Editor: Chris Van Wiemeersch, Mozilla https://mozilla.org/, [email protected]
Abstract: This specification describes support for accessing virtual reality (VR) devices, including sensors and head-mounted displays on the Web.
</pre>
<pre class="anchors">
urlPrefix: http://www.w3.org/TR/hr-time/
type: typedef; text: DOMHighResTimeStamp
type: dfn; text: timestamp origin
urlPrefix: https://wiki.whatwg.org/wiki/OffscreenCanvas
type: typedef; text: OffscreenCanvas
type: dfn; text: offscreen canvas
urlPrefix: https://www.w3.org/TR/gamepad/
type: interface; text: Gamepad
urlPrefix: https://www.w3.org/TR/html51/webappapis.html
type: dfn; text: window.requestAnimationFrame
urlPrefix: https://www.w3.org/TR/html5/
type: interface; text: Document
</pre>
# Introduction # {#intro}
Hardware that enables Virtual Reality applications requires high-precision, low-latency interfaces to deliver an acceptable experience.
Other interfaces, such as device orientation events, can be repurposed to surface VR input but doing so dilutes the interface's original
intent and often does not provide the precision necessary for high-quality VR. The WebVR API provides purpose-built interfaces
to VR hardware to allow developers to build compelling, comfortable VR experiences.
# DOM Interfaces # {#interfaces}
This section describes the interfaces and functionality added to the DOM to support runtime access to the functionality described above.
## VRDisplay ## {#interface-vrdisplay}
The {{VRDisplay}} interface forms the base of all VR devices supported by this API. It includes generic information such as device IDs and descriptions.
<pre class="idl">
interface VRDisplay : EventTarget {
readonly attribute boolean isConnected;
readonly attribute boolean isPresenting;
/**
* Dictionary of capabilities describing the VRDisplay.
*/
[SameObject] readonly attribute VRDisplayCapabilities capabilities;
/**
* If this VRDisplay supports room-scale experiences, the optional
* stage attribute contains details on the room-scale parameters.
* The stageParameters attribute can not change between null
* and non-null once the VRDisplay is enumerated; however,
* the values within VRStageParameters may change after
* any call to VRDisplay.submitFrame as the user may re-configure
* their environment at any time.
*/
readonly attribute VRStageParameters? stageParameters;
/**
* Return the current VREyeParameters for the given eye.
*/
VREyeParameters getEyeParameters(VREye whichEye);
/**
* An identifier for this distinct VRDisplay. Used as an
* association point in the Gamepad API.
*/
readonly attribute unsigned long displayId;
/**
* A display name, a user-readable name identifying it.
*/
readonly attribute DOMString displayName;
/**
* Populates the passed VRFrameData with the information required to render
* the current frame.
*/
boolean getFrameData(VRFrameData frameData);
/**
* Return a VRPose containing the future predicted pose of the VRDisplay
* when the current frame will be presented. The value returned will not
* change until JavaScript has returned control to the browser.
*
* The VRPose will contain the position, orientation, velocity,
* and acceleration of each of these properties.
*/
[NewObject] VRPose getPose();
/**
* Reset the pose for this display, treating its current position and
* orientation as the "origin/zero" values. VRPose.position,
* VRPose.orientation, and VRStageParameters.sittingToStandingTransform may be
* updated when calling resetPose(). This should be called in only
* sitting-space experiences.
*/
void resetPose();
/**
* z-depth defining the near plane of the eye view frustum
* enables mapping of values in the render target depth
* attachment to scene coordinates. Initially set to 0.01.
*/
attribute double depthNear;
/**
* z-depth defining the far plane of the eye view frustum
* enables mapping of values in the render target depth
* attachment to scene coordinates. Initially set to 10000.0.
*/
attribute double depthFar;
/**
* The callback passed to `requestAnimationFrame` will be called
* any time a new frame should be rendered. When the VRDisplay is
* presenting the callback will be called at the native refresh
* rate of the HMD. When not presenting this function acts
* identically to how window.requestAnimationFrame acts. Content should
* make no assumptions of frame rate or vsync behavior as the HMD runs
* asynchronously from other displays and at differing refresh rates.
*/
unsigned long requestAnimationFrame(FrameRequestCallback callback);
/**
* Passing the value returned by `requestAnimationFrame` to
* `cancelAnimationFrame` will unregister the callback.
*/
void cancelAnimationFrame(unsigned long handle);
/**
* Begin presenting to the VRDisplay. Must be called in response to a user gesture.
* Repeat calls while already presenting will update the VRLayers being displayed.
* If the number of values in the leftBounds/rightBounds arrays is not 0 or 4 for any of the passed layers the promise is rejected
* If the source of any of the layers is not present (null), the promise is rejected.
*/
Promise<void> requestPresent(sequence<VRLayerInit> layers);
/**
* Stops presenting to the VRDisplay.
*/
Promise<void> exitPresent();
/**
* Get the layers currently being presented.
*/
sequence<VRLayer> getLayers();
/**
* The VRLayer provided to the VRDisplay will be captured and presented
* in the HMD. Calling this function has the same effect on the source
* canvas as any other operation that uses its source image, and canvases
* created without preserveDrawingBuffer set to true will be cleared.
*/
void submitFrame();
};
</pre>
### Attributes ### {#vrdisplay-attributes}
<dfn attribute for="VRDisplay">isConnected</dfn>
The {{isConnected}} attribute MUST return the {{VRDisplay}}'s connected state.
<dfn attribute for="VRDisplay">isPresenting</dfn>
The {{isPresenting}} attribute MUST return the {{VRDisplay}}'s presentation state.
<dfn attribute for="VRDisplay">capabilities</dfn>
The {{capabilities}} attribute MUST return the {{VRDisplay}}'s {{VRDisplayCapabilities}} object, a dictionary of capabilities describing the {{VRDisplay}}.
<dfn method for="VRDisplay">getEyeParameters()</dfn>
Returns the current {{VREyeParameters}} for the given eye. The eye parameters MAY change at any time due to external factors, such as the user changing the IPD with hardware controls.
<dfn method for="VRDisplay">getFrameData()</dfn>
Populates the provided {{VRFrameData}} object with the {{VRPose}} and view and projection matricies for the current frame. These values describe the position, orientation, acceleration, and velocity of the {{VRDisplay}} that should be used when rendering the next frame of a scene. The User Agent MAY optionally use predictive techniques to estimate what these values will be at the time that the next frame will be displayed to the user. Subsequent calls to {{getFrameData()}} MUST provide the same values until the next call to {{submitFrame()}}. Returns true if the the provided {{VRFrameData}} object was successfully updated, false otherwise.
<dfn method for="VRDisplay">getPose()</dfn>
<i>(Deprecated)</i> Returns a {{VRPose}} describing the position, orientation, acceleration, and velocity of the {{VRDisplay}} that should be used when rendering the next frame of a scene. The User Agent MAY optionally use predictive techniques to estimate what the pose will be at the time that the next frame will be displayed to the user. Subsequent calls to {{getPose()}} MUST return a {{VRPose}} with the same values until the next call to {{submitFrame()}}.
This function is deprecated but is preserved for backwards compatibility. Using it MAY incur warnings from the User Agent. Prefer using {{getFrameData()}}, which also provides a {{VRPose}}, instead.
<dfn method for="VRDisplay">resetPose()</dfn>
Reset the pose for the {{VRDisplay}}, treating its current position and orientation as the "origin/zero" values. Future values returned from {{getFrameData()}} or {{getPose()}} will describe positions relative to the {{VRDisplay}}'s position when {{resetPose()}} was last called and will treat the display's yaw when {{resetPose()}} was last called as the forward orientation. The {{VRDisplay}}'s reported roll and pitch do not change when {{resetPose()}} is called as they are relative to gravity. Calling {{resetPose()}} may change the {{sittingToStandingTransform}} matrix of the {{VRStageParameters}}.
<dfn method for="VRDisplay">requestAnimationFrame()</dfn>
Functionally equivalent to <a href="https://www.w3.org/TR/html51/webappapis.html#animation-frames">window.requestAnimationFrame</a> when the {{VRDisplay}} is not presenting. When the {{VRDisplay}} is presenting the callback is called at the native refresh rate of the {{VRDisplay}}.
<dfn method for="VRDisplay">cancelAnimationFrame()</dfn>
Passing the value returned by {{requestAnimationFrame()}} to will unregister the callback.
<dfn method for="VRDisplay">requestPresent()</dfn>
Begins presenting the contents of the specified {{VRLayer}}s, described by {{VRLayerInit}} dictionaries, on the {{VRDisplay}} and fulfills the returned promise when presentation has begun. If {{canPresent}} is false the promise MUST be rejected. If the array contains more than {{maxLayers}} elements the promise MUST be rejected. If {{requestPresent()}} is called outside of a user gesture the promise MUST be rejected. The user agent MAY reject the promise for any other reason. If the {{VRDisplay}} is already presenting when {{requestPresent()}} is called the {{VRDisplay}} SHOULD update the {{VRLayer}} list being presented. If a call to {{requestPresent()}} is rejected while the {{VRDisplay}} is already presenting the {{VRDisplay}} MUST end presentation.
<dfn method for="VRDisplay">exitPresent()</dfn>
Ends presentation to the {{VRDisplay}} and fulfills the returned promise when fully exited. If the {{VRDisplay}} is not presenting the promise MUST be rejected.
<dfn method for="VRDisplay">getLayers()</dfn>
Returns an array with the {{VRLayer}} currently being presented. MUST return an empty array if the {{VRDisplay}} is not currently presenting. If the {{VRDisplay}} is presenting MUST return an array containing the {{VRLayer}}s last passed to {{requestPresent()}}.
<dfn method for="VRDisplay">submitFrame()</dfn>
Captures the current state of the {{VRLayer}} currently being presented and displays it on the {{VRDisplay}}. It is assumed that the frame was rendered using the {{VRPose}} and matrices provided by the last call to {{getFrameData()}}. If {{getFrameData()}} was not called prior to calling {{submitFrame()}} the user agent MAY warn the user of potentially malformed visuals or prevent the frame from being shown at all.
<div class="example">
The following code demonstrates presenting a simple rendering loop to a {{VRDisplay}}.
<pre class="lang-js">
var frameData = new VRFrameData();
// Render a single frame of VR data.
function onVRFrame() {
// Schedule the next frame's callback
vrDisplay.requestAnimationFrame(onVRFrame);
// Poll the VRDisplay for the current frame's matrices and pose
vrDisplay.getFrameData(frameData);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Render to 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();
// Render to 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();
// Indicate that we are ready to present the rendered frame to the VRDisplay
vrDisplay.submitFrame();
}
// Begin presentation (must be called within a user gesture)
vrDisplay.requestPresent([{ source: canvas }]).then(function() {
vrDisplay.requestAnimationFrame(onVRFrame);
});
</pre>
</div>
## VRLayer ## {#interface-vrlayer}
The {{VRLayer}} interface is provided to a {{VRDisplay}} and presented in the HMD.
<pre class="idl" id="vrlayer-dictionary">
typedef (HTMLCanvasElement or
OffscreenCanvas) VRSource;
[Constructor(optional VRLayerInit layer)]
interface VRLayer {
readonly attribute VRSource? source;
readonly attribute sequence<float> leftBounds;
readonly attribute sequence<float> rightBounds;
};
dictionary VRLayerInit {
VRSource? source = null;
sequence<float> leftBounds = [ ];
sequence<float> rightBounds = [ ];
};
</pre>
### Attributes ### {#vrlayer-attributes}
<dfn attribute for="VRLayer">source</dfn>
The {{VRLayer/source}} attribute defines the canvas whose contents will be presented by the {{VRDisplay}} when {{VRDisplay}}.{{submitFrame()}} is called. Upon being passed into {{requestPresent()}} the current backbuffer of the source's context MAY be lost, even if the context was created with the <code>preserveDrawingBuffer</code> context creation attribute set to <code>true</code>.
<dfn attribute for="VRLayer">leftBounds</dfn>
The {{VRLayer/leftBounds}} attribute contains four values defining the texture bounds within the {{VRLayer/source}} canvas to present to the eye in UV space: <code>[0]</code> left offset of the bounds (0.0 - 1.0); <code>[1]</code> top offset of the bounds (0.0 - 1.0); <code>[2]</code> width of the bounds (0.0 - 1.0); <code>[3]</code> height of the bounds (0.0 - 1.0). The {{VRLayer/leftBounds}} MUST default to <code>[0.0, 0.0, 0.5, 1.0]</code>.
<dfn attribute for="VRLayer">rightBounds</dfn>
The {{VRLayer/rightBounds}} attribute contains four values defining the texture bounds rectangle within the {{VRLayer/source}} canvas to present to the eye in UV space: <code>[0]</code> left offset of the bounds (0.0 - 1.0); <code>[1]</code> top offset of the bounds (0.0 - 1.0); <code>[2]</code> width of the bounds (0.0 - 1.0); <code>[3]</code> height of the bounds (0.0 - 1.0). The {{VRLayer/rightBounds}} MUST default to <code>[0.5, 0.0, 0.5, 1.0]</code>.
## VRDisplayCapabilities ## {#interface-vrdisplaycapabilities}
The {{VRDisplayCapabilities}} interface describes the capabilities of a {{VRDisplay}}. These are expected to be static per-device/per-user.
<pre class="idl">
interface VRDisplayCapabilities {
readonly attribute boolean hasPosition;
readonly attribute boolean hasOrientation;
readonly attribute boolean hasExternalDisplay;
readonly attribute boolean canPresent;
readonly attribute unsigned long maxLayers;
};
</pre>
### Attributes ### {#vrdisplaycapabilities-attributes}
<dfn attribute for="VRDisplayCapabilities">hasPosition</dfn>
The {{hasPosition}} attribute MUST return whether the {{VRDisplay}} is capable of tracking its position.
<dfn attribute for="VRDisplayCapabilities">hasOrientation</dfn>
The {{hasOrientation}} attribute MUST return whether the {{VRDisplay}} is capable of tracking its orientation.
<dfn attribute for="VRDisplayCapabilities">hasExternalDisplay</dfn>
The {{hasExternalDisplay}} attribute MUST return whether the {{VRDisplay}} is separate from the device's primary display. If presenting VR content will obscure other content on the device, this should be false. When false, the application should not attempt to mirror VR content or update non-VR UI because that content will not be visible.
<dfn attribute for="VRDisplayCapabilities">canPresent</dfn>
The {{canPresent}} attribute MUST return whether the {{VRDisplay}} is capable of presenting content to an HMD or similar device. Can be used to indicate "magic window" devices that are capable of 6DoF tracking but for which {{VRDisplay}}.{{requestPresent()}} is not meaningful. If false then calls to {{VRDisplay}}.{{requestPresent()}} should always fail, and {{VRDisplay}}.{{getEyeParameters()}} should return null.
<dfn attribute for="VRDisplayCapabilities">maxLayers</dfn>
Indicates the maximum length of the array that {{requestPresent()}} will accept. MUST be 1 if {{canPresent}} is true, 0 otherwise.
Note: Future revisions of this spec may allow multiple layers to enable more complex rendering effects such as compositing WebGL and DOM elements together. That functionality is not allowed by this revision of the spec.
## VREye ## {#interface-vreye}
<pre class="idl">
enum VREye {
"left",
"right"
};
</pre>
## VRFieldOfView ## {#interface-vrfieldofview}
<i>(Deprecated)</i> The {{VRFieldOfView}} interface represents a field of view, as given by 4 degrees describing the view from a center point.
<pre class="idl">
interface VRFieldOfView {
readonly attribute double upDegrees;
readonly attribute double rightDegrees;
readonly attribute double downDegrees;
readonly attribute double leftDegrees;
};
</pre>
## VRPose ## {#interface-vrpose}
The VRPose interface represents a sensor's state at a given timestamp.
<pre class="idl">
interface VRPose {
readonly attribute Float32Array? position;
readonly attribute Float32Array? linearVelocity;
readonly attribute Float32Array? linearAcceleration;
readonly attribute Float32Array? orientation;
readonly attribute Float32Array? angularVelocity;
readonly attribute Float32Array? angularAcceleration;
};
</pre>
### Attributes ### {#vrpose-attributes}
<dfn attribute for="VRPose">position</dfn>
Position of the {{VRDisplay}} as a 3D vector. Position is given in meters from
an origin point, which is either the position the sensor was first read at or
the position of the sensor at the point that {{resetPose()}} was last called.
The coordinate system uses these axis definitions:
* Positive X is to the user's right.
* Positive Y is up.
* Positive Z is behind the user.
All positions are given relative to the identity orientation in sitting space.
MAY be null if the sensor is incapable of providing positional data. User agents
MAY provide emulated position values through techniques such as neck modeling,
but when doing so SHOULD report {{VRDisplayCapabilities}}.{{hasPosition}} as
false. When not null MUST be a three-element array.
<dfn attribute for="VRPose">linearVelocity</dfn>
Linear velocity of the sensor given in meters per second. MAY be null if the
sensor is incapable of providing linear velocity. When not null MUST be a
three-element array.
<dfn attribute for="VRPose">linearAcceleration</dfn>
Linear acceleration of the sensor given in meters per second squared. MAY be
null if the sensor is incapable of providing linear acceleration. When not null
MUST be a three-element array.
<dfn attribute for="VRPose">orientation</dfn>
Orientation of the sensor as a quaternion. The orientation yaw (rotation around
the Y axis) is relative to the initial yaw of the sensor when it was first read
or the yaw of the sensor at the point that {{resetPose()}} was last called. An
orientation of [0, 0, 0, 1] is considered to be "forward". MAY be null if the
sensor is incapable of providing orientation data. When not null MUST be a
four-element array.
<dfn attribute for="VRPose">angularVelocity</dfn>
Angular velocity of the sensor given in radians per second. MAY be null if the
sensor is incapable of providing angular velocity. When not null MUST be a
three-element array.
<dfn attribute for="VRPose">angularAcceleration</dfn>
Angular acceleration of the sensor given in radians per second squared. MAY be
null if the sensor is incapable of providing angular acceleration. When not null
MUST be a three-element array.
<div class="example">
The following code snippet creates a WebGL-compatible matrix from a
{{VRPose}}:
<pre class="lang-js">
function poseToMatrix (pose) {
var out = new Float32Array(16);
// If the orientation or position are null, provide defaults.
var q = pose.orientation ? pose.orientation : [0, 0, 0, 1];
var v = pose.position ? pose.position : [0, 0, 0];
// Compute some values for the quaternion math.
var x2 = q[0] + q[0];
var y2 = q[1] + q[1];
var z2 = q[2] + q[2];
var xx = q[0] * x2;
var xy = q[0] * y2;
var xz = q[0] * z2;
var yy = q[1] * y2;
var yz = q[1] * z2;
var zz = q[2] * z2;
var wx = q[3] * x2;
var wy = q[3] * y2;
var wz = q[3] * z2;
out[0] = 1 - (yy + zz);
out[1] = xy + wz;
out[2] = xz - wy;
out[3] = 0;
out[4] = xy - wz;
out[5] = 1 - (xx + zz);
out[6] = yz + wx;
out[7] = 0;
out[8] = xz + wy;
out[9] = yz - wx;
out[10] = 1 - (xx + yy);
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
</pre>
</div>
## VRFrameData ## {#interface-vrframedata}
The VRFrameData interface represents all the information needed to render a single frame of a VR scene.
<pre class="idl">
[Constructor]
interface VRFrameData {
readonly attribute DOMHighResTimeStamp timestamp;
readonly attribute Float32Array leftProjectionMatrix;
readonly attribute Float32Array leftViewMatrix;
readonly attribute Float32Array rightProjectionMatrix;
readonly attribute Float32Array rightViewMatrix;
readonly attribute VRPose pose;
};
</pre>
### Attributes ### {#vrframedata-attributes}
<dfn attribute for="VRFrameData">timestamp</dfn>
Monotonically increasing value that allows the author to determine if position
state data been updated from the hardware. Since values are monotonically
increasing, they can be compared to determine the ordering of updates, as newer
values will always be greater than or equal to older values. The timestamp
starts at 0 the first time {{getFrameData()}} is invoked for a given
{{VRDisplay}}.
<dfn attribute for="VRFrameData">leftProjectionMatrix</dfn>
A 4x4 matrix describing the projection to be used for the left eye's rendering, given as a 16 element array in column major order. This value may be passed directly to WebGL's uniformMatrix4fv function. It is highly recommended that applications use this matrix without modification. Failure to use this projection matrix when rendering may cause the presented frame to be distorted or badly aligned, resulting in varying degrees of user discomfort.
<dfn attribute for="VRFrameData">leftViewMatrix</dfn>
A 4x4 matrix describing the view transform to be used for the left eye's rendering, given as a 16 element array in column major order. Represents the inverse of the model matrix of the left eye in sitting space. This value may be passed directly to WebGL's uniformMatrix4fv function. It is highly recommended that applications use this matrix when rendering.
<dfn attribute for="VRFrameData">rightProjectionMatrix</dfn>
A 4x4 matrix describing the projection to be used for the right eye's rendering, given as a 16 element array in column major order. This value may be passed directly to WebGL's uniformMatrix4fv function. It is highly recommended that applications use this matrix without modification. Failure to use this projection matrix when rendering may cause the presented frame to be distorted or badly aligned, resulting in varying degrees of user discomfort.
<dfn attribute for="VRFrameData">rightViewMatrix</dfn>
A 4x4 matrix describing the view transform to be used for the right eye's rendering, given as a 16 element array in column major order. Represents the inverse of the model matrix of the right eye in sitting space. This value may be passed directly to WebGL's uniformMatrix4fv function. It is highly recommended that applications use this matrix when rendering.
<dfn attribute for="VRFrameData">pose</dfn>
The {{VRPose}} of the {{VRDisplay}} at {{timestamp}}.
## VREyeParameters ## {#interface-vreyeparameters}
The {{VREyeParameters}} interface represents all the information required to correctly render a scene for a given eye.
<pre class="idl">
interface VREyeParameters {
readonly attribute Float32Array offset;
[SameObject] readonly attribute VRFieldOfView fieldOfView;
readonly attribute unsigned long renderWidth;
readonly attribute unsigned long renderHeight;
};
</pre>
### Attributes ### {#vreyeparameters-attributes}
<dfn attribute for="VREyeParameters">offset</dfn>
A three component vector describing the offset from the center point between the users eyes to the center of the eye in meters. The x component of this vector SHOULD represent half of the user's interpupillary distance (IPD), but MAY also represent the vector from the center point of the headset to the center point of the lens for the given eye. Values in the x component for left eye MUST be negative; values in the x component for right eye MUST be positive. This information should not be used to construct a view matrix, prefer using the view matricies provided in {{VRFrameData}} instead.
<dfn attribute for="VREyeParameters">fieldOfView</dfn>
<i>(Deprecated)</i> The current field of view for the eye. SHOULD conservatively cover the entire viewable frustum of the eye. The application should not use these values to construct a projection matrix, as it may not take into account all aspects of the {{VRDisplay}} optics. Prefer using the projection matrices provided in {{VRFrameData}} instead.
<dfn attribute for="VREyeParameters">renderWidth</dfn>
Describes the recommended render target width of each eye viewport, in pixels. If multiple eyes are rendered in a single render target, then the render target should be made large enough to fit both viewports. The {{renderWidth}} for the left eye and right eye MUST NOT overlap, and the {{renderWidth}} for the right eye MUST be to the right of the {{renderWidth}} for the left eye.
<dfn attribute for="VREyeParameters">renderHeight</dfn>
Describes the recommended render target height of each eye viewport, in pixels. If multiple eyes are rendered in a single render target, then the render target should be made large enough to fit both viewports. The {{renderWidth}} for the left eye and right eye MUST NOT overlap, and the {{renderWidth}} for the right eye MUST be to the right of the {{renderWidth}} for the left eye.
<div class="example">
Many HMDs will distort the rendered image to counteract undesired effects introduced by the headset optics. Because of this the optimal resolution of the canvas will often be larger than the HMD's physical resolution to ensure that the final image presented to the user has a 1:1 pixel ratio at the center of the user's view. The optimal canvas resolution can be calculated from the {{renderWidth}} and {{renderHeight}} for both eyes as follows:
<pre class="lang-js">
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>
</div>
## VRStageParameters ## {#interface-vrstageparameters}
The {{VRStageParameters}} interface represents the values describing the the stage/play area for devices that support room-scale experiences.
<pre class="idl">
interface VRStageParameters {
readonly attribute Float32Array sittingToStandingTransform;
readonly attribute float sizeX;
readonly attribute float sizeZ;
};
</pre>
### Attributes ### {#vrstageparameters-attributes}
<dfn attribute for="VRStageParameters">sittingToStandingTransform</dfn>
The {{sittingToStandingTransform}} attribute is a 16-element array containing the components of a 4x4 affine transformation matrix in column-major order. This matrix transforms the sitting-space view matrices of {{VRFrameData}} to standing-space. Multiplying the inverse of this matrix with the {{leftViewMatrix}} or {{rightViewMatrix}} will result in a standing space view matrix for the respective eye.
<dfn attribute for="VRStageParameters">sizeX</dfn>
Width of the play-area bounds in meters. The bounds are defined as an axis-aligned rectangle on the floor. The center of the rectangle is at (0,0,0) in standing-space coordinates. These bounds are defined for safety purposes. Content should not require the user to move beyond these bounds; however, it is possible for the user to ignore the bounds resulting in position values outside of this rectangle.
<dfn attribute for="VRStageParameters">sizeZ</dfn>
Depth of the play-area bounds in meters. The bounds are defined as an axis-aligned rectangle on the floor. The center of the rectangle is at (0,0,0) in standing-space coordinates. These bounds are defined for safety purposes. Content should not require the user to move beyond these bounds; however, it is possible for the user to ignore the bounds resulting in position values outside of this rectangle.
## Navigator Interface extension ## {#interface-navigator}
<pre class="idl">
partial interface Navigator {
Promise<sequence<VRDisplay>> getVRDisplays();
readonly attribute FrozenArray<VRDisplay> activeVRDisplays;
readonly attribute boolean vrEnabled;
};
</pre>
### Attributes ### {#navigator-attributes}
<dfn method for="Navigator" id="navigator-getvrdisplays-attribute">getVRDisplays()</dfn>
Return a Promise which resolves to a list of available {{VRDisplay}}s. The Promise MUST be rejected if the {{Document}} object is inside an iframe that does not have the {{allowvr}} attribute set.
<dfn attribute for="Navigator" id="navigator-activevrdisplays-attribute">activeVRDisplays</dfn>
{{activeVRDisplays}} includes every {{VRDisplay}} that is currently presenting.
<dfn attribute for="Navigator" id="navigator-vrenabled-attribute">vrEnabled</dfn>
The {{vrEnabled}} attribute's getter must return true if the context object is allowed to use the feature indicated by attribute name {{allowvr}} and VR is supported, and false otherwise.
<div class="example">
The following code finds the first available {{VRDisplay}}.
<pre class="lang-js">
var vrDisplay;
navigator.getVRDisplays().then(function (displays) {
// Use the first display in the array if one is available. If multiple
// displays are present, you may want to present the user with a way to
// select which display to use.
if (displays.length > 0) {
vrDisplay = displays[0];
}
});
</pre>
</div>
## VRDisplayEventReason ## {#interface-vrdisplayeventreason}
<pre class="idl">
enum VRDisplayEventReason {
"mounted",
"navigation",
"requested",
"unmounted"
};
</pre>
### Reasons ### {#vrdisplayeventreason-codes}
<dfn enum-value for="VRDisplayEventReason">mounted</dfn>
The {{VRDisplay}} has detected that the user has put it on.
<dfn enum-value for="VRDisplayEventReason">navigation</dfn>
The page has been navigated to from a context that allows this page to begin presenting immediately, such as from another site that was already in VR presentation mode.
<dfn enum-value for="VRDisplayEventReason">requested</dfn>
The user agent MAY request start VR presentation mode. This allows user agents to include a consistent UI to enter VR across diferent sites.
<dfn enum-value for="VRDisplayEventReason">unmounted</dfn>
The {{VRDisplay}} has detected that the user has taken it off.
## VRDisplayEvent ## {#interface-vrdisplayevent}
<pre class="idl">
[Constructor(DOMString type, VRDisplayEventInit eventInitDict)]
interface VRDisplayEvent : Event {
readonly attribute VRDisplay display;
readonly attribute VRDisplayEventReason? reason;
};
dictionary VRDisplayEventInit : EventInit {
required VRDisplay display;
VRDisplayEventReason reason;
};
</pre>
### Attributes ### {#vrdisplayevent-attributes}
<dfn attribute for="VRDisplayEvent">display</dfn>
The {{VRDisplay}} associated with this event.
<dfn attribute for="VRDisplayEvent">reason</dfn>
{{VRDisplayEventReason}} describing why this event has has been fired.
## Window Interface extension ## {#interface-window}
<pre class="idl">
partial interface Window {
attribute EventHandler onvrdisplayconnect;
attribute EventHandler onvrdisplaydisconnect;
attribute EventHandler onvrdisplayactivate;
attribute EventHandler onvrdisplaydeactivate;
attribute EventHandler onvrdisplayblur;
attribute EventHandler onvrdisplayfocus;
attribute EventHandler onvrdisplaypresentchange;
};
</pre>
User agents implementing this specification MUST provide the following new DOM events. The corresponding events must be of type {{VRDisplayEvent}} and must fire on the window object. Registration for and firing of the events must follow the usual behavior of DOM4 Events.
<dfn event for="Window" id="window-vrdisplayconnect-event">onvrdisplayconnect</dfn>
A user agent MAY dispatch this event type to indicate that a {{VRDisplay}} has been connected.
<dfn event for="Window" id="window-vrdisplaydisconnect-event">onvrdisplaydisconnect</dfn>
A user agent MAY dispatch this event type to indicate that a {{VRDisplay}} has been disconnected.
<dfn event for="Window" id="window-vrdisplayactivate-event">onvrdisplayactivate</dfn>
A user agent MAY dispatch this event type to indicate that something has occured which suggests the {{VRDisplay}} should be presented to. For example, if the {{VRDisplay}} is capable of detecting when the user has put it on, this event SHOULD fire when they do so with the reason "mounted".
<dfn event for="Window" id="window-vrdisplaydeactivate-event">onvrdisplaydeactivate</dfn>
A user agent MAY dispatch this event type to indicate that something has occured which suggests the {{VRDisplay}} should exit presentation. For example, if the {{VRDisplay}} is capable of detecting when the user has taken it off, this event SHOULD fire when they do so with the reason "unmounted".
<dfn event for="Window" id="window-onvrdisplayblur-event">onvrdisplayblur</dfn>
A user agent MAY dispatch this event type to indicate that presentation to the display by the page is paused by the user agent, OS, or VR hardware. While a {{VRDisplay}} is blurred it does not lose it's presenting status ({{isPresenting}} continues to report true) but {{getFrameData()}} returns false without updating the provided {{VRFrameData}} and {{getPose()}} returns null. This is to prevent tracking while the user interacts with potentially sensitive UI. For example: A user agent SHOULD blur the presenting application when the user is typing a URL into the browser with a virtual keyboard, otherwise the presenting page may be able to guess the URL the user is entering by tracking their head motions.
<dfn event for="Window" id="window-onvrdisplayfocus-event">onvrdisplayfocus</dfn>
A user agent MAY dispatch this event type to indicate that presentation to the display by the page has resumed after being blurred.
<dfn event for="Window" id="window-vrdisplaypresentchange-event">onvrdisplaypresentchange</dfn>
A user agent MUST dispatch this event type to indicate that a {{VRDisplay}} has begun or ended VR presentation. This event should not fire on subsequent calls to {{requestPresent()}} after the {{VRDisplay}} has already begun VR presentation.
## allowvr iframe attribute ## {#allowvr-attribute}
<pre class="idl">
partial interface HTMLIFrameElement {
attribute boolean allowvr;
};
</pre>
The {{allowvr}} attribute is a boolean attribute. When specified, it indicates that {{Document}} objects in the iframe element's browsing context are to be allowed to access VR devices (if it's not blocked for other reasons, e.g. there is another ancestor iframe without this attribute set). {{Document}} objects in an iframe element without this attribute should reject calls to {{getVRDisplays()}} and should not fire any {{VRDisplayEvent}}.
<div class="example">
Example of declaring an iframe that is allowed to access VR features.
<pre class="lang-js">
<body>
<p>This iframe is allowed to use VR features</p>
<iframe src="https://vr.example.com/embed?id=67445" allowvr></iframe>
</body>
</pre>
</div>
## Gamepad Interface extension ## {#interface-gamepad}
<pre class="idl">
partial interface Gamepad {
readonly attribute unsigned long displayId;
};
</pre>
### Attributes ### {#gamepad-attributes}
<dfn attribute for="Gamepad" id="gamepad-getvrdisplays-attribute">displayId</dfn>
Return the {{VRDisplay/displayId}} of the {{VRDisplay}} this {{Gamepad}} is associated with. A {{Gamepad}} is considered to be associated with a {{VRDisplay}} if it reports a pose that is in the same space as the {{VRDisplay}} pose. If the {{Gamepad}} is not associated with a {{VRDisplay}} should return 0.
# Security Considerations # {#security}
While not directly affecting the API interface and Web IDL, WebVR implementations should maintain the user's expectations of privacy, security, and comfort on the Web by adhering to the following guidelines:
* Trusted UI must be drawn by an independent rendering context who's state is isolated from that of the WebGL contexts provided as a {{VRLayer}} source to a {{VRDisplay}}.
* A "VR Compositor" runs asynchronously from content, responsible for compositing the trusted and untrusted content. If content is not performant or does not submit frames, or terminates unexpectedly the browser should be able to continue presenting a responsive front-end.
* Users should always be provided an action, such as pressing a reserved hardware button or performing a gesture, that escapes out of WebVR content and displays the browsers trusted UI.
* When navigating between pages in VR the browser should display trusted UI elements informing the user of the security information of the site they are navigating to which is normally presented by the 2D UI, such as the URL and encryption status.
* The {{VRDisplay}} pose and other VR inputs are only updated for the focused page.
* The Gamepad API will be updated such that the gamepad inputs are only updated for the focused page.
* Non-focused tabs are allowed to enumerate {{Gamepad}}s and {{VRDisplay}}s but will see last received state or default values.
* To prevent CORS-related vulnerabilities, each page will see a new instance of objects returned by the WebVR API, such as {{VRDisplay}}. Attributes such as the {{VRLayer}}.{{VRLayer/source}} set by one page must not be able to be read by another.
# Acknowledgements # {#ack}