# VR

가상현실 앱을 three.js로 만드는 것은 매우 기본적으로 three.js에게 WedXR을 사용할 것이라 알리기만 하면됩니다. WedXR에 몇가지 사항을 명확하게 해야 하는데 이를 생각하여 보면 먼저 카메라가 가리키는 방향은 향하고 있는지 VR시스템에서 제공해야합니다. 사용자가 머리를 돌려 보는 방향을 선택하기 때문입니다. 비슷하게 각 시스템 이후 VR 시스템에서 시야와 화면비가 제공됩니다. (각 시스템은 시야와 디스플레이 측면이 다릅니다)

반응형 웹페이지 만들기 예시를 통하여 VR을 지원하도록 만들어 보겠습니다.

시작하기 전에 안드로이드 스마트폰, 구글 데이드림, 오큘러스 고, 오큘러스 리프트, 바이브, 삼성 기어 VR, WebXR browser가 설치된 아이폰과 같은 VR 지원 장치가 필요합니다.

다음으로, 로컬에서 실행 중인 경우 다음과 같은 간단한 웹 서버를 실행해야 합니다. the article on setting up 참조.

VR을 보는 데 사용하는 장치가 실행 중인 컴퓨터와 다른 경우 https를 통해 웹 페이지를 서비스해야 합니다. 그렇지 않으면 브라우저에서 사용을 허용하지 않습니다. WebXR API. the article on setting up에 언급된 서버 Servez에는 https를 사용할 수 있는 옵션이 있습니다. 확인 후 서버를 시작합니다.

URL을 기록해 두십시오. 컴퓨터의 로컬 IP 주소가 필요합니다. 일반적으로 `192`, `172` 또는 `10`으로 시작합니다. `https://` 부분을 포함한 전체 주소를 입력하시면 됩니다.

VR 기기의 브라우저로 이동합니다. NOTE: 작업 컴퓨터와 VR 장치는 동일한 로컬 네트워크에 있어야 합니다. 또는 WiFi이고 아마도 홈 네트워크에 있어야 할것입니다. NOTE: 많은 카페에서 이러한 방법으로 기계 대 기계 연결을 합니다.

아래와 같은 오류 메시지가 표시됩니다. "고급(advanced)"을 클릭한 다음 진행(proceed) 을 클릭합니다.

이제 예제를 실행할 수 있습니다.

실제로 WebVR 개발을 하려는 경우 배워야 할 또 다른 사항은 원격 디버깅(remote debugging) 입니다. 이를 통해 콘솔 경보, 오류, 실제로 코드 디버그(debug your code)가 가능합니다.

아래 코드가 작동하는 것을 보고 싶다면 이 사이트에서 코드를 실행할 수 있습니다.

가장 먼저 해야 할 일은 three.js를 포함시킨 후 VR 지원을 포함하는 것입니다.

    import * as THREE from 'three';
    +import {VRButton} from 'three/addons/webxr/VRButton.js';

이후 three.js's WebXR 지원을 활성화하며, 이를 위한 VR button을 페이지에 추가하여 주어야합니다.

    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
    +  renderer.xr.enabled = true;
    +  document.body.appendChild(VRButton.createButton(renderer));

three.js가 렌더 루프를 실행하도록 해야 합니다. 지금까지 우리는 `requestAnimationFrame`loop 를 사용하였습니다. 하지만 VR을 지원하기 위해서 우리는 three.js가 우리의 render loop를 관리할 수 있도록 해야합니다. 이 과정을 `WebGLRenderer.setAnimationLoop`를 호출 및 루프를 호출하는 함수를 전달하여 진행 가능하게 합니다.

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

세부 사항이 하나 더 있습니다. 우리는 아마 카메라 높이를 설정해야 합니다. 예로 서있는 사용자의 평균 키를 들 수 있습니다.

    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    +camera.position.set(0, 1.6, 0);

큐브를 카메라 앞으로 이동합니다.

    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    cube.position.x = x;
    +cube.position.y = 1.6;
    +cube.position.z = -2;

카메라가 `z = 0` 에 있고 카메라는 -z축을 바라보기 때문에 우리는 `z = -2`에 배치 시켰습니다(cude).

이것은 매우 중요한 점을 제시합니다. Units in VR are in meters. 다른 말로 One Unit = One Meter. 이것은 카메라가 0보다 1.6미터 위에 있음을 의미합니다. 큐브의 중심은 카메라 앞에서 2미터입니다. 각 큐브 1x1x1미터 크기입니다. 이것은 VR이 실제 세계 에 사용자에 반응하여 사물을 조정해야 하기 때문에 중요합니다. 즉 사용자의 움직임과 VR에서의 움직임을 매치 시켜줄 단위가 필요합니다.

그리고 그것으로(단위) 우리는 앞으로 3개의 회전하는 큐브와 VR에 들어갈 버튼 을 카메라 앞에 가져와야 합니다.

새 탭에서 보기

카메라 주변에 방(참조할 수 있는 공간)과 같은 감싸는 것이 있으면 VR이 더 잘 작동합니다. 따라서 과거 the article on backgrounds에서 진행한 것과 유사하게 간단한 그리드 큐브맵을 추가해 보겠습니다.

우리는 같은 그리드를 사용할 것입니다. 그리드 룸으로 제공할 큐브의 각 면에 대한 텍스처입니다.

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

더욱 나아진것이 확인 가능합니다.

새 탭에서 보기

Note: VR을 실제로 보려면 WebXR 호환 장치가 필요합니다. 대부분의 Android 휴대폰은 Chrome 또는 Firefox를 사용하여 WebXR을 지원 합니다. iOS의 경우 WebXR App를 참조 하시면 됩니다. iOS에서 일반적으로 WebXR 지원은 2019년 5월 현재 지원되지 않습니다.

Android 또는 iPhone에서 WebXR을 사용하려면 VR 헤드셋이 필요합니다. 전화용. 골판지로 만든 1개에 5달러부터 어디에서나 구입할 수 있습니다. 불행히도 어떤 제품을 추천해야 할지 모르겠습니다. 저는 여러가지 제품을 구입하였습니다. 그 중 6개는 수년에 걸쳐 생산되었으며 모두 품질이 다릅니다. $25 이상을 지불한 적은 없습니다.

VR 헤드셋의 몇 가지 문제만 언급하겠습니다.

1. 휴대전화에 맞습니까?

   전화기는 다양한 크기로 제공되므로 VR 헤드셋이 일치해야 합니다. 많은 헤드셋이 다양한 크기와 일치한다고 주장합니다. 내 경험 더 많은 스마트폰 크기와 일치할수록 기능은 나빠집니다. 특정 크기에 맞게 설계된 잘 타협한 제품을 구매해야 합니다.

2. 당신의 얼굴에 집중할 수 있습니까?

   일부 장치에는 다른 장치보다 더 많은 조절 요소가 있습니다. 일반적으로는 렌즈가 눈에서 얼마나 멀리 떨어져 있는지, 그리고 렌즈가 얼마나 멀리 떨어져 있는지 최대 2개의 조절 요소가 존재합니다.

3. 너무 반사적인가요?

   당신의 눈에서 전화까지 플라스틱 원뿔의 많은 헤드셋. 플라스틱이 반짝이거나 반사되면 다음과 같이 작동합니다. 화면을 반사하는 거울처럼 매우 산만합니다.

   리뷰 중 이 문제를 다루는 것으로 보이는 경우는 거의 없습니다.

4. 당신의 얼굴에 편안한가요?

   대부분의 장치는 안경처럼 코에 닿습니다. 몇 분 후에 아플 수 있습니다. 일부는 주변에 스트랩이 있습니다. 너의 머리 위로 가는 3번째 끈이 있습니다. 이것들은 장치를 올바른 위치에 유지하는 데 도움이 될 수도 있고 도움이 되지 않을 수도 있습니다.

   대부분의 (모든?) 장치에서 눈이 중앙에 있어야 합니다. 렌즈와 함께. 렌즈가 자신보다 약간 높거나 낮은 경우 눈 이미지의 초점이 흐려집니다. 이것은 매우 실망 스러울 수 있습니다. 작업이 초점에 맞게 시작될 수 있지만 45-60초 후에 장치를 1mm 위 또는 아래로 이동하면 갑자기 흐릿한 이미지에 초점을 맞추려고 애쓰는 경우가 있습니다.

5. 안경을 착용하고 사용할수 있습니까?

   안경을 쓰신 분들은 리뷰를 읽어보시고 특정 헤드셋이 안경과 잘 매치되는 경우는 정말 아쉽게도 추천을 해드릴 수가 없습니다.

   구글은 일부 판지로 만든 저렴한 추천 그들 중 일부는 $ 5만큼 낮으므로 거기에서 시작하고 즐길 수 있습니다. 그런 다음 업그레이드를 고려하시면 됩니다. ($5는 커피 1잔 가격과 같으니 꼭 이용해 보세요!)

또한 3가지 기본 유형의 장치가 있습니다.

1. 3자유도(3dof), 입력 장치 없음

   이것은 일반적으로 전화 스타일이지만 때로는 할 수 있습니다. 타사 입력 장치를 구입하십시오. 3 자유도 위/아래(1), 왼쪽/오른쪽(2)을 보고 기울일 수 있음을 의미합니다. 머리를 좌우로(3).

2. 1개의 입력 장치(3dof)로 3자유도(3dof)

   이것은 기본적으로 Google Daydream과 Oculus GO입니다.

   이것들은 또한 3개의 자유도를 허용하고 작은 VR 내부에서 레이저 포인터처럼 작동하는 컨트롤러입니다. 레이저 포인터의 자유도는 3개뿐입니다. NS 시스템은 입력 장치가 가리키는 방향을 알 수 있지만 장치가 어디에 있는지 알 수 없습니다.

3. 입력 장치(6dof)가 있는 6자유도(6dof)

   이것들은 좋은 물건입니다. 6 자유도 이 장치는 사용자가 보고 있는 방향을 알 뿐만 아니라 그러나 그들은 또한 당신의 머리가 실제로 어디에 있는지 알고 있습니다. 그 의미는 왼쪽에서 오른쪽으로 또는 앞뒤로 움직이거나 일어서거나 앉는 경우 장치는 이것을 등록할 수 있고 VR의 모든 것은 그에 따라 움직입니다. 놀랍도록 실제적인 느낌입니다. 당신도 이와 비슷한 경험을 하게될것입니다. 아니면 적어도 저는 그랬고 지금도 그렇습니다.

   또한 이러한 장치에는 일반적으로 2개의 컨트롤러가 포함됩니다. 각 손에 대하여 시스템은 사용자의 위치를 정확히 알 수 있습니다. (손이 어떤 방향으로 향하고 있는지 손을 뻗고, 만지고, 밀기, 비틀기 등...)

이 모든 것을 다루었지만 어떤 장치가 WebXR과 함께 작동할지 확신할 수 없습니다. Chrome을 실행할 때 대부분의 Android 휴대전화가 작동할 것이라고 99% 확신합니다. 당신은 `about:flags`에서 WebXR support를 켜야 할수도 있습니다.

Google Draydream 또한 비슷하게 작동할 것입니다.
`about:flags`에서 WebXR support 를 활성화 하세요.

Oculus Rift, Vive 및 Vive Pro는 Cheome 이나 Firefox를 통해 작동합니다.

Oculus Go와 Oculus Quest는 둘 다 사용자 정의 OS를 사용하지만 인터넷에 따르면 둘 다 작동하는 것으로 보입니다.

이제, VR 장치와 WebXR에 대한 긴 설명에 마지막을 설명하겠습니다.

- VR 및 Non-VR 모두 지원

내가 아는한 적어도 r112에서는 three.js 에 VR과 Non-VR 모드 모두를 지원하는 쉬운 방법이 없습니다.

이상적으로 VR 모드가 아니면 `OrbitControls`와 같은 것들을 사용하여 카메라를 제어할 수 있습니다. 그리고 이 전환 과정에서 일조의 여러 이벤트가 발생합니다. VR 모드에서 벗어나 컨트롤을 켜고 끌 수 있습니다.

만약 three.js가 앞서 말한 두가지를 지원해준다면 해당 artical을 업데이트 하도록 노력하겠습니다. 그때까지는 2가지 버전의 사이트를 만들거나 다음과 같이 URL에 flag 를 pass in 해줍니다.

    https://mysite.com/mycooldemo?allowvr=true

그럼 우리는 스위치 모드에 몇몇 링크를 추가할 수 있습니다.

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

그리고 추가한 것들을 배치할 css 를 추가합니다.

    body {
        margin: 0;
    }
    #c {
        width: 100%;
        height: 100%;
        display: block;
    }
    +.mode {
    +  position: absolute;
    +  right: 1em;
    +  top: 1em;
    +}

코드안에서 다음과 같은 파라미터를 사용 가능합니다.

    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({antialias: true, 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';
    +  }

어떤 방식이 적합하지는 모릅니다. VR에 필요한 것과 비 VR에 필요한 것 사이에는 종종 차이점을 느끼고 있습니다. 둘은 매우 다르므로 가장 간단한 것을 제외하고는 2개의 별도 페이지일 수 있습니다. 무엇이 더 좋은지는 사용자가 결정해야 합니다.

여러 가지 이유로 라이브 편집기에서 작동하지 않습니다. 이 사이트에 있으므로 확인하고 싶다면 여기를 클릭하세요. 비 VR 모드에서 시작해야 하며 마우스나 손가락을 사용하여 이동할 수 있습니다. 카메라. "허용 VR"을 클릭하면 VR 모드를 허용하도록 전환되어야 하며 VR 기기를 사용 중인 경우 "VR 입력"을 클릭할 수 있습니다.

- VR 지원 수준 결정

  위에서 우리는 3가지 유형의 VR 기기를 다루었습니다.

  - 3DOF input 없음
  - 3DOF + 3DOF input
  - 6DOF + 6DOF input

  목적에 따라 위 중 어떤 장치를 이용할지 결정해야합니다.

  예를 들어 가장 단순한 장치에는 입력이 없습니다. 당신이 할 수있는 최선 일반적으로 사용자의 보기에 일부 버튼이나 개체가 있도록 만드는 것입니다. 사용자가 디스플레이 중앙에 일부 마커를 정렬하는 경우 1/2초 동안 해당 개체에서 해당 버튼을 클릭합니다. 일반적인 UX는 다음을 나타내는 개체 위에 나타날 작은 타이머를 표시하는 것입니다. 잠시 동안 마커를 유지하면 개체/버튼이 선택됩니다.

  당신이 할 수 있는 최선에 대한 다른 입력이 없기 때문에 다음 레벨에는 하나의 3DOF 입력 장치가 있습니다. Daydream의 경우 일반적으로 사물을 가리킬 수 있고 사용자는 적어도 2개의 버튼을 가지고 있습니다. 또한 일반 터치 입력을 제공하는 터치 패드가 있습니다.

  어쨌든 사용자가 이러한 유형의 장치를 가지고 있다면 사용자가 머리를 이용하여 가르키는 것보다 훨씬 더 간단히 물건을 가리킬 수 있어 편안합니다.

  그것과 유사한 수준은 게임 콘솔 컨트롤러를 포함한 3DOF 또는 6DOF 장치일 수 있습니다.

  여기서 무엇을 할지 결정해야 합니다.

  가장 흔한 것은 사용자가 여전히 바라 봐야하며 컨트롤러는 버튼용으로만 사용된다는 점입니다.

  마지막 레벨은 6DOF 헤드셋과 2개의 6DOF 컨트롤러를 사용하는 사용자입니다. 이러한 사용자는 종종 3DOF와 다를게 없는 답답한 경험을 할 수도 있을것입니다. 마찬가지로 그들은 일반적으로 다음을 수행할 수 있을 것으로 기대합니다. VR에서 손으로 물건을 가상으로 조작하여 지원 여부를 결정해야 합니다.

보시다시피 VR을 시작하는 것은 매우 쉽지만 실제로 VR을 고르고 세팅하는데는 많은 디자인을 고민 및 결정 해야합니다.

이것은 three.js를 사용한 VR에 대한 아주 간단한 소개였습니다. 이제 future articles에서 일부 입력 방법을 다루겠습니다.