몰입형 웹은 브라우저를 통해 호스팅되는 가상 세계 환경을 의미합니다. 이 전체 가상 현실 환경은 브라우저 또는 VR 지원 헤드셋에 표시되었습니다.
몰입형 웹은 브라우저를 통해 호스팅되는 가상 세계 환경을 의미합니다. 여기에는 브라우저 또는 Google Daydream, Oculus Rift, Samsung Gear VR, HTC Vive, Windows Mixed Reality 헤드셋과 같은 VR 지원 헤드셋에 표시되는 전체 가상 현실 (VR) 환경과 AR 지원 휴대기기용으로 개발된 증강 현실 환경이 포함됩니다.
몰입형 환경을 설명하는 데 두 가지 용어를 사용하지만, 완전한 현실에서 완전히 몰입도 높은 VR 환경에 이르기까지 다양한 수준의 AR이 있는 스펙트럼으로 생각해야 합니다.
몰입형 환경의 예는 다음과 같습니다.
- 몰입형 360° 동영상
- 몰입형 환경에서 제공되는 기존 2D(또는 3D) 동영상
- 데이터 시각화
- 홈쇼핑
- 예술
- 아직 아무도 생각하지 못한 멋진걸
거기에 어떻게 가나요?
몰입형 웹은 이제 거의 1년 동안 초기 형태로 제공되고 있습니다. 이는 Chrome 62부터 시작 체험판에서 사용할 수 있는 WebVR 1.1 API를 통해 이루어졌습니다. 이 API는 Firefox 및 Edge와 Safari용 폴리필에서도 지원됩니다.
이제 다음 단계로 넘어갈 시간입니다.
오리진 트라이얼이 2018년 7월 24일에 종료되었으며, 사양은 WebXR Device API 및 새로운 오리진 트라이얼로 대체되었습니다.
WebVR 1.1은 어떻게 되었나요?
WebVR 1.1에서 많은 것을 배웠지만 시간이 지남에 따라 개발자가 빌드하려는 애플리케이션 유형을 지원하려면 몇 가지 주요 변경사항이 필요하다는 것이 분명해졌습니다. 얻은 교훈의 전체 목록은 너무 길어서 여기에 다루기 어렵지만 API가 기본 JavaScript 스레드에 명시적으로 연결되는 문제, 개발자가 명백히 잘못된 구성을 설정할 수 있는 기회가 너무 많음, 마술 창과 같은 일반적인 용도가 의도적인 기능이 아닌 부작용이라는 문제 등이 있습니다. 마법 창은 헤드셋 없이 몰입형 콘텐츠를 보는 기법으로, 앱이 기기의 방향 센서를 기반으로 단일 뷰를 렌더링합니다.
새로운 디자인을 통해 더 간편하게 구현하고 성능을 크게 개선할 수 있습니다. 동시에 AR 및 기타 사용 사례가 등장하고 있었으며 향후 이러한 사용 사례를 지원할 수 있도록 API를 확장할 수 있어야 했습니다.
WebXR Device API는 이러한 확장된 사용 사례를 염두에 두고 설계 및 명명되었으며 더 나은 방향을 제시합니다. WebVR의 구현자는 WebXR Device API로의 마이그레이션을 약속했습니다.
WebXR Device API란 무엇인가요?
이전의 WebVR 사양과 마찬가지로 WebXR Device API는 Google, Microsoft, Mozilla 등의 기여자가 있는 Immersive Web Community Group의 제품입니다. XR의 'X'는 몰입형 환경 스펙트럼의 모든 것을 나타내는 일종의 대수적 변수로 의도되었습니다. 이전에 언급된 오리진 트라이얼과 폴리필을 통해 사용할 수 있습니다.
이 도움말은 Chrome 67 베타 기간에 처음 게시되었을 때 VR 기능만 사용 설정되었습니다. Chrome 69에서 증강 현실이 도입되었습니다. 웹용 증강 현실에서 자세히 알아보세요.
이 새로운 API에는 이와 같은 기사에서 다룰 수 있는 것보다 더 많은 기능이 있습니다. WebXR 샘플을 이해하는 데 필요한 정보를 제공하고자 합니다. 자세한 내용은 원본 설명 및 몰입형 웹 얼리 어답터 가이드를 참고하세요. 오리진 트라이얼이 진행되면 후자를 확대할 예정입니다. 자유롭게 문제를 열거나 pull 요청을 제출하세요.
이 도움말에서는 XR 세션을 시작, 중지, 실행하는 방법과 입력 처리에 관한 몇 가지 기본사항을 설명합니다.
AR/VR 콘텐츠를 화면에 그리는 방법은 다루지 않습니다. WebXR Device API는 이미지 렌더링 기능을 제공하지 않습니다. 질문자님이 결정하실 문제입니다. 그리기는 WebGL API를 사용하여 실행됩니다. 야망이 있다면 가능합니다. 하지만 프레임워크를 사용하는 것이 좋습니다. 몰입형 웹 샘플은 데모 전용으로 만든 Cottontail을 사용합니다. Three.js는 5월부터 WebXR을 지원했습니다. A-Frame에 대해서는 들어본 적이 없습니다.
앱 시작 및 실행
기본 프로세스는 다음과 같습니다.
- XR 기기를 요청합니다.
- 사용 가능한 경우 XR 세션을 요청합니다. 사용자가 휴대전화를 헤드셋에 착용하도록 하려면 이를 몰입형 세션이라고 하며 들어가려면 사용자 동작이 필요합니다.
- 세션을 사용하여 초당 60개의 이미지 프레임을 제공하는 렌더링 루프를 실행합니다. 각 프레임에서 화면에 적절한 콘텐츠를 그립니다.
- 사용자가 종료를 결정할 때까지 렌더링 루프를 실행합니다.
- XR 세션을 종료합니다.
좀 더 자세히 살펴보고 코드를 포함해 보겠습니다. 지금 보여드릴 내용에서는 앱을 실행할 수 없습니다. 하지만 이는 대략적인 개념을 제공하기 위한 예시일 뿐입니다.
XR 기기 요청
여기에서 표준 기능 감지 코드를 확인할 수 있습니다. checkForXR()
와 같은 함수에 이를 래핑할 수 있습니다.
몰입형 세션을 사용하지 않는 경우 기능 광고 및 사용자 동작 가져오기를 건너뛰고 세션 요청으로 바로 이동할 수 있습니다. 몰입형 세션은 헤드셋이 필요한 세션입니다. 몰입형이 아닌 세션은 기기 화면에 콘텐츠를 표시하기만 합니다. 전자는 가상 현실이나 증강 현실을 언급할 때 대부분의 사람들이 떠올리는 것입니다. 후자를 '매직 윈도우'라고도 합니다.
if (navigator.xr) {
navigator.xr.requestDevice()
.then(xrDevice => {
// Advertise the AR/VR functionality to get a user gesture.
})
.catch(err => {
if (err.name === 'NotFoundError') {
// No XRDevices available.
console.error('No XR devices available:', err);
} else {
// An error occurred while requesting an XRDevice.
console.error('Requesting XR device failed:', err);
}
})
} else{
console.log("This browser does not support the WebXR API.");
}
XR 세션 요청
이제 기기와 사용자 동작이 있으므로 세션을 가져와야 합니다. 세션을 만들려면 브라우저에 그릴 캔버스가 필요합니다.
xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
// The immersive option is optional for non-immersive sessions; the value
// defaults to false.
immersive: false,
outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Use a WebGL context as a base layer.
xrSession.baseLayer = new XRWebGLLayer(session, gl);
// Start the render loop
})
렌더링 루프 실행
이 단계의 코드는 약간 복잡합니다. 이 문제를 해결하기 위해 몇 가지 단어를 알려드리겠습니다. 최종 코드를 살펴보려면 건너뛰어 빠르게 살펴본 다음 다시 돌아와 전체 설명을 확인하세요. 추론할 수 없는 부분이 많습니다.
렌더링 루프의 기본 프로세스는 다음과 같습니다.
- 애니메이션 프레임을 요청합니다.
- 기기의 위치를 쿼리합니다.
- 기기의 위치에 따라 기기 위치에 콘텐츠를 그립니다.
- 입력 장치에 필요한 작업을 실행합니다.
- 사용자가 종료할 때까지 초당 60번 반복합니다.
프레젠테이션 프레임 요청
'프레임'이라는 단어는 Web XR 컨텍스트에서 여러 가지 의미가 있습니다. 첫 번째는 기준 프레임으로, 이는 좌표계의 원점이 어디에서 계산되는지, 기기가 움직일 때 원점에 어떤 일이 일어나는지를 정의합니다. (사용자가 이동할 때 뷰가 동일하게 유지되나요? 아니면 실제와 같이 이동하나요?)
두 번째 유형의 프레임은 XRFrame
객체로 표시되는 프레젠테이션 프레임입니다. 이 객체에는 AR/VR 장면의 단일 프레임을 기기에 렌더링하는 데 필요한 정보가 포함됩니다. 프레젠테이션 프레임은 requestAnimationFrame()
를 호출하여 검색되므로 약간 혼란스러울 수 있습니다.
이렇게 하면 window.requestAnimationFrame()
와 호환됩니다.
내용을 더 전달하기 전에 코드를 알려 드리겠습니다. 아래 샘플은 렌더링 루프가 시작되고 유지되는 방식을 보여줍니다. '프레임'이라는 단어가 이중으로 사용된 것을 볼 수 있습니다. requestAnimationFrame()
에 대한 재귀 호출을 확인합니다. 이 함수는 초당 60번 호출됩니다.
xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
// The time argument is for future use and not implemented at this time.
// Process the frame.
xrFrame.session.requestAnimationFrame(onFrame);
}
});
포즈
화면에 아무것도 그리기 전에 디스플레이 기기가 가리키는 위치를 알아야 하며 화면에 액세스해야 합니다. 일반적으로 AR/VR에서 사물의 위치와 방향을 포즈라고 합니다. 시청자와 입력 장치 모두 자세를 갖습니다. 입력 장치는 나중에 다룹니다. 뷰어 및 입력 기기 자세는 모두 열 주요 순서로 Float32Array
에 저장된 4x4 행렬로 정의됩니다. 현재 애니메이션 프레임 객체에서 XRFrame.getDevicePose()
을 호출하여 시청자의 포즈를 가져옵니다.
항상 포즈가 다시 표시되는지 테스트하세요. 문제가 발생하면 화면에 그리지 않는 것이 좋습니다.
let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
// Draw something to the screen.
}
조회수
포즈를 확인한 후에는 무언가를 그려야 합니다. 그리는 객체를 뷰 (XRView
)라고 하며 여기서 세션 유형이 중요합니다. 뷰는 XRFrame
객체에서 배열로 검색됩니다. 비몰입형 세션에 있는 경우 배열에는 하나의 뷰가 있습니다. 몰입형 세션에 있는 경우
배열에는 각 눈에 하나씩 두 개가 있습니다.
for (let view of xrFrame.views) {
// Draw something to the screen.
}
이는 WebXR과 다른 몰입형 시스템의 중요한 차이점입니다. 하나의 뷰를 반복하는 것이 무의미해 보일 수 있지만, 이렇게 하면 다양한 기기에 단일 렌더링 경로를 사용할 수 있습니다.
전체 렌더링 루프
이 모든 것을 종합하면 아래 코드가 됩니다. 입력 장치의 자리표시자를 남겨두었습니다. 이 내용은 이후 섹션에서 다룹니다.
xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
// The time argument is for future use and not implemented at this time.
let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
for (let view of xrFrame.views) {
// Draw something to the screen.
}
}
// Input device code will go here.
frame.session.requestAnimationFrame(onFrame);
}
}
XR 세션 종료
XR 세션은 XRSession.end()
호출을 통해 자체 코드로 종료하는 등 여러 가지 이유로 종료될 수 있습니다. 헤드셋의 연결이 끊어졌거나 다른 애플리케이션에서 헤드셋을 제어하는 경우도 있습니다. 따라서 애플리케이션이 종료 이벤트를 모니터링해야 하며, 종료 이벤트가 발생하면 세션 및 렌더기 객체를 삭제해야 합니다. 종료된 XR 세션은 다시 시작할 수 없습니다.
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Create a WebGL layer and initialize the render loop.
xrSession.addEventListener('end', onSessionEnd);
});
// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
xrSession = null;
// Ending the session stops executing callbacks passed to the XRSession's
// requestAnimationFrame(). To continue rendering, use the window's
// requestAnimationFrame() function.
window.requestAnimationFrame(onDrawFrame);
}
상호작용은 어떻게 작동하나요?
애플리케이션 전체 기간과 마찬가지로 AR 또는 VR에서 객체와 상호작용하는 방법을 간단히 살펴보겠습니다.
WebXR Device API는 사용자 입력에 '포인트 앤 클릭' 접근 방식을 채택합니다. 이 접근 방식을 사용하면 모든 입력 소스에 입력 기기가 가리키는 위치를 나타내는 포인터 광선과 항목이 선택된 시점을 나타내는 이벤트가 있습니다.
앱이 포인터 광선을 그리고 포인터가 가리키는 위치를 표시합니다. 사용자가 입력 기기를 클릭하면 이벤트(특히 select
, selectStart
, selectEnd
)가 발생합니다. 앱은 클릭된 항목을 확인하고 적절하게 응답합니다.
입력 장치 및 포인터 광선
사용자에게 포인터 광선은 컨트롤러와 사용자가 가리키는 대상 사이의 희미한 선일 뿐입니다. 하지만 앱에서 그려야 합니다. 즉, 입력 기기의 포즈를 가져와 해당 위치에서 AR/VR 공간의 객체로 선을 그리는 것을 의미합니다. 이 프로세스는 대략 다음과 같습니다.
let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
if (!inputPose) {
continue;
}
if (inputPose.gripMatrix) {
// Render a virtual version of the input device
// at the correct position and orientation.
}
if (inputPose.pointerMatrix) {
// Draw a ray from the gripMatrix to the pointerMatrix.
}
}
이는 Immersive Web Community Group에서 제공하는 입력 추적 샘플의 축소된 버전입니다. 프레임 렌더링과 마찬가지로 포인터 광선과 기기를 그리는 것은 개발자에게 달려 있습니다. 앞서 언급했듯이 이 코드는 렌더링 루프의 일부로 실행되어야 합니다.
가상 공간에서 항목 선택
AR/VR에서는 사물을 가리키는 것만으로는 별로 쓸모가 없습니다. 유용한 작업을 하려면
사용자는 원하는 것을 선택할 수 있어야 합니다 WebXR Device API는 사용자 상호작용에 응답하기 위한 세 가지 이벤트(select
, selectStart
, selectEnd
)를 제공합니다. 예상치 못한 버그가 있습니다. 입력 장치가 클릭되었다고만 알려줍니다. 환경에서 클릭된 항목을 알려주지 않습니다. 이벤트 핸들러는 XRSession
객체에 추가되며 사용 가능해지는 즉시 추가해야 합니다.
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Create a WebGL layer and initialize the render loop.
xrSession.addEventListener('selectstart', onSelectStart);
xrSession.addEventListener('selectend', onSelectEnd);
xrSession.addEventListener('select', onSelect);
});
이 코드는 더 많은 컨텍스트를 원하는 경우를 위해 입력 선택 예를 기반으로 합니다.
클릭된 항목을 파악하려면 포즈를 사용합니다. (놀라셨나요? 아닌 것 같았습니다.) 세부정보는 앱 또는 사용 중인 프레임워크에 따라 다르므로 이 도움말의 범위를 벗어납니다. Cottontail의 접근 방식은 입력 선택 예시를 참고하세요.
function onSelect(ev) {
let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
if (!inputPose) {
return;
}
if (inputPose.pointerMatrix) {
// Figure out what was clicked and respond.
}
}
결론: 향후 계획
앞서 언급했듯이 증강 현실은 Chrome 69 (2018년 6월 카나리아 배포 예정)에서 제공될 것으로 예상됩니다. 그럼에도 불구하고 지금까지 제공된 기능을 사용해 보시기 바랍니다. 더 나은 기능을 제공하기 위해 의견이 필요합니다. ChromeStatus.com에서 WebXR 히트 테스트를 확인하여 진행 상황을 추적하세요. WebXR 앵커를 따라 포즈 추적을 개선할 수도 있습니다.