You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							383 lines
						
					
					
						
							19 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							383 lines
						
					
					
						
							19 KiB
						
					
					
				
								<!DOCTYPE html><html lang="en"><head>
							 | 
						|
								    <meta charset="utf-8">
							 | 
						|
								    <title>VR</title>
							 | 
						|
								    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
							 | 
						|
								    <meta name="twitter:card" content="summary_large_image">
							 | 
						|
								    <meta name="twitter:site" content="@threejs">
							 | 
						|
								    <meta name="twitter:title" content="Three.js – VR">
							 | 
						|
								    <meta property="og:image" content="https://threejs.org/files/share.png">
							 | 
						|
								    <link rel="shortcut icon" href="/files/favicon_white.ico" media="(prefers-color-scheme: dark)">
							 | 
						|
								    <link rel="shortcut icon" href="/files/favicon.ico" media="(prefers-color-scheme: light)">
							 | 
						|
								
							 | 
						|
								    <link rel="stylesheet" href="/manual/resources/lesson.css">
							 | 
						|
								    <link rel="stylesheet" href="/manual/resources/lang.css">
							 | 
						|
								<!-- Import maps polyfill -->
							 | 
						|
								<!-- Remove this when import maps will be widely supported -->
							 | 
						|
								<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
							 | 
						|
								
							 | 
						|
								<script type="importmap">
							 | 
						|
								{
							 | 
						|
								  "imports": {
							 | 
						|
								    "three": "../../build/three.module.js"
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								  </head>
							 | 
						|
								  <body>
							 | 
						|
								    <div class="container">
							 | 
						|
								      <div class="lesson-title">
							 | 
						|
								        <h1>VR</h1>
							 | 
						|
								      </div>
							 | 
						|
								      <div class="lesson">
							 | 
						|
								        <div class="lesson-main">
							 | 
						|
								          <p>Making a VR app in three.js is pretty simple. You basically just have to tell
							 | 
						|
								three.js you want to use WebXR. If you think about it a few things about WebXR
							 | 
						|
								should be clear. Which way the camera is pointing is supplied by the VR system
							 | 
						|
								itself since the user turns their head to choose a direction to look. Similarly
							 | 
						|
								the field of view and aspect will be supplied by the VR system since each system
							 | 
						|
								has a different field of view and display aspect.</p>
							 | 
						|
								<p>Let's take an example from the article on <a href="responsive.html">making a responsive webpage</a>
							 | 
						|
								and make it support VR.</p>
							 | 
						|
								<p>Before we get started you're going to need a VR capable device like an Android
							 | 
						|
								smartphone, Google Daydream, Oculus Go, Oculus Rift, Vive, Samsung Gear VR., an
							 | 
						|
								iPhone with a <a href="https://apps.apple.com/us/app/webxr-viewer/id1295998056">WebXR browser</a>.</p>
							 | 
						|
								<p>Next, if you are running locally you need to run a simple web server like is
							 | 
						|
								covered in <a href="setup.html">the article on setting up</a>. </p>
							 | 
						|
								<p>If the device you are using to view VR is not the same computer you're running
							 | 
						|
								on you need to serve your webpage via https or else the browser will not allow using
							 | 
						|
								the WebXR API. The server mentioned in <a href="setup.html">the article on setting up</a>
							 | 
						|
								called <a href="https://greggman.github.io/servez">Servez</a> has an option to use https. 
							 | 
						|
								Check it and start the server. </p>
							 | 
						|
								<div class="threejs_center"><img src="../resources/images/servez-https.png" class="nobg" style="width: 912px;"></div>
							 | 
						|
								
							 | 
						|
								<p>The note the URLs. You need the one that is your computer's local ipaddress.
							 | 
						|
								It will usually start with <code class="notranslate" translate="no">192</code>, <code class="notranslate" translate="no">172</code> or <code class="notranslate" translate="no">10</code>. Type that full address, including the <code class="notranslate" translate="no">https://</code> part
							 | 
						|
								into your VR device's browser. Note: Your computer and your VR device need to be on the same local network
							 | 
						|
								or WiFi and you probably need to be on a home network. note: Many cafes are setup to disallow this kind of
							 | 
						|
								machine to machine connection.</p>
							 | 
						|
								<p>You'll be greeted with an error something like the one below. Click "advanced" and then click
							 | 
						|
								<em>proceed</em>.</p>
							 | 
						|
								<div class="threejs_center"><img src="../resources/images/https-warning.gif"></div>
							 | 
						|
								
							 | 
						|
								<p>Now you can run your examples.</p>
							 | 
						|
								<p>If you're really going to do WebXR development another thing you should learn about is
							 | 
						|
								<a href="https://developers.google.com/web/tools/chrome-devtools/remote-debugging/">remote debugging</a>
							 | 
						|
								so that you can see console warnings, errors, and of course actually 
							 | 
						|
								<a href="debugging-javascript.html">debug your code</a>.</p>
							 | 
						|
								<p>If you just want to see the code work below you can just run the code from
							 | 
						|
								this site.</p>
							 | 
						|
								<p>The first thing we need to do is include the VR support after
							 | 
						|
								including three.js</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from 'three';
							 | 
						|
								+import {VRButton} from 'three/addons/webxr/VRButton.js';
							 | 
						|
								</pre>
							 | 
						|
								<p>Then we need to enable three.js's WebXR support and add its
							 | 
						|
								VR button to our page</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
							 | 
						|
								  const canvas = document.querySelector('#c');
							 | 
						|
								  const renderer = new THREE.WebGLRenderer({canvas});
							 | 
						|
								+  renderer.xr.enabled = true;
							 | 
						|
								+  document.body.appendChild(VRButton.createButton(renderer));
							 | 
						|
								</pre>
							 | 
						|
								<p>We need to let three.js run our render loop. Until now we have used a
							 | 
						|
								<code class="notranslate" translate="no">requestAnimationFrame</code> loop but to support VR we need to let three.js handle
							 | 
						|
								our render loop for us. We can do that by calling
							 | 
						|
								<a href="/docs/#api/en/renderers/WebGLRenderer.setAnimationLoop"><code class="notranslate" translate="no">WebGLRenderer.setAnimationLoop</code></a> and passing a function to call for the loop.</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
							 | 
						|
								  time *= 0.001;
							 | 
						|
								
							 | 
						|
								  if (resizeRendererToDisplaySize(renderer)) {
							 | 
						|
								    const canvas = renderer.domElement;
							 | 
						|
								    camera.aspect = canvas.clientWidth / canvas.clientHeight;
							 | 
						|
								    camera.updateProjectionMatrix();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  cubes.forEach((cube, ndx) => {
							 | 
						|
								    const speed = 1 + ndx * .1;
							 | 
						|
								    const rot = time * speed;
							 | 
						|
								    cube.rotation.x = rot;
							 | 
						|
								    cube.rotation.y = rot;
							 | 
						|
								  });
							 | 
						|
								
							 | 
						|
								  renderer.render(scene, camera);
							 | 
						|
								
							 | 
						|
								-  requestAnimationFrame(render);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								-requestAnimationFrame(render);
							 | 
						|
								+renderer.setAnimationLoop(render);
							 | 
						|
								</pre>
							 | 
						|
								<p>There is one more detail. We should probably set a camera height
							 | 
						|
								that's kind of average for a standing user.</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
							 | 
						|
								+camera.position.set(0, 1.6, 0);
							 | 
						|
								</pre>
							 | 
						|
								<p>and move the cubes up to be in front of the camera</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
							 | 
						|
								scene.add(cube);
							 | 
						|
								
							 | 
						|
								cube.position.x = x;
							 | 
						|
								+cube.position.y = 1.6;
							 | 
						|
								+cube.position.z = -2;
							 | 
						|
								</pre>
							 | 
						|
								<p>We set them to <code class="notranslate" translate="no">z = -2</code> since the camera will now be at <code class="notranslate" translate="no">z = 0</code> and
							 | 
						|
								camera defaults to looking down the -z axis.</p>
							 | 
						|
								<p>This brings up an extremely important point. <strong>Units in VR are in meters</strong>.
							 | 
						|
								In other words <strong>One Unit = One Meter</strong>. This means the camera is 1.6 meters above 0.
							 | 
						|
								The cube's centers are 2 meters in front of the camera. Each cube
							 | 
						|
								is 1x1x1 meter large. This is important because VR needs to adjust things to the
							 | 
						|
								user <em>in the real world</em>. That means we need the units used in three.js to match
							 | 
						|
								the user's own movements.</p>
							 | 
						|
								<p>And with that we should get 3 spinning cubes in front
							 | 
						|
								of the camera with a button to enter VR.</p>
							 | 
						|
								<p></p><div translate="no" class="threejs_example_container notranslate">
							 | 
						|
								  <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/webxr-basic.html"></iframe></div>
							 | 
						|
								  <a class="threejs_center" href="/manual/examples/webxr-basic.html" target="_blank">click here to open in a separate window</a>
							 | 
						|
								</div>
							 | 
						|
								
							 | 
						|
								<p></p>
							 | 
						|
								<p>I find that VR works better if we have something surrounding the camera like
							 | 
						|
								room for reference so let's add a simple grid cubemap like we covered in
							 | 
						|
								<a href="backgrounds.html">the article on backgrounds</a>. We'll just use the same grid
							 | 
						|
								texture for each side of the cube which will give as a grid room.</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
							 | 
						|
								+{
							 | 
						|
								+  const loader = new THREE.CubeTextureLoader();
							 | 
						|
								+  const texture = loader.load([
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+    'resources/images/grid-1024.png',
							 | 
						|
								+  ]);
							 | 
						|
								+  scene.background = texture;
							 | 
						|
								+}
							 | 
						|
								</pre>
							 | 
						|
								<p>That's better.</p>
							 | 
						|
								<p></p><div translate="no" class="threejs_example_container notranslate">
							 | 
						|
								  <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/webxr-basic-w-background.html"></iframe></div>
							 | 
						|
								  <a class="threejs_center" href="/manual/examples/webxr-basic-w-background.html" target="_blank">click here to open in a separate window</a>
							 | 
						|
								</div>
							 | 
						|
								
							 | 
						|
								<p></p>
							 | 
						|
								<p>Note: To actually see VR you will need a WebXR compatible device.
							 | 
						|
								I believe most Android Phones can support WebXR using Chrome or Firefox.
							 | 
						|
								For iOS you might be able to use this <a href="https://apps.apple.com/us/app/webxr-viewer/id1295998056">WebXR App</a>
							 | 
						|
								though in general WebXR support on iOS is unsupported as of May 2019.</p>
							 | 
						|
								<p>To use WebXR on Android or iPhone you'll need a <em>VR Headset</em>
							 | 
						|
								for phones. You can get them for anywhere from $5 for one made of cardboard
							 | 
						|
								to $100. Unfortunately I don't know which ones to recommend. I've purchased
							 | 
						|
								6 of them over the years and they are all of varying quality. I've
							 | 
						|
								never paid more than about $25.</p>
							 | 
						|
								<p>Just to mention some of the issues</p>
							 | 
						|
								<ol>
							 | 
						|
								<li><p>Do they fit your phone</p>
							 | 
						|
								<p>Phones come in a variety of sizes and so the VR headsets need to match.
							 | 
						|
								Many headsets claim to match a large variety of sizes. My experience
							 | 
						|
								is the more sizes they match the worse they actually are since instead
							 | 
						|
								of being designed for a specific size they have to make compromises
							 | 
						|
								to match more sizes. Unfortunately multi-size headsets are the most common type.</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>Can they focus for your face</p>
							 | 
						|
								<p>Some devices have more adjustments than others. Generally there
							 | 
						|
								are at most 2 adjustments. How far the lenses are from your eyes
							 | 
						|
								and how far apart the lenses are.</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>Are they too reflective</p>
							 | 
						|
								<p>Many headsets of a cone of plastic from your eye to the phone.
							 | 
						|
								If that plastic is shinny or reflective then it will act like
							 | 
						|
								a mirror reflecting the screen and be very distracting.</p>
							 | 
						|
								<p>Few if any of the reviews seem to cover this issue.</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>Are the comfortable on your face.</p>
							 | 
						|
								<p>Most of the devices rest on your nose like a pair of glasses.
							 | 
						|
								That can hurt after a few minutes. Some have straps that go around
							 | 
						|
								your head. Others have a 3rd strap that goes over your head. These
							 | 
						|
								may or may not help keep the device at the right place.</p>
							 | 
						|
								<p>It turns out for most (all?) devices, you eyes need to be centered
							 | 
						|
								with the lenses. If the lenses are slightly above or below your
							 | 
						|
								eyes the image gets out of focus. This can be very frustrating
							 | 
						|
								as things might start in focus but 45-60 seconds later the device
							 | 
						|
								has shifted up or down 1 millimeter and you suddenly realize you've
							 | 
						|
								been struggling to focus on a blurry image.</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>Can they support your glasses.</p>
							 | 
						|
								<p>If you wear eye glasses then you'll need to read the reviews to see
							 | 
						|
								if a particular headset works well with eye glasses.</p>
							 | 
						|
								</li>
							 | 
						|
								</ol>
							 | 
						|
								<p>I really can't make any recommendations unfortunately. <a href="https://vr.google.com/cardboard/get-cardboard/">Google has some
							 | 
						|
								cheap recommendations made from cardboard</a>
							 | 
						|
								some of them as low as $5 so maybe start there and if you enjoy it
							 | 
						|
								then consider upgrading. $5 is like the price of 1 coffee so seriously, give it try!</p>
							 | 
						|
								<p>There are also 3 basic types of devices.</p>
							 | 
						|
								<ol>
							 | 
						|
								<li><p>3 degrees of freedom (3dof), no input device</p>
							 | 
						|
								<p>This is generally the phone style although sometimes you can
							 | 
						|
								buy a 3rd party input device. The 3 degrees of freedom
							 | 
						|
								mean you can look up/down (1), left/right(2) and you can tilt
							 | 
						|
								your head left and right (3).</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>3 degrees of freedom (3dof) with 1 input device (3dof)</p>
							 | 
						|
								<p>This is basically Google Daydream and Oculus GO</p>
							 | 
						|
								<p>These also allow 3 degrees of freedom and include a small
							 | 
						|
								controller that acts like a laser pointer inside VR.
							 | 
						|
								The laser pointer also only has 3 degrees of freedom. The
							 | 
						|
								system can tell which way the input device is pointing but
							 | 
						|
								it can not tell where the device is.</p>
							 | 
						|
								</li>
							 | 
						|
								<li><p>6 degrees of freedom (6dof) with input devices (6dof)</p>
							 | 
						|
								<p>These are <em>the real deal</em> haha. 6 degrees of freedom
							 | 
						|
								means not only do these device know which way you are looking
							 | 
						|
								but they also know where your head actually is. That means
							 | 
						|
								if you move from left to right or forward and back or stand up / sit down
							 | 
						|
								the devices can register this and everything in VR moves accordingly.
							 | 
						|
								It's spookily and amazingly real feeling. With a good demo
							 | 
						|
								you'll be blown away or at least I was and still am.</p>
							 | 
						|
								<p>Further these devices usually include 2 controllers, one
							 | 
						|
								for each hand and the system can tell exactly where your
							 | 
						|
								hands are and which way they are oriented and so you can
							 | 
						|
								manipulate things in VR by just reaching out, touching,
							 | 
						|
								pushing, twisting, etc...</p>
							 | 
						|
								<p>6 degree of freedom devices include the Vive and Vive Pro,
							 | 
						|
								the Oculus Rift and Quest, and I believe all of the Windows MR devices.</p>
							 | 
						|
								</li>
							 | 
						|
								</ol>
							 | 
						|
								<p>With all that covered I don't for sure know which devices will work with WebXR.
							 | 
						|
								I'm 99% sure that most Android phones will work when running Chrome. You may
							 | 
						|
								need to turn on WebXR support in <a href="about:flags"><code class="notranslate" translate="no">about:flags</code></a>. I also know Google
							 | 
						|
								Daydream will also work and similarly you need to enable WebXR support in
							 | 
						|
								<a href="about:flags"><code class="notranslate" translate="no">about:flags</code></a>. Oculus Rift, Vive, and Vive Pro will work via
							 | 
						|
								Chrome or Firefox. I'm less sure about Oculus Go and Oculus Quest as both of
							 | 
						|
								them use custom OSes but according to the internet they both appear to work.</p>
							 | 
						|
								<p>Okay, after that long detour about VR Devices and WebXR
							 | 
						|
								there's some things to cover</p>
							 | 
						|
								<ul>
							 | 
						|
								<li><p>Supporting both VR and Non-VR</p>
							 | 
						|
								<p>AFAICT, at least as of r112, there is no easy way to support
							 | 
						|
								both VR and non-VR modes with three.js. Ideally
							 | 
						|
								if not in VR mode you'd be able to control the camera using
							 | 
						|
								whatever means you want, for example the <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>,
							 | 
						|
								and you'd get some kind of event when switching into and
							 | 
						|
								out of VR mode so that you could turn the controls on/off.</p>
							 | 
						|
								</li>
							 | 
						|
								</ul>
							 | 
						|
								<p>If three.js adds some support to do both I'll try to update
							 | 
						|
								this article. Until then you might need 2 versions of your 
							 | 
						|
								site OR pass in a flag in the URL, something like</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate notranslate" translate="no">https://mysite.com/mycooldemo?allowvr=true
							 | 
						|
								</pre><p>Then we could add some links in to switch modes</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><body>
							 | 
						|
								  <canvas id="c"></canvas>
							 | 
						|
								+  <div class="mode">
							 | 
						|
								+    <a href="?allowvr=true" id="vr">Allow VR</a>
							 | 
						|
								+    <a href="?" id="nonvr">Use Non-VR Mode</a>
							 | 
						|
								+  </div>
							 | 
						|
								</body>
							 | 
						|
								</pre>
							 | 
						|
								<p>and some CSS to position them</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-css" translate="no">body {
							 | 
						|
								    margin: 0;
							 | 
						|
								}
							 | 
						|
								#c {
							 | 
						|
								    width: 100%;
							 | 
						|
								    height: 100%;
							 | 
						|
								    display: block;
							 | 
						|
								}
							 | 
						|
								+.mode {
							 | 
						|
								+  position: absolute;
							 | 
						|
								+  right: 1em;
							 | 
						|
								+  top: 1em;
							 | 
						|
								+}
							 | 
						|
								</pre>
							 | 
						|
								<p>in your code you could use that parameter like this</p>
							 | 
						|
								<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
							 | 
						|
								  const canvas = document.querySelector('#c');
							 | 
						|
								  const renderer = new THREE.WebGLRenderer({canvas});
							 | 
						|
								-  renderer.xr.enabled = true;
							 | 
						|
								-  document.body.appendChild(VRButton.createButton(renderer));
							 | 
						|
								
							 | 
						|
								  const fov = 75;
							 | 
						|
								  const aspect = 2;  // the canvas default
							 | 
						|
								  const near = 0.1;
							 | 
						|
								  const far = 5;
							 | 
						|
								  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
							 | 
						|
								  camera.position.set(0, 1.6, 0);
							 | 
						|
								
							 | 
						|
								+  const params = (new URL(document.location)).searchParams;
							 | 
						|
								+  const allowvr = params.get('allowvr') === 'true';
							 | 
						|
								+  if (allowvr) {
							 | 
						|
								+    renderer.xr.enabled = true;
							 | 
						|
								+    document.body.appendChild(VRButton.createButton(renderer));
							 | 
						|
								+    document.querySelector('#vr').style.display = 'none';
							 | 
						|
								+  } else {
							 | 
						|
								+    // no VR, add some controls
							 | 
						|
								+    const controls = new OrbitControls(camera, canvas);
							 | 
						|
								+    controls.target.set(0, 1.6, -2);
							 | 
						|
								+    controls.update();
							 | 
						|
								+    document.querySelector('#nonvr').style.display = 'none';
							 | 
						|
								+  }
							 | 
						|
								</pre>
							 | 
						|
								<p>Whether that's good or bad I don't know. I have a feeling the differences
							 | 
						|
								between what's needed for VR and what's needed for non-VR are often
							 | 
						|
								very different so for all but the most simple things maybe 2 separate pages
							 | 
						|
								are better? You'll have to decide.</p>
							 | 
						|
								<p>Note for various reasons this will not work in the live editor
							 | 
						|
								on this site so if you want to check it out 
							 | 
						|
								<a href="../examples/webxr-basic-vr-optional.html" target="_blank">click here</a>.
							 | 
						|
								It should start in non-VR mode and you can use the mouse or fingers to move
							 | 
						|
								the camera. Clicking "Allow VR" should switch to allow VR mode and you should
							 | 
						|
								be able to click "Enter VR" if you're on a VR device.</p>
							 | 
						|
								<ul>
							 | 
						|
								<li><p>Deciding on the level of VR support</p>
							 | 
						|
								<p>Above we covered 3 types of VR devices. </p>
							 | 
						|
								<ul>
							 | 
						|
								<li>3DOF no input</li>
							 | 
						|
								<li>3DOF + 3DOF input</li>
							 | 
						|
								<li>6DOF + 6DOF input</li>
							 | 
						|
								</ul>
							 | 
						|
								<p>You need to decide how much effort you're willing to put in
							 | 
						|
								to support each type of device.</p>
							 | 
						|
								<p>For example the simplest device has no input. The best you can
							 | 
						|
								generally do is make it so there are some buttons or objects in the user's view
							 | 
						|
								and if the user aligns some marker in the center of the display
							 | 
						|
								on those objects for 1/2 a second or so then that button is clicked.
							 | 
						|
								A common UX is to display a small timer that will appear over the object indicating
							 | 
						|
								if you keep the marker there for a moment the object/button will be selected.</p>
							 | 
						|
								<p>Since there is no other input that's about the best you can do</p>
							 | 
						|
								<p>The next level up you have one 3DOF input device. Generally it
							 | 
						|
								can point at things and the user has at least 2 buttons. The Daydream
							 | 
						|
								also has a touchpad which provides normal touch inputs.</p>
							 | 
						|
								<p>In any case if a user has this type of device it's far more
							 | 
						|
								comfortable for the user to by able to point at things with
							 | 
						|
								their controller than it is to make them do it with their
							 | 
						|
								head by looking at things.</p>
							 | 
						|
								<p>A similar level to that might be 3DOF or 6DOF device with a
							 | 
						|
								game console controller. You'll have to decide what to do here.
							 | 
						|
								I suspect the most common thing is the user still has to look
							 | 
						|
								to point and the controller is just used for buttons.</p>
							 | 
						|
								<p>The last level is a user with a 6DOF headset and 2 6DOF controllers.
							 | 
						|
								Those users will find an experience that is only 3DOF to often
							 | 
						|
								be frustrating. Similarly they usually expect to be able to 
							 | 
						|
								virtually manipulate things with their hands in VR so you'll
							 | 
						|
								have to decide if you want to support that or not.</p>
							 | 
						|
								</li>
							 | 
						|
								</ul>
							 | 
						|
								<p>As you can see getting started in VR is pretty easy but
							 | 
						|
								actually making something shippable in VR will require
							 | 
						|
								lots of decision making and design.</p>
							 | 
						|
								<p>This was a pretty brief intro into VR with three.js. We'll
							 | 
						|
								cover some of the input methods in <a href="webxr-look-to-select.html">future articles</a>.</p>
							 | 
						|
								
							 | 
						|
								        </div>
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								  
							 | 
						|
								  <script src="/manual/resources/prettify.js"></script>
							 | 
						|
								  <script src="/manual/resources/lesson.js"></script>
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								</body></html>
							 | 
						|
								
							 |