1. 소개
가상현실(VR) 및 증강현실(AR) 애플리케이션을 가능하게 하는 하드웨어가 이제 소비자들에게 널리 제공되고 있으며, 이는 새로운 기회와 도전을 동시에 제공하는 몰입형 컴퓨팅 플랫폼을 제공합니다. 몰입형 하드웨어와 직접 상호작용할 수 있는 능력은 웹이 이 환경에서 일급 시민으로서 제대로 작동하도록 보장하는 데 필수적입니다.
몰입형 컴퓨팅은 수용할 만한 경험을 제공하기 위해 고정밀, 저지연 통신에 대한 엄격한 요구사항을 도입합니다. 이는 또한 웹과 같은 플랫폼에 고유한 보안 문제도 가져옵니다. WebXR 디바이스 API는 다양한 하드웨어 폼팩터에서 웹 개발자가 몰입감 있고, 편안하며, 안전한 애플리케이션을 만들 수 있도록 필요한 인터페이스를 제공합니다.
RelativeOrientationSensor
및 AbsoluteOrientationSensor
와 같은 다른 웹 인터페이스는 일부 기기에서 입력을 받아 제한적인 상황에서 WebXR 디바이스 API를 폴리필하는 데 재활용될 수 있습니다. 그러나 이러한 인터페이스는 6DoF 트래킹, 헤드셋 주변기기로의 출력, 또는 트래킹 입력 디바이스와 같은
고급 몰입형 경험의 여러 기능을 지원할 수 없습니다.
1.1. 용어
이 문서에서는 XR이라는 약어를 가상현실, 증강현실 및 기타 관련 기술을 위한 하드웨어, 애플리케이션, 기법 전체를 일컫는 말로 사용합니다. 예시는 다음과 같으나 이에 국한되지 않습니다:
-
불투명, 투명, 또는 비디오 패스스루를 사용하는 헤드 마운트 디스플레이
-
위치 추적이 가능한 모바일 기기
-
헤드 트래킹 기능이 있는 고정형 디스플레이
이들 사이의 중요한 공통점은 모두 공간 트래킹 기능을 제공하여 가상 콘텐츠의 시점을 시뮬레이션할 수 있다는 점입니다.
"XR 디바이스", "XR 애플리케이션" 등의 용어는 일반적으로 위에 언급한 모든 경우에 적용됩니다. 이 문서의 일부 내용이 특정 기기 하위 집합에만 적용되는 경우, 해당 부분에서 명확히 표시됩니다.
3DoF 및 6DoF라는 용어는 이 문서 전반에서 XR 디바이스의 트래킹 능력을 설명하는 데 사용됩니다.
-
3DoF 디바이스는 "Three Degrees of Freedom"의 약자로, 회전 운동만 추적할 수 있는 기기입니다. 이는 트래킹에 오로지 가속도계와 자이로스코프 데이터를 사용하는 기기에서 일반적입니다. 3DoF 디바이스는 사용자의 평행 이동(이동)을 감지하지 못하지만, 목이나 팔의 움직임 모델링을 통해 이동을 추정하는 알고리즘을 사용할 수 있습니다.
-
6DoF 디바이스는 "Six Degrees of Freedom"의 약자로, 회전과 이동을 모두 추적할 수 있어 공간 내에서의 1:1 정밀 트래킹이 가능합니다. 이는 일반적으로 사용자의 환경에 대한 어느 정도의 이해를 필요로 합니다. 이러한 환경 인식은 트래킹되는 기기 자체의 센서(예: 카메라나 깊이 센서)를 활용하는 inside-out 트래킹이나, 사용자의 환경에 배치된 외부 기기(카메라 또는 광원 등)를 기준점으로 사용하는 outside-in 트래킹을 통해 달성될 수 있습니다. XR 디바이스는 이를 통해 자신의 위치를 파악합니다.
1.2. 애플리케이션 흐름
WebXR 디바이스 API를 사용하는 대부분의 애플리케이션은 다음과 같은 순서를 따릅니다:
-
원하는 유형의 XR 콘텐츠가 하드웨어와 UA에서 지원되는지 확인하기 위해
navigator.xr.isSessionSupported()
를 쿼리합니다. -
지원된다면, 사용자에게 XR 콘텐츠를 알립니다.
-
창이 일시적 활성화 상태가 되기를 기다립니다. 이는 사용자가 페이지의 버튼을 클릭하여 XR 콘텐츠를 보려 한다는 의사를 표시하는 경우가 일반적입니다.
-
사용자 활성화 이벤트 내에서
XRSession
을navigator.xr.requestSession()
으로 요청합니다. -
XRSession
요청이 성공하면, 이를 통해 프레임 루프를 실행하여 XR 입력에 반응하고 XR 디바이스에 표시할 이미지를 생성합니다.
2. 모델
2.1. XR 디바이스
XR 디바이스는 사용자에게 몰입형 콘텐츠를 제공할 수 있는 물리적 하드웨어 유닛입니다. 콘텐츠는 시각, 청각, 햅틱 또는 기타 감각 출력을 통해 사용자의 환경의 다양한 측면을 시뮬레이션하거나 보강하면 "몰입형"이라고 간주됩니다. 대부분의 경우 사용자의 공간 내 움직임을 추적하고, 사용자의 움직임에 동기화된 출력을 생성하는 것을 포함합니다. 데스크톱 클라이언트에서는 주로 헤드셋 주변기기를 의미합니다. 모바일 클라이언트에서는 뷰어 하네스와 함께 모바일 기기 자체를 의미할 수 있습니다. 스테레오 표시 기능이 없지만 더 발전된 트래킹 기능을 가진 장치를 의미할 수도 있습니다.
XR 디바이스는 지원 모드 목록(리스트 형태의 문자열 리스트) 을 가지며, 내포하는 값들은 해당 XR 디바이스가 지원하는 XRSessionMode
열거값입니다.
각 XR 디바이스는 자신의 지원 모드 목록에 있는 각 XRSessionMode
에
대해 허용된 기능 집합(순서 있는 집합의 기능 디스크립터)을 가지며, 반드시
처음에는 빈 집합이어야 합니다.
유저 에이전트는 몰입형 XR 디바이스 목록(리스트 형태의 XR 디바이스)을 가지며, 반드시 처음에는 빈 리스트여야 합니다.
유저 에이전트는 몰입형
XR 디바이스(null
또는 XR
디바이스)을 가지며, 이는 처음에는 null
이고 몰입형 XR 디바이스 목록 중 활성 XR 디바이스를 나타냅니다. 이 객체는 별도의 스레드에서 비동기적으로
갱신될 수 있습니다.
유저 에이전트는 기본 인라인 XR 디바이스를 반드시 가져야 하며, 이는 XR 디바이스이고, 내포해야 하는 값은 "inline"
입니다.
기본 인라인 XR
디바이스는 어떤 포즈 정보도 제공해서는 안 되며, 포인터 이벤트로 생성된 XR 입력 소스 또는 이벤트 이외의 XR 입력 소스나 이벤트를 제공해서는 안 됩니다.
참고: 기본 인라인 XR 디바이스는 개발자의 편의를 위해 존재하며, 인라인 및 몰입형 콘텐츠 모두에 동일한 렌더링 및 입력 로직을 사용할 수 있도록 해줍니다. 기본 인라인 XR 디바이스는 페이지 내 다른 메커니즘(입력의 경우 포인터 이벤트 등)으로 이미 개발자에게 제공되는 정보 외에 별도의 정보를 노출하지 않으며, 단지 XR 중심의 형식으로 해당 값을 제공합니다.
유저 에이전트는 인라인 XR
디바이스를 반드시 가져야 하며, 이는 XR
디바이스이고, 내포해야 하는 값은 "inline"
입니다.
인라인 XR 디바이스는, 제공하는 트래킹
정보가 인라인 콘텐츠에 노출되기에 적절하다면 몰입형 XR 디바이스일 수 있고, 아니면 기본 인라인 XR 디바이스일 수 있습니다.
참고: 휴대폰에서는 인라인 XR 디바이스가 자이로스코프·가속도계 등 휴대폰 내부 센서에서 유도된 포즈 정보를 제공할 수 있습니다. 유사한 센서가 없는 데스크톱/노트북에서는 인라인 XR 디바이스가 포즈 정보를 제공할 수 없으므로 기본 인라인 XR 디바이스로 대체됩니다. 이미 XR 디바이스에서 실행 중인 경우 인라인 XR 디바이스는 동일한 디바이스가 되며, 여러 뷰를 지원할 수 있습니다. 기본 인라인 XR 디바이스가 노출하는 것 이상의 트래킹 또는 입력 기능을 제공하려면 반드시 사용자 동의가 필요합니다.
현재 몰입형 XR 디바이스 목록, 인라인 XR 디바이스, 몰입형 XR 디바이스의 값은 별도의 스레드에서 비동기적으로 갱신될 수 있습니다. 이 객체들은 병렬로 실행되지 않는 단계에서 직접 접근해서는 안 됩니다.
3. 초기화
3.1. navigator.xr
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute XRSystem xr ; };
xr
속성 getter는 반드시 해당 객체와 연결된 XRSystem
객체를 반환해야
합니다.
3.2. XRSystem
[SecureContext ,Exposed =Window ]interface :
XRSystem EventTarget { // MethodsPromise <boolean >isSessionSupported (XRSessionMode ); [
mode NewObject ]Promise <XRSession >requestSession (XRSessionMode ,
mode optional XRSessionInit = {}); // Events
options attribute EventHandler ondevicechange ; };
유저 에이전트는 XRSystem
객체를
Navigator
객체가 생성될 때 만들어 그 객체에 연관시켜야 합니다.
XRSystem
객체는 API의 진입점으로, 유저 에이전트에서 사용 가능한 XR 기능을 쿼리하고 XRSession
을 생성하여
XR 하드웨어와 통신을 시작하는 데 사용됩니다.
유저 에이전트는 시스템에 연결된 몰입형 XR 디바이스를 열거할 수 있어야 하며, 이때 사용 가능한 각 디바이스를 몰입형 XR 디바이스 목록에 넣어야 합니다. 이후 열거 요청 알고리즘은 반드시 캐시된 몰입형 XR 디바이스 목록을 재사용해야 합니다. 디바이스를 열거하는 과정에서 디바이스 트래킹을 초기화해서는 안 됩니다. 최초 열거 이후로 유저 에이전트는 디바이스 연결 및 연결 해제를 모니터링하며, 연결된 디바이스를 몰입형 XR 디바이스 목록에 추가하고, 연결 해제된 디바이스는 목록에서 제거해야 합니다.
몰입형 XR 디바이스 목록이 변경될 때마다 유저 에이전트는 다음 단계를 실행하여 몰입형 XR 디바이스를 선택해야 합니다:
-
oldDevice를 몰입형 XR 디바이스로 둡니다.
-
몰입형 XR 디바이스 목록이 빈 리스트라면, 몰입형 XR 디바이스를
null
로 설정합니다. -
몰입형 XR 디바이스 목록의 크기가 1이라면, 몰입형 XR 디바이스를 몰입형 XR 디바이스 목록[0]으로 설정합니다.
-
몰입형 XR 디바이스를 다음과 같이 설정합니다:
- 활성화된
XRSession
이 있고 몰입형 XR 디바이스 목록에 oldDevice가 포함되어 있으면: -
몰입형 XR 디바이스를 oldDevice로 설정합니다.
- 그 외:
-
몰입형 XR 디바이스를 유저 에이전트가 선택한 디바이스로 설정합니다.
- 활성화된
-
필요하다면 인라인 XR 디바이스를 몰입형 XR 디바이스로 갱신하거나, 그렇지 않으면 기본 인라인 XR 디바이스로 갱신할 수 있습니다.
-
기기가 처음 열거된 경우 또는 oldDevice가 몰입형 XR 디바이스와 같다면, 이 단계를 중단합니다.
-
작업을 큐에 추가하여 XR compatible 불리언 값을 모든
WebGLRenderingContextBase
인스턴스에 대해false
로 설정합니다. -
작업을 큐에 추가하여 이벤트를 발생시키는데, devicechange라는 이름의 이벤트를 관련 전역 객체의
navigator
의xr
에 발생시킵니다. -
작업을 큐에 추가하여 몰입형 XR 디바이스 또는 인라인 XR 디바이스의 변경에 영향을 받는 모든
XRPermissionStatus
객체에 대해 적절한change
이벤트를 발생시킵니다.
참고: 이 단계들은 반드시 병렬로 실행되어야 합니다.
참고: 몰입형 XR 디바이스 목록에 여러 디바이스가 있을 때 유저 에이전트는 원하는 기준으로 몰입형 XR 디바이스를 선택할 수 있습니다. 예를 들어, 유저 에이전트는 항상 목록의 첫 번째 항목을 선택하거나, 사용자가 디바이스 우선순위를 관리할 수 있도록 UI를 제공할 수 있습니다. 기본 디바이스 선택 알고리즘이 안정적이라면 여러 브라우징 세션에 걸쳐 동일한 디바이스가 선택될 것입니다.
유저 에이전트는 다음 단계를 실행하여 몰입형 XR 디바이스가 선택되었는지 확인할 수 있습니다:
-
몰입형 XR 디바이스가
null
이 아니면 몰입형 XR 디바이스를 반환하고, 이 단계를 중단합니다. -
몰입형 XR 디바이스를 열거합니다.
-
몰입형 XR 디바이스를 선택합니다.
-
몰입형 XR 디바이스를 반환합니다.
참고: 이 단계들은 반드시 병렬로 실행되어야 합니다.
ondevicechange
속성은 이벤트 핸들러 IDL 속성이며, devicechange 이벤트 타입에 해당합니다.
isSessionSupported(mode)
메서드는 지정된
mode가 유저 에이전트 및 디바이스에서 지원될 수 있는지 쿼리합니다.
이 메서드가 호출되면 다음 단계를 실행해야 합니다:
-
요청하는 문서의 origin이 "xr-spatial-tracking" permissions policy를 사용할 수 없다면, reject promise를 "
SecurityError
"DOMException
으로 하고 반환합니다. -
세션 mode가 지원되는지 다음과 같이 확인합니다:
- 유저 에이전트와 시스템이 절대 지원하지 않는 mode 세션이라면
-
resolve promise를
false
로 합니다. - 유저 에이전트와 시스템이 보통 지원하는 mode 세션이라면
-
여기서 유저 에이전트 문자열로 구별할 수 없는 모든 인스턴스가 동일한 결과를 내는 경우에 한해 promise를 resolve
true
로 할 수 있습니다. - 그 외의 경우
-
다음 단계를 병렬로 실행합니다:
-
device를 몰입형 XR 디바이스가 선택되었는지 확인의 결과로 설정합니다.
-
device가 null이면, resolve promise를
false
로 하고 이 단계를 중단합니다. -
device의 지원 모드 목록에 mode가 없다면, 작업을 큐에 추가하여 resolve promise를
false
로 하고 이 단계를 중단합니다. -
권한 요청을 강력한 기능 "xr-session-supported"에 대해
XRSessionSupportedPermissionDescriptor
및mode
값을 mode로 하여 요청합니다. 결과가"denied"
라면, 작업을 큐에 추가하여 resolve promise를false
로 하고 이 단계를 중단합니다. 자세한 정보는 핑거프린팅 고려사항을 참고하세요.
-
-
promise를 반환합니다.
참고: isSessionSupported()
의
목적은 유저 에이전트가 XRSession
을 생성할
수 있는 능력을 완벽하게 보고하는 것이 아니라, 주어진 모드 세션을 광고할지 여부를 페이지에 알리는 것입니다. 필요한 하드웨어/소프트웨어의 존재를 확인하더라도 일정 수준의
false-positive가 발생할 수 있습니다. (예: 하드웨어가 있더라도, 세션 요청 시점에 이미 다른 애플리케이션에 독점적으로 할당되어 있을 수 있습니다.)
대부분의 XR 콘텐츠 페이지는 문서 수명 주기 초기에 isSessionSupported()
를
호출할 것으로 예상됩니다. 따라서 isSessionSupported()
호출 시 모달 또는 침입성 UI 표시를 피해야 합니다. isSessionSupported()
는
디바이스 선택 UI를 트리거해서는 안 되며, 시스템에서 실행 중인 XR 애플리케이션을 방해해서도 안 되고, 시스템 트레이나 스토어 등 XR 관련 애플리케이션을 실행시켜서도 안 됩니다.
immersive-vr
세션이 지원되는지 확인합니다.
const supported= await navigator. xr. isSessionSupported( 'immersive-vr' ); if ( supported) { // 'immersive-vr' 세션을 지원할 수 있습니다. // 페이지에서 사용자에게 지원을 안내하세요. } else { // 'immersive-vr' 세션을 지원하지 않습니다. }
XRSystem
객체는 대기 중인 몰입형
세션 불리언(초기값 false
), 활성 몰입형 세션(초기값 null
), 인라인 세션 목록(초기값 빈 배열)을 가집니다.
requestSession(mode, options)
메서드는 가능한 경우 주어진 mode에 대한 XRSession
을
초기화하려 시도하며, 필요하다면 몰입형 모드로 진입합니다.
이 메서드가 호출되면 유저 에이전트는 다음 단계를 실행해야 합니다:
-
mode가 몰입형 세션 모드라면 immersive를
true
로, 아니면false
로 둡니다. -
세션 요청이 허용되는지 다음과 같이 확인합니다:
- immersive가
true
인 경우: -
-
몰입형 세션 요청이 허용되는지 global object에 대해 확인하고, 허용되지 않으면 reject promise를 "
SecurityError
"DOMException
으로 하고 반환합니다. -
대기 중인 몰입형 세션이
true
이거나 활성 몰입형 세션이null
이 아니면, reject promise를 "InvalidStateError
"DOMException
으로 하고 반환합니다. -
대기 중인 몰입형 세션을
true
로 설정합니다.
-
- 그 외:
-
인라인 세션 요청이 허용되는지 global object에 대해 확인하고, 허용되지 않으면 reject promise를 "
SecurityError
"DOMException
으로 하고 반환합니다.
- immersive가
-
다음 단계를 병렬로 실행합니다:
-
requiredFeatures를 options의
requiredFeatures
로 둡니다. -
optionalFeatures를 options의
optionalFeatures
로 둡니다. -
device를 현재 디바이스 얻기의 결과로 mode, requiredFeatures, optionalFeatures를 전달하여 설정합니다.
-
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
device가
null
이거나 device의 지원 모드 목록에 mode가 없다면, 다음 단계를 실행합니다:-
reject promise를 "
NotSupportedError
"DOMException
으로 합니다. -
immersive가
true
라면 대기 중인 몰입형 세션을false
로 설정합니다. -
이 단계를 중단합니다.
-
-
descriptor를
XRPermissionDescriptor
로 초기화하며, mode, requiredFeatures, optionalFeatures로 초기화합니다. -
status를
XRPermissionStatus
로, 초기값null
로 둡니다. -
xr 권한 요청을 descriptor, status로 실행합니다.
-
status의
state
가"denied"
라면, 다음 단계를 실행합니다:-
reject promise를 "
NotSupportedError
"DOMException
으로 합니다. -
immersive가
true
라면 대기 중인 몰입형 세션을false
로 설정합니다. -
이 단계를 중단합니다.
-
-
세션 초기화를 session, mode, granted, device로 실행합니다.
-
활성 몰입형 세션을 필요에 따라 다음과 같이 설정합니다:
- immersive가
true
인 경우: -
활성 몰입형 세션을 session으로, 대기 중인 몰입형 세션을
false
로 설정합니다. - 그 외:
-
session을 인라인 세션 목록에 추가합니다.
- immersive가
-
resolve promise를 session으로 합니다.
-
작업을 큐에 추가하여 다음 단계를 실행합니다:
참고: 이 단계는 초기inputsourceschange
이벤트가 초기 세션 resolve 이후 발생하도록 보장합니다.-
session의 promise resolved 플래그를
true
로 설정합니다. -
sources를 session에 연결된 기존 입력 소스로 둡니다.
-
sources가 비어있지 않으면 다음 단계를 실행합니다:
-
session의 활성 XR 입력 소스 목록을 sources로 설정합니다.
-
XRInputSourcesChangeEvent
의inputsourceschange
이벤트를 session에 대해added
를 sources로 하여 발생시킵니다.
-
-
-
-
-
promise를 반환합니다.
현재 디바이스
얻기는 XRSessionMode
mode, requiredFeatures, optionalFeatures에 대해 유저 에이전트가 다음 단계를 실행해야 합니다:
-
다음 중 하나로 device를 선택합니다:
- mode가 몰입형 세션 모드인 경우:
-
device를 몰입형 XR 디바이스가 선택되었는지 확인의 결과로 설정합니다.
- requiredFeatures 또는 optionalFeatures가 비어 있지 않다면:
-
device를 인라인 XR 디바이스로 설정합니다.
- 그 외:
-
device를 기본 인라인 XR 디바이스로 설정합니다.
-
device를 반환합니다.
참고: 이 단계들은 반드시 병렬로 실행되어야 합니다.
immersive-vr
XRSession
을
요청합니다.
const xrSession= await navigator. xr. requestSession( "immersive-vr" );
3.3. XRSessionMode
XRSessionMode
열거형은 XRSession
이 동작할
수 있는 모드를 정의합니다.
enum {
XRSessionMode "inline" ,"immersive-vr" ,"immersive-ar" };
-
inline
세션 모드는 세션의 출력이 HTML 문서 내의 요소로 표시됨을 의미합니다.inline
세션 콘텐츠는 반드시 모노(즉, 단일 view)로 표시되어야 합니다. viewer 트래킹을 허용할 수 있습니다. User agent는 반드시inline
세션 생성을 허용해야 합니다. -
immersive-vr
세션 모드는 세션의 출력이 독점 접근 권한을 가지고 몰입형 XR 디바이스 디스플레이에 표시되며, 콘텐츠가 사용자의 환경과 통합되는 것이 아님을 의미합니다. -
immersive-ar
세션 모드의 동작은 WebXR AR Module에서 정의되며, UA가 해당 모듈을 구현하지 않는 한 몰입형 XR 디바이스의 지원 모드 목록에 추가되어서는 안 됩니다.
이 문서에서 인라인 세션이라는 용어는
inline
세션과 동의어이며, 몰입형 세션이라는
용어는 immersive-vr
또는 immersive-ar
세션을 의미합니다.
몰입형 세션은 반드시 일정 수준의 viewer 트래킹을 제공해야 하며, 콘텐츠는 사용자 및/또는 주변 환경에
대해 올바른 크기로 표시되어야 합니다.
또한, 몰입형 세션은 반드시 독점 접근 권한을 몰입형 XR 디바이스에 받아야
하며, 몰입형 세션이
"visible"
상태일 때 HTML 문서는 몰입형 XR
디바이스의 디스플레이에 표시되지 않으며, 다른 소스의 콘텐츠도 독점 접근 권한을 갖지 않습니다. 독점 접근은 user agent가 자신의 UI를 오버레이하는 것을 막지는
않지만, 이 UI는 최소화되어야 합니다.
참고: UA는 접근성 또는 안전을 위해 guardian 경계, 장애물, 대체 입력 소스가 없을 때 사용자의 손 등의 콘텐츠를 오버레이할 수 있습니다.
참고: 향후 명세 또는 모듈에서 몰입형 세션의 정의에 추가 세션 모드를 포함시킬 수 있습니다.
참고: 독점 접근이 제공되는 방식의 예로는 가상현실 헤드셋에 표시되는 스테레오 콘텐츠가 있습니다.
참고: 예를 들어, 몰입형 세션에서 user agent 또는 운영체제가 렌더링된 콘텐츠 위에 알림을 표시하는 식의 오버레이 UI를 보여줄 수 있습니다.
참고: 몰입형 XR 디바이스의 디스플레이에서 몰입형 세션이 실행 중일 때 HTML 문서는 표시되지 않지만, 사용자가 자신의 컴퓨터에서 2D 브라우저로 몰입형 세션에 진입하는 경우와 같이 별도의 화면에는 표시될 수 있습니다.
3.4. 기능 종속성
XRSession
의 일부
기능은 여러 가지 이유로 보편적으로 제공되지 않을 수 있습니다. 그중 하나는 모든 XR 디바이스가 전체 기능 집합을 지원하지 않는다는 점입니다. 또 다른 고려사항은 일부 기능이 민감한 정보를 노출할 수
있으므로, 동작 전에 사용자 의도에 대한 명확한 신호가 필요할
수 있다는 점입니다.
기저 XR 플랫폼을 초기화하고 XRSession
을
생성했는데 애플리케이션이 올바르게 동작할 수 없다는 사실을 즉시 사용자에게 알리는 것은 좋지 않은 사용자 경험이므로, 개발자는 필수 기능을 XRSessionInit
딕셔너리를 requestSession()
에
전달하여 표시할 수 있습니다.
이 경우, 필수 기능 중 하나라도
디바이스의 한계나 사용자 의도에 대한 명확한 신호가 없는 경우
생성이 차단됩니다.
또한, 개발자는 더 뛰어난 디바이스에서 실행될 때 점진적으로 기능을 향상시키는 경험을 설계하는 것이 권장됩니다. 경험에 필수적이지는 않지만 사용할 수 있을 경우 활용할 선택적 기능도 XRSessionInit
딕셔너리에서 명시해야 필요한 경우 사용자 의도를 판단할 수
있습니다.
dictionary {
XRSessionInit sequence <DOMString >requiredFeatures ;sequence <DOMString >optionalFeatures ; };
requiredFeatures
배열에는 경험에 필요한 필수 기능이 들어 있습니다. 목록에
인식되지 않는 기능 디스크립터가
있으면 XRSession
이
생성되지 않습니다. requiredFeatures
배열에 있는 기능 중 XR
디바이스에서 지원하지 않거나, 필요한 경우 사용자
의도에 대한 명확한 신호를 받지 못한 기능이 있으면 XRSession
이
생성되지 않습니다.
optionalFeatures
배열에는 경험에 필요한 선택적 기능이 들어 있습니다. 목록에
인식되지 않는 기능 디스크립터가
있으면 해당 값은 무시됩니다.
optionalFeatures
배열에 있는 기능은 XR
디바이스에서 지원하고, 필요한 경우 사용자
의도가 명확하면 활성화되지만, 지원하지 않더라도 XRSession
생성이 차단되지는 않습니다.
기능 목록에 지정된 값이 다음 중 하나라면 유효한 기능 디스크립터로 간주합니다:
-
모든
XRReferenceSpaceType
열거값의 문자열 표현
향후 명세 개정과 추가 모듈이 허용 기능 디스크립터 목록을 확장할 수 있습니다.
참고: 기능에 추가 초기화가 필요한 경우, XRSessionInit
딕셔너리에 해당 기능을 위한 필드를 확장해야 합니다.
요청된 XRSessionMode
에 따라 특정 기능 디스크립터가
기본적으로 requiredFeatures
또는 optionalFeatures
목록에 추가됩니다. 아래 표는 각 세션 타입과 기능 목록에 연관된 기본 기능을 설명합니다:
기능 | 세션 | 목록 |
---|---|---|
"viewer"
| 인라인 세션 및 몰입형 세션 | requiredFeatures
|
"local"
| 몰입형 세션 | requiredFeatures
|
requiredFeatures
및 optionalFeatures
의 기능 디스크립터 전체 목록을
요청된 기능이라고 하며, 이는
XRSession
에
대해 적용됩니다.
일부 기능 디스크립터는 요청된 기능 목록에 포함되어 있을 때 권한 정책 및/또는 사용자 의도가 명확하게 확인되어야 활성화됩니다(명시적 동의 또는 묵시적 동의). 아래 표는 활성화 전에 충족되어야 하는 기능 요구사항을 설명합니다:
기능 | 권한 정책 필요 | 동의 필요 |
---|---|---|
"local"
| "xr-spatial-tracking" | 인라인 세션 은 동의 필요 |
"local-floor"
| "xr-spatial-tracking" | 항상 동의 필요 |
"bounded-floor"
| "xr-spatial-tracking" | 항상 동의 필요 |
"unbounded"
| "xr-spatial-tracking" | 항상 동의 필요 |
참고: "local"
은 몰입형 세션의 요청된 기능에 항상 기본 기능으로 포함되며, 따라서 모든 몰입형 세션은 반드시 명시적 동의 또는 묵시적 동의를 받아야 합니다.
요청된 기능 은 XR 디바이스가 해당 기능을 지원할 수 있음을 전제로 세션에서만 활성화될 수 있습니다. 즉, XR 디바이스가 일부 설정에서 해당 기능을 지원함이 알려진 경우(현 설정에서 지원 여부가 아직 검증되지 않았더라도) 활성화가 가능합니다. 유저 에이전트는 더 일관된 사용자 경험을 위해 더 엄격한 제약을 적용할 수 있습니다.
참고: 예를 들어, 여러 VR 디바이스는 사용자가 이동할 수 있는 안전 경계를 구성하거나, 경계 없이
제자리 모드로 동작할 수 있습니다. 이런 기기는 "bounded-floor"
XRReferenceSpace
를
지원할 수 있는 것으로 간주되지만, 현재 안전 경계가 구성되어 있지 않아도 경험이 요구할 경우 사용자가 디바이스를 적절히 설정할 수 있다고 기대하기 때문입니다. 이는 유저 에이전트가 XR 디바이스를 완전히
초기화하거나 사용자의 환경을 인식할 때까지 기다리지 않고도 요청된 기능을 resolve할 수 있도록 허용합니다. 하지만, 세션 요청 시점에 안전 경계 상태를
추가 초기화 없이 알고 있다면, 안전 경계가 이미 구성되지 않은 경우 "bounded-floor"
기능을 거부할 수 있습니다.
4. 세션
4.1. XRSession
XR 하드웨어와의 모든 상호작용은 XRSession
객체를 통해 이루어지며, 이 객체는 requestSession()
을 XRSystem
객체에서 호출해야만 얻을 수 있습니다. 세션을 성공적으로 획득하면, 이를 사용해 뷰어 포즈 폴링
을
하거나, 사용자의 환경에 대한 정보를 쿼리하거나, 이미지를 사용자에게 표시할 수 있습니다.
유저 에이전트는 가능하다면 디바이스 트래킹이나 렌더링 기능을 XRSession을 획득하기 전까지 초기화하지 않아야 합니다. 이는 XR 시스템이 실제로 사용되지 않을 때 불필요하게 XR 시스템을 활성화해서 발생할 수 있는 배터리 소모 증가, 관련 유틸리티 앱이 노출되는 등 바람직하지 않은 부작용을 방지하기 위함입니다. 일부 XR 플랫폼은 트래킹 초기화 없이 하드웨어 존재를 감지할 수 있는 방법을 제공하지 않으므로, 이는 강한 권고 사항입니다.
enum {
XRVisibilityState "visible" ,"visible-blurred" ,"hidden" , }; [SecureContext ,Exposed =Window ]interface :
XRSession EventTarget { // Attributesreadonly attribute XRVisibilityState visibilityState ;readonly attribute float ?frameRate ;readonly attribute Float32Array ?supportedFrameRates ; [SameObject ]readonly attribute XRRenderState renderState ; [SameObject ]readonly attribute XRInputSourceArray inputSources ; [SameObject ]readonly attribute XRInputSourceArray trackedSources ;readonly attribute FrozenArray <DOMString >enabledFeatures ;readonly attribute boolean isSystemKeyboardSupported ; // Methodsundefined updateRenderState (optional XRRenderStateInit = {});
state Promise <undefined >updateTargetFrameRate (float ); [
rate NewObject ]Promise <XRReferenceSpace >requestReferenceSpace (XRReferenceSpaceType );
type unsigned long requestAnimationFrame (XRFrameRequestCallback );
callback undefined cancelAnimationFrame (unsigned long );
handle Promise <undefined >end (); // Eventsattribute EventHandler onend ;attribute EventHandler oninputsourceschange ;attribute EventHandler onselect ;attribute EventHandler onselectstart ;attribute EventHandler onselectend ;attribute EventHandler onsqueeze ;attribute EventHandler onsqueezestart ;attribute EventHandler onsqueezeend ;attribute EventHandler onvisibilitychange ;attribute EventHandler onframeratechange ; };
각 XRSession
은
mode를 가지며, 이는 XRSessionMode
값 중 하나입니다.
각 XRSession
은
애니메이션 프레임을 가지며, 이는 active가 false
, animationFrame이
true
, session
이
해당 XRSession
으로
초기화된 XRFrame
입니다.
각 XRSession
은
허용된 기능 집합을 가지며, 이는 해당 XRSession
에 부여된
기능 디스크립터에 해당하는 DOMString
의
집합입니다.
enabledFeatures
속성은 허용된 기능 집합의
기능을 DOMString
의
새 배열로 반환합니다.
isSystemKeyboardSupported
속성은 XRSystem
이 XRSession
이 활성
상태일 때 시스템 키보드를 표시할 수 있는지 나타냅니다. isSystemKeyboardSupported
가 true
이면, 오버레이 키보드를 트리거하는 Web API(예: focus)가 시스템 키보드를 표시합니다.
XRSession
은
키보드가 표시되는 동안 해당 visibility state를 "visible-blurred"
로
설정해야 합니다.
세션 초기화를 위해 session, mode, granted, device를 받아 다음 단계를 유저 에이전트가 실행해야 합니다:
-
session의 mode를 mode로 설정합니다.
-
session의 XR 디바이스를 device로 설정합니다.
-
session의 허용된 기능 집합을 granted로 설정합니다.
-
렌더 상태 초기화를 실행합니다.
-
유저 에이전트의 다른 기능에서 이미 초기화하지 않았다면, 플랫폼 특화 단계(트래킹 및 렌더링 초기화, 필요한 경우 사용자를 위한 안내 포함)를 수행합니다.
참고: 일부 기기는 활성화를 위해 추가 사용자 안내가 필요할 수 있습니다. 예를 들어, 휴대폰 기반 헤드셋에서 몰입형 모드로 진입하려면 폰을 헤드셋에 꽂아야 하고, 데스크톱 브라우저에서 외부 헤드셋에 연결되어 있다면 헤드셋을 착용해야 합니다. 이러한 안내를 표시하는 책임은 저자가 아니라 유저 에이전트에 있습니다.
여러 상황에서 세션이 종료될 수
있으며, 이는 영구적이고 되돌릴 수 없습니다. 한 번 세션이 종료되면 XR 디바이스의 트래킹 및 렌더링 기능에 다시 접근하려면 새 세션을 요청해야 합니다. 각 XRSession
은
ended 불리언을 가지며, 초기값은 false
이고, 세션이 종료되었는지를 나타냅니다.
XRSession
session이 종료되면 다음 단계를 실행합니다:
-
session의 ended 값을
true
로 설정합니다. -
session을 인라인 세션 목록에서 제거합니다.
-
session이 반환한 미해결 promise를
InvalidStateError
로 Reject합니다(end()
가 반환한 promise 제외). -
유저 에이전트의 다른 기능이 더 이상 사용하지 않는다면, 디바이스의 트래킹 및 렌더링 기능을 종료하기 위한 플랫폼 특화 단계를 반드시 수행해야 합니다. 이 단계에는 반드시 다음이 포함됩니다:
-
작업 큐에 추가하여
XRSessionEvent
타입의end
이벤트를 session에 발생시킵니다.
end()
메서드는 세션을 수동으로 종료할 수 있는 방법을 제공합니다. 호출되면 다음 단계를 반드시
실행해야 합니다:
각 XRSession
은
활성 렌더 상태(새 XRRenderState
)와
대기 중 렌더 상태(초기값
null
인 XRRenderState
)를
가집니다.
renderState
속성은 해당 XRSession
의 활성 렌더 상태를 반환합니다.
각 XRSession
은
최소 인라인
시야각과 최대 인라인 시야각을 가지며, 라디안 단위로 정의됩니다. 값은 반드시 유저 에이전트에 의해 결정되며
0
이상 PI
이하여야 합니다.
각 XRSession
은
최소 근거리 클리핑 평면과
최대 원거리 클리핑 평면을
가지며, 미터 단위로 정의됩니다. 값은 반드시 유저 에이전트에 의해 결정되어야 하며 음수가 아니어야 합니다. 최소 근거리 클리핑 평면은 0.1
미만이어야 하며, 최대 원거리
클리핑 평면은 1000.0
이상(무한대일 수도 있음)이 권장됩니다.
유저 에이전트가 XRSession
session과 XRRenderStateInit
newState로 대기 중 레이어 상태 업데이트를 할 때 다음 단계를 실행해야 합니다:
-
newState의
layers
값이null
이 아니면,NotSupportedError
를 throw 합니다.
참고: WebXR layers module에서 이 알고리즘에 대한 새로운 의미를 도입할 예정입니다.
유저 에이전트가 XRSession
session에 rate로 기본 프레임률 적용을 하고자 할 때 다음 단계를 반드시 실행해야 합니다:
-
rate가 session의 내부 기본 프레임률과 같으면 이 단계를 중단합니다.
-
session의 ended 값이
true
이면 이 단계를 중단합니다. -
session의 내부 기본 프레임률을 rate로 설정합니다.
-
XRSessionEvent
타입의frameratechange
이벤트를 session에 발생시킵니다.
updateTargetFrameRate(rate)
메서드는 목표 프레임률
rate를 XRSession
에
전달합니다.
이 메서드가 호출되면 유저 에이전트는 다음 단계를 실행해야 합니다:
-
session을 this로 둡니다.
-
session에 내부 기본 프레임률이 없으면, reject promise를 "
InvalidStateError
"DOMException
으로 하고 반환합니다. -
session의 ended 값이
true
이면, reject promise를 "InvalidStateError
"DOMException
으로 하고 반환합니다. -
rate가
supportedFrameRates
에 포함되지 않으면, reject promise를 "TypeError
"DOMException
으로 하고 반환합니다. -
session의 내부 목표 프레임률을 rate로 설정합니다.
-
작업 큐에 추가하여 다음 단계를 실행합니다:
-
XR 컴포지터는 rate를 사용해 새로운 디스플레이 프레임률 및/또는 기본 프레임률을 계산할 수 있습니다.
-
newrate를 새 기본 프레임률로 둡니다.
-
작업 큐에 추가하여 다음 단계를 실행합니다:
-
기본 프레임률 적용을 newrate, session으로 실행합니다.
-
resolve promise.
-
-
promise를 반환합니다.
XR 컴포지터가 어떤 이유로든 기본 프레임률을 변경하면(예:
"visible-blurred"
이벤트 중), 원인 이벤트가 끝난 후에는 내부 목표 프레임률을 사용해야 합니다.
updateRenderState(newState)
메서드는 활성 렌더 상태에
다음 프레임에 적용될 업데이트를 큐에 올립니다. 이 메서드에 전달된 XRRenderStateInit
newState의 설정되지 않은 필드는 변경되지 않습니다.
이 메서드가 호출되면 유저 에이전트는 다음 단계를 실행해야 합니다:
-
session을 this로 둡니다.
-
session의 ended 값이
true
이면,InvalidStateError
를 throw 하고 단계를 중단합니다. -
newState의
baseLayer
가 session이 아닌XRSession
으로 생성됐다면InvalidStateError
를 throw 하고 단계를 중단합니다. -
newState의
inlineVerticalFieldOfView
가 설정되어 있고 session이 몰입형 세션이면,InvalidStateError
를 throw 하고 단계를 중단합니다. -
newState의
depthNear
,depthFar
,inlineVerticalFieldOfView
,baseLayer
,layers
중 어떤 것도 설정되어 있지 않다면, 단계를 중단합니다. -
대기 중 레이어 상태 업데이트를 session, newState로 실행합니다.
-
activeState를 session의 활성 렌더 상태로 둡니다.
-
session의 대기 중 렌더 상태가
null
이면, activeState의 복사본으로 설정합니다. -
newState의
passthroughFullyObscured
값이 설정되어 있으면, session의 대기 중 렌더 상태의passthroughFullyObscured
를 newState의 해당 값으로 설정합니다. -
newState의
depthNear
값이 설정되어 있으면 session의 대기 중 렌더 상태의depthNear
를 newState의 해당 값으로 설정합니다. -
newState의
depthFar
값이 설정되어 있으면 session의 대기 중 렌더 상태의depthFar
를 newState의 해당 값으로 설정합니다. -
newState의
inlineVerticalFieldOfView
값이 설정되어 있으면 session의 대기 중 렌더 상태의inlineVerticalFieldOfView
를 newState의 해당 값으로 설정합니다. -
newState의
baseLayer
값이 설정되어 있으면 session의 대기 중 렌더 상태의baseLayer
를 newState의 해당 값으로 설정합니다.
요청 시, XRSession
session은 반드시 다음 단계를 실행하여 대기 중 렌더 상태를 적용해야 합니다:
-
activeState를 session의 활성 렌더 상태로 둡니다.
-
newState를 session의 대기 중 렌더 상태로 둡니다.
-
session의 대기 중 렌더 상태를
null
로 설정합니다. -
oldBaseLayer를 activeState의
baseLayer
로 둡니다. -
oldLayers를 activeState의
layers
로 둡니다. -
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
activeState를 newState로 설정합니다.
-
oldBaseLayer가 activeState의
baseLayer
와 다르거나, oldLayers가 activeState의layers
와 다르거나, 또는 어떤 레이어의 크기가 변경되었다면, 뷰포트 업데이트를 session에 대해 실행합니다. -
activeState의
inlineVerticalFieldOfView
가 session의 최소 인라인 시야각보다 작으면, activeState의inlineVerticalFieldOfView
를 session의 최소 인라인 시야각으로 설정합니다. -
activeState의
inlineVerticalFieldOfView
가 session의 최대 인라인 시야각보다 크면, activeState의inlineVerticalFieldOfView
를 session의 최대 인라인 시야각으로 설정합니다. -
activeState의
depthNear
가 session의 최소 근거리 클리핑 평면보다 작으면, activeState의depthNear
를 session의 최소 근거리 클리핑 평면으로 설정합니다. -
activeState의
depthFar
가 session의 최대 원거리 클리핑 평면보다 크면, activeState의depthFar
를 session의 최대 원거리 클리핑 평면으로 설정합니다. -
baseLayer를 activeState의
baseLayer
로 둡니다. -
activeState의 composition enabled와 output canvas를 다음과 같이 설정합니다:
- session의 mode가
"inline"
이고, baseLayer가XRWebGLLayer
의 인스턴스이며 composition enabled가false
인 경우: -
activeState의 composition enabled 불리언을
false
로 설정합니다.activeState의 output canvas를 baseLayer의 context의
canvas
로 설정합니다. - 그 외의 경우:
-
activeState의 composition enabled 불리언을
true
로 설정합니다.activeState의 output canvas를
null
로 설정합니다.
- session의 mode가
-
requestReferenceSpace(type)
메서드는 가능하다면 주어진 type의 새로운 XRReferenceSpace
를 생성합니다.
이 메서드가 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:
-
다음 단계를 병렬로 실행합니다:
-
reference space is supported를 type과 session에 대해 실행한 결과가
false
이면, 작업을 큐에 추가하여 reject promise를NotSupportedError
로 하고 이 단계를 중단합니다. -
type 타입의 reference space를 트래킹하기 위해 필요한 플랫폼 리소스를 셋업합니다.
유저 에이전트는 해당 reference space의 트래킹이 설정될 때까지 기다릴 필요 없이requestReferenceSpace()
를 resolve할 수 있습니다. 세션이 초기 트래킹을 시도하는 동안getViewerPose()
가null
을 반환해도 괜찮으며, 콘텐츠는 이 시간을 스플래시 화면 등으로 활용할 수 있습니다. type이"bounded-floor"
이고 경계가 아직 설정되지 않았다면, 유저 에이전트는 경계를 작은 초기 영역으로 두고 나중에reset
이벤트로 갱신할 수 있습니다. -
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
reference space 생성을 type, session으로 하여 referenceSpace로 둡니다.
-
resolve promise를 referenceSpace로 합니다.
-
-
promise를 반환합니다.
각 XRSession
은
활성 XR 입력 소스
목록(리스트
형태의 XRInputSource
)
과 활성 XR 추적
소스 목록(리스트 형태의 XRInputSource
)
을 가지며, 둘 다 반드시 처음에는 빈 리스트여야 합니다.
각 XRSession
은
XR 디바이스를 가지며, 이는 초기화 시 지정된 XR 디바이스입니다.
inputSources
속성은 해당 XRSession
의 활성 XR 입력 소스 목록을 반환합니다.
trackedSources
속성은 해당 XRSession
의 활성 XR 추적 소스 목록을 반환합니다.
유저 에이전트는 해당 XR 디바이스에 연결된 모든 XR 입력 소스를 모니터링해야 하며, XR 입력 소스가 추가, 제거, 변경될 때를 감지해야 합니다.
각 XRSession
은
promise resolved 플래그를 가지며, 초기값은 false
입니다.
참고: 이 플래그의 목적은 입력 소스 추가, 입력 소스 제거, 입력 소스 변경 알고리즘이 실제로 사용자 코드가 이벤트 리스너를 부착할 기회를 얻기 전에는 실행되지 않도록 보장하는 것입니다. 구현체는 세션 resolve 후에 입력 소스 변경 리스닝을 시작하는 방식으로 동작한다면 이 플래그가 필요하지 않을 수도 있습니다.
새로운 XR 입력 소스가 사용 가능해질 때 XRSession
session에 대해 유저 에이전트는 다음 단계를 실행해야 합니다:
-
session의 promise resolved 플래그가 설정되지 않았다면, 이 단계를 중단합니다.
-
added primary sources를 새로운 리스트로 둡니다.
-
added tracked sources를 새로운 리스트로 둡니다.
-
각 새로운 XR 입력 소스에 대해:
-
inputSource를 이
XRSession
의 관련 realm에서 새XRInputSource
로 두고, 다음 단계를 실행합니다:- inputSource가 기본 입력 소스인 경우:
-
inputSource를 added primary sources에 추가합니다.
- 그 외의 경우:
-
inputSource를 added tracked sources에 추가합니다.
-
-
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
확장 session의 활성 XR 입력 소스 목록 에 added primary sources를 추가합니다.
-
added primary sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의inputsourceschange
이벤트를 session에 대해added
를 added primary sources로 하여 발생시킵니다. -
확장 session의 활성 XR 추적 소스 목록에 added tracked sources를 추가합니다.
-
added tracked sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의trackedsourceschange
이벤트를 session에 대해added
를 added tracked sources로 하여 발생시킵니다.
-
이전에 추가된 XR 입력 소스가 더 이상 사용
가능하지 않을 때 XRSession
session에 대해, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
session의 promise resolved 플래그가 설정되어 있지 않으면, 이 단계를 중단합니다.
-
removed primary sources를 새로운 리스트로 둡니다.
-
removed tracked sources를 새로운 리스트로 둡니다.
-
더 이상 사용 가능하지 않은 각 XR 입력 소스에 대해:
-
inputSource를 session의 활성 XR 입력 소스 목록에 연결된 XR 입력 소스의
XRInputSource
로 둔 뒤, 다음 단계를 수행합니다:- inputSource가 기본 입력 소스인 경우:
-
inputSource를 removed primary sources에 추가합니다.
- 그 외의 경우:
-
inputSource를 removed tracked sources에 추가합니다.
-
-
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
제거 removed primary sources에 있는 각
XRInputSource
를 session의 활성 XR 입력 소스 목록에서 제거합니다. -
removed primary sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의inputsourceschange
이벤트를 session에 대해removed
를 removed primary sources로 하여 발생시킵니다. -
제거 removed tracked sources에 있는 각
XRInputSource
를 session의 활성 XR 추적 소스 목록에서 제거합니다. -
removed tracked sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의trackedsourceschange
이벤트를 session에 대해removed
를 removed tracked sources로 하여 발생시킵니다.
-
참고: 유저 에이전트는 입력 소스가 위치와 방향 트래킹을 모두 일시적으로 잃을 때 이 이벤트를 발생시킬 수 있습니다. 이는 물리적 핸드헬드 컨트롤러 입력 소스에만 권장되며, 트래킹 손 입력 소스의 경우 자주 발생하므로 이 이벤트를 발생시키는 것은 권장되지 않고, 트래커 오브젝트 입력 소스의 경우도 애플리케이션이 신원 개념을 유지하기 어렵게 하므로 권장되지 않습니다.
handedness
,
targetRayMode
,
profiles
,
gripSpace
의 존재, 그리고 기본
입력 소스 또는 트래킹 입력 소스로서의 상태가 XR 입력 소스에서 변경되었을 때 XRSession
session에 대해, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
session의 promise resolved 플래그가 설정되어 있지 않으면, 이 단계를 중단합니다.
-
added primary sources를 새로운 리스트로 둡니다.
-
removed primary sources를 새로운 리스트로 둡니다.
-
added tracked sources를 새로운 리스트로 둡니다.
-
removed tracked sources를 새로운 리스트로 둡니다.
-
변경된 각 XR 입력 소스에 대해:
-
oldInputSource를 session의 활성 XR 입력 소스 목록에 연결된 이전 XR 입력 소스의
XRInputSource
로 두고, 다음 단계를 수행합니다: -
newInputSource를 session의 관련 realm에서 새
XRInputSource
로 두고, 다음 단계를 수행합니다:
-
-
작업을 큐에 추가하여 다음 단계를 실행합니다:
-
제거 removed primary sources에 있는 각
XRInputSource
를 session의 활성 XR 입력 소스 목록에서 제거합니다. -
확장 session의 활성 XR 입력 소스 목록에 added primary sources를 추가합니다.
-
added primary sources 또는 removed primary sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의inputsourceschange
이벤트를 session에 대해added
를 added primary sources로 하고,removed
를 removed primary sources로 하여 발생시킵니다. -
제거 removed tracked sources에 있는 각
XRInputSource
를 session의 활성 XR 추적 소스 목록에서 제거합니다. -
확장 session의 활성 XR 입력 소스 목록에 added tracked sources를 추가합니다.
-
added tracked sources 또는 removed tracked sources가 비어있지 않으면,
XRInputSourcesChangeEvent
타입의trackedsourceschange
이벤트를 session에 대해added
를 added tracked sources로 하고,removed
를 removed tracked sources로 하여 발생시킵니다.
-
각 XRSession
은
visibility state 값을 가지며, 이는 enum입니다. 인라인 세션의 경우 visibility state는 반드시
Document
의
visibilityState와 일치해야 합니다. 몰입형 세션의 경우 visibility state는 아래 상태
중 세션의 상태에 가장 부합하는 값으로 설정되어야 합니다.
-
visible
상태는XRSession
에서 렌더링된 이미지가 사용자가 볼 수 있으며requestAnimationFrame()
콜백이 XR 디바이스의 네이티브 새로고침 속도대로 처리됨을 나타냅니다. 입력도XRSession
에서 정상적으로 처리됩니다. -
visible-blurred
상태는XRSession
에서 렌더링된 이미지가 사용자가 볼 수는 있지만, 주요 초점이 아닌 경우입니다.requestAnimationFrame()
콜백이 스로틀링될 수 있습니다. 입력은XRSession
에서 처리되지 않습니다. -
hidden
상태는XRSession
에서 렌더링된 이미지가 사용자가 볼 수 없음을 나타냅니다.requestAnimationFrame()
콜백은 visibility state가 변경될 때까지 처리되지 않습니다. 입력도XRSession
에서 처리되지 않습니다.
visibilityState
속성은 XRSession
의 visibility state를 반환합니다. onvisibilitychange
속성은 이벤트 핸들러 IDL 속성이며 visibilitychange
이벤트 타입에 해당합니다.
visibility state는 사용자 에이전트에 의해 XR 애니메이션 프레임 처리 중이 아닐 때 언제든 변경될 수 있으며, 사용자 에이전트는 세션 가시성이 외부에서 영향을 받는 경우를 감지할 수 있도록 XR 플랫폼을 모니터링하고, 상태를 적절히 갱신해야 합니다.
참고: XRSession
의 visibility state는 반드시 HTML 문서의 가시성을 의미하지는 않습니다. 시스템 구성에 따라
몰입형 세션이 활성화되어 있어도
페이지는 계속 보일 수 있습니다(예: PC에 연결된 헤드셋이 몰입형 세션의 콘텐츠를 보는 동안 모니터에 페이지가 계속 표시될 수 있음). 페이지 가시성 판단은 Page Visibility를 사용해야
합니다.
참고: XRSession
의 visibility state는 테더드 세션에서 2D 콘텐츠가 여전히 보이는 경우 마우스 동작에는 영향을
주거나 제한하지 않습니다. 콘텐츠가 마우스 동작을 더 강하게 제어하려면 [pointerlock] API 사용을 고려하세요.
XRSystem
에는
프레임률을 설명할 수 있는 여러 정의가 있습니다:
-
명목상 프레임률:
XRSystem
이 최적 성능 유지를 위해 경험이 렌더링하도록 요청하는 프레임률입니다. 경험이 프레임을 놓치면requestAnimationFrame()
이 이만큼 호출되지 않을 수도 있지만,XRSystem
이 달성하려는 목표입니다. -
실제 프레임률: 경험이 실제로 초당 몇 번
requestAnimationFrame()
을 처리하는지 성능 측정값입니다. 이 값은XRSystem
의 프레임 타이밍에 따라 달라집니다. -
디스플레이 프레임률: 실제로 물리적 디스플레이에 그려지는 프레임률로, 경험의 명목상 프레임률을 기반으로 할 수도 있습니다. 이는 하드웨어 구현 세부사항이며, 경험에 드러나지 않습니다.
각 XRSession
은
내부 목표 프레임률을 가질 수 있으며, 이는 목표 프레임률입니다.
각 XRSession
은
내부 명목상 프레임률을 가질 수 있으며, 이는 명목상 프레임률입니다. 실제 프레임률이 명목상 프레임률보다 낮으면, XR 컴포지터가 리프로젝션 등 기술을 사용할 수 있습니다. inline
세션에는 선택적이며 반드시 없어야 합니다.
frameRate
속성은 내부 명목상
프레임률을 반영합니다. XRSession
에 내부 명목상 프레임률이 없으면 null
을 반환합니다.
onframeratechange
속성은 이벤트 핸들러 IDL 속성이며 frameratechange
이벤트 타입에 해당합니다. XRSession
의 명목상 프레임률이 어떤 이유로든
바뀌면, 반드시 기본 프레임률 적용을 새 명목상 프레임률과 해당 XRSession
에 대해
실행해야 합니다.
supportedFrameRates
속성은 지원되는 목표 프레임률 값 목록을 반환합니다.
이 속성은 선택적이며, inline
세션이나 프레임률 제어를 지원하지 않는 XRSystem
에서는 반드시
없어야 합니다. XRSession
이
supportedFrameRates
속성을 지원한다면 frameRate
도
반드시 지원해야 합니다.
각 XRSession
은
뷰어 참조 공간을 가지며, 이는 XRReferenceSpace
타입의 "viewer"
로,
단위 변환 origin offset을
가집니다.
각 XRSession
은
뷰 목록을 가지며, 이는 리스트 형태의 뷰로, XR 디바이스가 제공하는 뷰에 해당합니다. XRSession
의
renderState
의
composition enabled 불리언이 false
이면, 뷰 목록은 반드시
하나의 뷰만 포함해야 합니다. 뷰 목록은 XRSession
중에는
불변이며, 세션 중 노출될 수 있는 모든 뷰를 포함해야 하며, 초기에는 active하지 않을 수도 있는 보조 뷰도 포함해야 합니다.
onend
속성은 이벤트 핸들러 IDL 속성이며 end
이벤트 타입에 해당합니다.
oninputsourceschange
속성은 이벤트 핸들러 IDL 속성이며 inputsourceschange
이벤트 타입에 해당합니다.
onselectstart
속성은 이벤트 핸들러 IDL 속성이며 selectstart
이벤트 타입에 해당합니다.
onselectend
속성은 이벤트 핸들러 IDL 속성이며 selectend
이벤트 타입에 해당합니다.
onselect
속성은 이벤트 핸들러 IDL 속성이며 select
이벤트 타입에 해당합니다.
onsqueezestart
속성은 이벤트 핸들러 IDL 속성이며 squeezestart
이벤트 타입에 해당합니다.
onsqueezeend
속성은 이벤트 핸들러 IDL 속성이며 squeezeend
이벤트 타입에 해당합니다.
onsqueeze
속성은 이벤트 핸들러 IDL 속성이며 squeeze
이벤트 타입에 해당합니다.
4.2. XRRenderState
XRRenderState
는 XRSession
의
출력이 어떻게 합성되는지에 영향을 주는 설정 가능한 값들의 집합을 나타냅니다. 주어진 XRSession
에 대한
활성 렌더 상태는 프레임 경계
사이에서만 변경될 수 있으며, updateRenderState()
를
통해 업데이트를 큐에 쌓을 수 있습니다.
dictionary {
XRRenderStateInit double ;
depthNear double ;
depthFar boolean ;
passthroughFullyObscured double ;
inlineVerticalFieldOfView XRWebGLLayer ?;
baseLayer sequence <XRLayer >?; }; [
layers SecureContext ,Exposed =Window ]interface {
XRRenderState readonly attribute double depthNear ;readonly attribute double depthFar ;readonly attribute boolean ?passthroughFullyObscured ;readonly attribute double ?inlineVerticalFieldOfView ;readonly attribute XRWebGLLayer ?baseLayer ; };
각 XRRenderState
는 output canvas를 가지며, 이는 HTMLCanvasElement
이고
초기값은 null
입니다. output canvas는 "inline"
XRSession
을
위해 렌더링된 콘텐츠가 표시되는 DOM 요소입니다.
각 XRRenderState
는 composition enabled 불리언도 가지며, 초기값은 true
입니다.
XRRenderState
가
composition enabled 상태란, 렌더링 명령이 API가 제공하는 표면에서 실행되고
XR Compositor에 의해 표시될 때를
의미합니다. 만약 "inline"
XRSession
에
대해 렌더링이 output canvas에 직접 표시된다면, XRRenderState
의
composition enabled 플래그는 반드시 false
여야
합니다.
참고: 이 시점에서 XRRenderState
는 composition enabled가 false
일 때만 output canvas를 가집니다. 하지만 향후 명세에서는 미러링이나 레이어 합성과 같은 고급 사용을
지원하는 output canvas 설정 메서드가 추가될 수 있습니다.
XRRenderState
객체가 XRSession
session에 대해 생성될 때, 유저 에이전트는 반드시 다음 단계를 실행하여 렌더 상태를 초기화해야 합니다:
-
state를 session의 관련 realm에서 새
XRRenderState
객체로 둡니다. -
state의
depthNear
를0.1
로 초기화합니다. -
state의
depthFar
를1000.0
으로 초기화합니다. -
state의
passthroughFullyObscured
를false
로 초기화합니다. -
state의
inlineVerticalFieldOfView
는 다음과 같이 초기화합니다:- session이 인라인 세션인 경우:
-
state의
inlineVerticalFieldOfView
를PI * 0.5
로 초기화합니다. - 그 외의 경우:
-
state의
inlineVerticalFieldOfView
를null
로 초기화합니다.
-
state의
baseLayer
를null
로 초기화합니다.
depthNear
속성은 viewer로부터 근거리 클리핑 평면까지의 거리를 미터 단위로 정의합니다. depthFar
속성은 viewer로부터 원거리 클리핑 평면까지의 거리를 미터 단위로 정의합니다.
depthNear
와 depthFar
는 projectionMatrix
계산에 사용됩니다. XRView
의
projectionMatrix
가
렌더링에서 사용될 때 viewer로부터의 거리가 depthNear
와
depthFar
사이에 있는 지오메트리만 그려집니다. 또한 XRWebGLLayer
의
depth buffer 값 해석에도 사용됩니다. depthNear
는 depthFar
보다
클 수도 있습니다.
참고: 일반적으로 렌더링을 위한 원근 투영 행렬을 만들 때 개발자는 시야각, 근거리/원거리 클리핑 평면을 지정합니다. 몰입형 XR 디바이스에 표시할 때는 적절한 시야각이 광학계, 디스플레이, 카메라 조합에 의해 결정됩니다. 그러나 근거리/원거리 클리핑 평면은 렌더링되는 콘텐츠의 유형에 따라 적절한 값을 애플리케이션이 조정할 수 있습니다.
passthroughFullyObscured
속성은 작성자가
뷰포트를 가상 콘텐츠로 완전히 덮을 의도가 있음을 XRSystem
에 힌트로
전달합니다. 불투명 픽셀로 뷰포트를 더 이상 덮지 않게 되면 반드시 이 플래그를 false
로 다시 설정해야 합니다.
참고: XRSystem
은 이 플래그를
힌트로 사용하여 일시적으로 패스스루를 비활성화할 수 있습니다. 시스루 광학계가 탑재된 디바이스에서는 사용자가 환경을 계속 볼 수 있으므로 이 플래그는 아무 효과가 없습니다.
inlineVerticalFieldOfView
속성은 "inline"
XRSession
의
projection matrix 계산에 사용되는 기본 수직 시야각(라디안 단위)을 정의합니다. projection matrix 계산에는 output canvas의 종횡비도
반영됩니다. 이 값은 몰입형 세션에서는
반드시 null
이어야 합니다.
baseLayer
속성은 XRWebGLLayer를 정의하며, XR 컴포지터가 이 레이어로부터 이미지를 가져옵니다.
4.3. 애니메이션 프레임
XRSession
이 XR 디바이스의 트래킹 상태
정보를 제공하는 주요 방법은 requestAnimationFrame()
을 XRSession
인스턴스에서 호출하여 스케줄된 콜백을 통해서입니다.
callback =
XRFrameRequestCallback undefined (DOMHighResTimeStamp ,
time XRFrame );
frame
각 XRFrameRequestCallback
객체는 cancelled 불리언을 가지며, 초기값은
false
입니다.
각 XRSession
은
애니메이션 프레임
콜백 목록(초기값은 빈 배열), 현재 실행 중인 애니메이션 프레임 콜백 목록(역시 초기값은 빈 배열),
애니메이션
프레임 콜백 식별자(초기값 0인 숫자)을 가집니다.
requestAnimationFrame(callback)
메서드는 다음 번 유저 에이전트가 디바이스의 애니메이션 프레임을 실행하고자 할 때 callback을 실행하도록 큐에 올립니다.
이 메서드가 호출되면, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
session을 this로 둡니다.
-
session의 ended 값이
true
이면,0
을 반환하고 단계를 중단합니다. -
session의 애니메이션 프레임 콜백 식별자를 1 증가시킵니다.
-
callback을 session의 애니메이션 프레임 콜백 목록에, session의 애니메이션 프레임 콜백 식별자 현재 값과 연결하여 추가합니다.
-
session의 애니메이션 프레임 콜백 식별자의 현재 값을 반환합니다.
cancelAnimationFrame(handle)
메서드는 애니메이션 프레임 콜백 식별자 handle에 해당하는 기존
애니메이션 프레임 콜백을 취소합니다.
이 메서드가 호출되면, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
session을 this로 둡니다.
-
session의 애니메이션 프레임 콜백 목록 또는 session의 현재 실행 중인 애니메이션 프레임 콜백 목록 중 handle과 연결된 항목을 찾습니다.
-
해당 항목이 있으면, 그 항목의 cancelled 불리언을
true
로 설정하고 session의 애니메이션 프레임 콜백 목록에서 제거합니다.
renderState
state로 할 때, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
state의
baseLayer
가null
이면false
를 반환합니다. -
true
를 반환합니다.
참고: WebXR layers module에서 이 알고리즘의 새로운 의미가 도입될 예정입니다.
XRSession
session에 대해 결정할 때, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
레이어 상태 확인을 session의
renderState
로 실행한 결과가false
이면false
를 반환합니다. -
session의 mode가
"inline"
이고, session의renderState
의 output canvas가null
이면false
를 반환합니다. -
true
를 반환합니다.
XRSession
session이 viewer 상태를 타임스탬프
frameTime으로 XR 디바이스에서 갱신받았을 때,
XR 애니메이션 프레임을
실행하며,
애니메이션 프레임 콜백 목록이 비어 있든 아니든 반드시 다음 단계를 실행해야 합니다:
-
작업을 큐에 추가하여 다음 단계를 수행합니다:
-
now를 현재 고해상도 시간으로 둡니다.
-
frame을 session의 애니메이션 프레임으로 둡니다.
-
frame의 time을 frameTime으로 설정합니다.
-
frame의
predictedDisplayTime
을 frameTime으로 설정합니다. -
session의 mode가
"inline"
이 아니면, frame의predictedDisplayTime
을 XR 컴포지터가 이 XR 애니메이션 프레임을 표시할 것으로 예상되는 평균 타임스탬프로 설정합니다. -
뷰 목록의 각 view에 대해, view의 viewport modifiable 플래그를 true로 설정합니다.
-
만약 뷰 목록 내 어떤 view의 active 플래그가 이전 XR 애니메이션 프레임 이후로 변경되었으면, 뷰포트 업데이트를 실행합니다.
-
프레임이 렌더링되어야 한다면 session에 대해:
-
session의 현재 실행 중인 애니메이션 프레임 콜백 목록을 session의 애니메이션 프레임 콜백 목록으로 설정합니다.
-
session의 애니메이션 프레임 콜백 목록을 빈 배열로 설정합니다.
-
frame의 active 불리언을
true
로 설정합니다. -
프레임 업데이트 적용을 frame에 대해 실행합니다.
-
session의 현재 실행 중인 애니메이션 프레임 콜백 목록의 각 entry에 대해 순서대로:
-
entry의 cancelled 불리언이
true
면 다음 entry로 넘어갑니다. -
콜백 함수 호출을 entry에 대해 « now, frame » 및 "
report
"로 실행합니다. -
session의 현재 실행 중인 애니메이션 프레임 콜백 목록을 빈 리스트로 설정합니다.
-
frame의 active 불리언을
false
로 설정합니다.
-
-
session의 대기 중 렌더 상태가
null
이 아니면, 대기 중 렌더 상태 적용을 실행합니다.
-
Window
인터페이스의 requestAnimationFrame()
메서드는 어떤 XRSession
이 활성
상태이어도 변경되지 않으며, requestAnimationFrame()
을 XRSession
에서
호출해도 Window
의 requestAnimationFrame()
과 아무런 상호작용이 없습니다. 활성 몰입형 세션은 페이지가 가려지는 경우 렌더링 기회에 영향을 줄 수 있습니다. 2D 브라우저 뷰가 활성 몰입형 세션 동안에도 보이는 경우(즉, 테더드
헤드셋에서 세션이 실행 중인 경우), Window
의 requestAnimationFrame()
및 requestIdleCallback()
의 콜백 타이밍은 세션의 requestAnimationFrame()
과 일치하지 않을 수 있으므로, XR 콘텐츠 렌더링에는 의존하지 않아야 합니다.
참고: 유저 에이전트는 XRSession
의
requestAnimationFrame()
이 Window
의 requestAnimationFrame()
콜백 내에서 호출될 경우 개발자 콘솔에 경고를 표시할 수 있습니다. 활성 몰입형 세션이 렌더링 기회에 영향을 줄 수 있으며, 실행된다 하더라도 올바른 타이밍이 아닐 수 있기 때문입니다.
Window
requestAnimationFrame()
에 전달된 콜백은 세션이 활성화되어 있는 동안 처리되지 않을 수 있습니다. 이는 사용 중인 디바이스 종류에 따라 다르며, 몰입형 콘텐츠가 HTML 문서를 완전히 가리는 모바일이나
독립형(standalone) 디바이스에서 가장 자주 발생합니다. 따라서 개발자는 Window
requestAnimationFrame()
콜백을 이용해 XRSession
requestAnimationFrame()
콜백을 예약하거나, 그 반대(공유 렌더링 로직을 사용하더라도)도 해서는 안 됩니다. 이 가이드를 따르지 않는 애플리케이션은 일부 플랫폼에서 올바르게 동작하지 않을 수 있습니다. 아래는 이런 두
종류의 애니메이션 루프 간 전환을 원활하게 처리할 수 있는 더 효과적인 패턴 예시입니다:
let xrSession= null ; function onWindowAnimationFrame( time) { window. requestAnimationFrame( onWindowAnimationFrame); // 일부 기기(예: 데스크탑 + 테더드 헤드셋)에서는 몰입형 세션이 실행 중에도 이 콜백이 호출될 수 있습니다. // 두 애니메이션 루프가 동시에 렌더링하지 않도록, 세션이 종료될 때까지 이 루프에서는 그리기를 건너뜁니다. if ( ! xrSession) { renderFrame( time, null ); } } // window 애니메이션 루프는 페이지가 로딩되자마자 바로 시작할 수 있습니다. window. requestAnimationFrame( onWindowAnimationFrame); function onXRAnimationFrame( time, xrFrame) { xrSession. requestAnimationFrame( onXRAnimationFrame); renderFrame( xrFrame. predictedDisplayTime, xrFrame); } function renderFrame( time, xrFrame) { // 공통 렌더링 로직. } // 아래 함수는 코드 내 다른 곳에서 사용자 동작에 의해 호출된다고 가정합니다. async function startXRSession() { xrSession= await navigator. xr. requestSession( 'immersive-vr' ); xrSession. addEventListener( 'end' , onXRSessionEnded); // 세션에 필요한 설정을 여기서 진행합니다. // 세션의 애니메이션 루프를 시작합니다. xrSession. requestAnimationFrame( onXRAnimationFrame); } function onXRSessionEnded() { xrSession= null ; }
HTML 문서에 렌더링하기 위해 "inline"
세션을 사용하는 애플리케이션은 별도의 애니메이션 루프 동기화 작업을 할 필요가 없습니다. 몰입형 세션이 활성화되면 유저 에이전트가 "inline"
세션의 애니메이션 루프를 자동으로 일시 중지해주기 때문입니다.
4.4. XR 컴포지터
유저 에이전트는 반드시 XR 컴포지터를 유지해야 하며, 이는 XR 디바이스로의 표시 및 프레임 타이밍을 담당합니다. XR 컴포지터는 반드시 문서에서 생성된 어떤 그래픽 컨텍스트와도 상태가 격리된 독립적인 렌더링 컨텍스트를 사용해야 합니다. 컴포지터는 페이지가 컴포지터 상태를 손상시키거나 다른 페이지/앱의 콘텐츠를 읽어오는 것을 반드시 방지해야 합니다. 또한, 컴포지터는 페이지 성능과 사용자에게 적절한 프레임률로 새로운 이미지를 표시하는 기능을 분리하기 위해 별도의 스레드나 프로세스에서 실행되어야 합니다. 컴포지터는 디바이스 메뉴 등 추가적인 디바이스 또는 유저 에이전트 UI를 렌더링된 콘텐츠 위에 합성할 수 있습니다.
참고: 향후 명세 확장에서는 같은 페이지에서 오는 여러 레이어도 컴포지터가 합성하도록 할 수 있습니다.
5. 프레임 루프
5.1. XRFrame
XRFrame
은 XRSession
에 대해
트래킹되는 모든 객체의 상태 스냅샷을 나타냅니다.
애플리케이션은 XRSession
에서
requestAnimationFrame()
을
호출하여 XRFrame
을 획득할
수 있습니다.
콜백이 호출될 때 XRFrame
이 전달됩니다.
select
이벤트처럼 트래킹 상태를 전달해야 하는 이벤트 또한 XRFrame
을 제공합니다.
[SecureContext ,Exposed =Window ]interface { [
XRFrame SameObject ]readonly attribute XRSession session ;readonly attribute DOMHighResTimeStamp predictedDisplayTime ;XRViewerPose ?getViewerPose (XRReferenceSpace );
referenceSpace XRPose ?getPose (XRSpace ,
space XRSpace ); };
baseSpace
각 XRFrame
은 active 불리언(초기값 false
)과 animationFrame 불리언(초기값 false
)을 가집니다.
session
속성은 XRFrame
을 생성한 XRSession
을
반환합니다.
몰입형 세션의 경우 predictedDisplayTime
속성은 이 XRFrame
이 디바이스
디스플레이에 표시될 것으로 예상되는 평균 시점을 나타내는 DOMHighResTimeStamp
를
반환해야 합니다. "inline"
XRSession
의
경우, predictedDisplayTime
은
XRFrameRequestCallback
에
전달된 타임스탬프와 동일한 값을 반환해야 합니다.
predictedDisplayTime
은 requestAnimationFrame()
콜백이 예약되거나 실행된 시점이 아닌, 프레임이 표시될 때의 상태로 XR 씬을 렌더링할 수 있게 하기 위한 목적입니다.
predictedDisplayTime
은 렌더링에 할당된 시간을 추론하는 용도가 아닙니다. XR 컴포지터가 프레임 제출 후 추가적인 처리를 하기 때문입니다. 만약 경험이 predictedDisplayTime
까지
처리할 수 있다고 가정하면, XR 컴포지터가
프레임을 제대로 활용하지 못해 목표 프레임률을 달성할 수 없습니다.
각 XRFrame
은 주어진
time에 대해 모든 트래킹 객체의 상태를 나타내며, 이 상태에 대한 구체적 정보를 저장하거나 질의할 수 있습니다.
getViewerPose(referenceSpace)
메서드는
XRFrame
의 time 시점에
referenceSpace를 기준으로 viewer의
pose를 XRViewerPose
로
제공합니다.
이 메서드가 호출되면 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
frame을 this로 둡니다.
-
session을 frame의
session
객체로 둡니다. -
frame의 animationFrame 불리언이
false
면,InvalidStateError
를 throw 하고 단계를 중단합니다. -
pose를 session의 관련 realm에서 새
XRViewerPose
객체로 둡니다. -
session의 viewer reference space의 pose를 referenceSpace 기준에서 frame이 나타내는 시점에 pose에 populate하고,
force emulation
을true
로 설정합니다. -
pose가
null
이면null
을 반환합니다. -
xrviews를 빈 리스트로 둡니다.
-
offset를
0
으로 설정한다. -
활성 뷰(view) view마다
session
의 뷰 목록(list of views)에서 다음 단계를 수행한다:-
xrview를 session의 relevant realm에서 새로운
XRView
객체로 생성한다. -
xrview의 underlying view를 view로 초기화한다.
-
xrview의
index
를 offset으로 초기화한다. -
xrview의 frame을 frame으로 초기화한다.
-
xrview의 session을 session으로 초기화한다.
-
xrview의 reference space를 referenceSpace로 초기화한다.
-
viewtransform을 view offset과 동일한 session의 relevant realm에서 new
XRRigidTransform
객체로 생성한다. -
xrview의
transform
속성을 곱셈(multiplying)의 결과값, 즉XRViewerPose
의transform
과 viewtransform 변환을 session의 relevant realm에서 곱한 결과로 설정한다. -
xrviews에 xrview를 추가한다.
-
offset을
1
만큼 증가시킨다.
-
-
pose의
views
를 xrviews로 설정합니다. -
pose를 반환합니다.
getPose(space, baseSpace)
메서드는
XRFrame
이
나타내는 시점의 baseSpace 기준으로 space의 pose를 XRPose
로 제공합니다.
이 메서드가 호출되면 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
프레임 업데이트는 XRFrame
을 받아 실행될 수
있는 알고리즘으로, 각 XRFrame
마다 실행됩니다.
모든 XRSession
은
프레임 업데이트 목록을 가지며, 이는 리스트 형태의 프레임 업데이트이고, 초기값은 빈 리스트입니다.
프레임 업데이트 적용은 XRFrame
frame에 대해 다음 단계를 반드시 실행해야 합니다:
-
frame의
session
의 프레임 업데이트 목록의 각 frame update에 대해:-
frame update를 frame으로 실행합니다.
-
참고: 이 명세는 프레임 업데이트를 정의하지 않지만, 다른 명세에서 추가할 수 있습니다.
6. 공간(Spaces)
WebXR Device API의 핵심 기능 중 하나는 공간 트래킹을 제공하는 것입니다. Space는 애플리케이션이 트래킹되는 엔티티들이 사용자의 물리적 환경 및 서로 간에 어떻게 공간적으로 연관되어 있는지 파악할 수 있게 해주는 인터페이스입니다.
6.1. XRSpace
XRSpace
는 물리적 위치에 해당하는 원점을 가진 가상 좌표계를 나타냅니다. API에서 요청하거나 전달하는 모든 공간 데이터는 항상 특정 XRSpace
와 특정 XRFrame
시점에 대해
표현됩니다. 예를 들어 pose position과 같은 수치 값은 해당 space의 원점을 기준으로 한 좌표입니다. 이 인터페이스는 의도적으로 불투명하게 설계되었습니다.
[SecureContext ,Exposed =Window ]interface :
XRSpace EventTarget { };
각 XRSpace
는 이를 생성한
XRSession
을
session으로 가집니다.
각 XRSpace
는 공간상의
위치와 방향 값을 가지는 네이티브 원점을 가집니다. XRSpace
의 네이티브 원점은 XR 디바이스의 트래킹
시스템에 의해 업데이트될 수 있으며, 각 XRSpace
는 자신의 네이티브 원점이 어떻게
트래킹되고 갱신되는지에 대한 의미를 다르게 정의할 수 있습니다.
각 XRSpace
는 유효 원점(effective origin)을 가지며, 이는 XRSpace
의 좌표계의 기준이 됩니다.
유효 space에서 네이티브
원점의 space로 변환하는 변환은 원점 오프셋(origin offset)으로 정의되며,
이는 XRRigidTransform
이며
초기값은 단위 변환(identity
transform)입니다. 즉, 유효 원점은 원점 오프셋과 네이티브 원점을 곱해 구할 수 있습니다.
XRSpace
의 유효 원점은
다른 XRSpace
의
좌표계에서만 XRPose
로 관찰할
수 있으며,
이는 XRFrame
의
getPose()
메서드가 반환합니다. XRSpace
들 간의 공간적
관계는 XRFrame
마다
변경될 수 있습니다.
포즈를 채우기(populate the
pose) 위해, XRSpace
인
space와 XRSpace
인
baseSpace를, XRFrame
frame이 나타내는 시점에서 XRPose
pose에 대해, 선택적 force emulation 플래그와 함께, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:
-
frame의 active 불리언이
false
이면InvalidStateError
를 throw 하고 단계를 중단합니다. -
session을 frame의
session
객체로 둡니다. -
space의 session이 session과 다르면,
InvalidStateError
를 throw 하고 단계를 중단합니다. -
baseSpace의 session이 session과 다르면,
InvalidStateError
를 throw 하고 단계를 중단합니다. -
poses may be reported 조건을 확인하고, 만족하지 않으면
SecurityError
를 throw 하고 단계를 중단합니다. -
session의
visibilityState
가"visible-blurred"
이고, space 또는 baseSpace가XRInputSource
에 연관되어 있다면, pose를null
로 하고 단계를 중단합니다. -
limit을 space와 baseSpace 사이에서 poses must be limited 결과로 둡니다.
-
transform을 pose의
transform
으로 둡니다. -
XR 디바이스의 트래킹 시스템에 frame의 time 시점의 space의 pose를 baseSpace 기준으로 질의한 다음, 다음 단계를 실행합니다:
- limit이
false
이고, 트래킹 시스템이 space의 pose에 대해 baseSpace 기준으로 actively tracked 또는 statically known한 6DoF pose를 제공하는 경우: -
transform의
orientation
을 view의 유효 원점이 baseSpace의 좌표계에서 갖는 orientation으로 설정합니다.transform의
position
을 view의 유효 원점이 baseSpace의 좌표계에서 갖는 position으로 설정합니다.지원된다면, pose의
linearVelocity
를 space의 유효 원점이 baseSpace의 좌표계에서 갖는 선속도로 설정합니다.지원된다면, pose의
angularVelocity
를 space의 유효 원점이 baseSpace의 좌표계에서 갖는 각속도로 설정합니다.pose의
emulatedPosition
을false
로 설정합니다. - 그 외 limit이
false
이고, 트래킹 시스템이 3DoF pose 또는 위치가 actively tracked/static하지 않은 6DoF pose만 제공하는 경우: -
transform의
orientation
을 space의 유효 원점이 baseSpace의 좌표계에서 갖는 orientation으로 설정합니다.transform의
position
을 트래킹 시스템이 추정한 space의 유효 원점이 baseSpace의 좌표계에서 갖는 위치로 설정합니다. 이 값에는 목/팔 모델 등 계산된 오프셋이 포함될 수 있습니다. 위치 추정이 불가능하면 마지막으로 알려진 위치를 사용해야 합니다.pose의
linearVelocity
를null
로 설정합니다.pose의
angularVelocity
를null
로 설정합니다.pose의
emulatedPosition
을true
로 설정합니다. - 또는, space의 pose가 과거에 baseSpace 기준으로 확인된 적이 있고, force
emulation이
true
인 경우: -
transform의
position
을 space의 유효 원점이 baseSpace의 좌표계에서 마지막으로 알려진 위치로 설정합니다.transform의
orientation
을 space의 유효 원점이 baseSpace의 좌표계에서 마지막으로 알려진 orientation으로 설정합니다.pose의
linearVelocity
를null
로 설정합니다.pose의
angularVelocity
를null
로 설정합니다.pose의
emulatedPosition
불리언을true
로 설정합니다. - 그 외의 경우:
-
pose를
null
로 설정합니다.
- limit이
참고: XRPose
의 emulatedPosition
불리언은 baseSpace의 위치가 에뮬레이션되는지 여부가 아니라, space의 위치를 baseSpace 기준으로 평가할 때
에뮬레이션이 필요한지를 나타냅니다. 예를 들어, 3DoF 트래킹 컨트롤러는 targetRaySpace
또는 gripSpace
를
XRReferenceSpace
에
대해 쿼리할 때는 emulatedPosition
이
true
로 보고되지만, targetRaySpace
의
pose를 gripSpace
기준으로 쿼리하면 정확하게 관계가 알려져 있으므로 emulatedPosition
이
false
로 보고됩니다.
6.2. XRReferenceSpace
XRReferenceSpace
는 애플리케이션이 사용자의 물리적 환경과 공간적 관계를 설정할 때 사용할 수 있는 대표적인 XRSpace
중 하나입니다.
XRReferenceSpace
는
대체로 XRSession
의 전체
기간 동안 고정되어 있을 것으로 기대되며, 가장 흔한 예외는 세션 도중 사용자가 재설정하는 경우입니다. 각 XRReferenceSpace
의
네이티브 원점은
+X
는 "오른쪽", +Y
는 "위", -Z
는 "앞"으로 간주되는 좌표계를 정의합니다.
enum {
XRReferenceSpaceType "viewer" ,"local" ,"local-floor" ,"bounded-floor" ,"unbounded" }; [SecureContext ,Exposed =Window ]interface :
XRReferenceSpace XRSpace { [NewObject ]XRReferenceSpace getOffsetReferenceSpace (XRRigidTransform );
originOffset attribute EventHandler onreset ; };
각 XRReferenceSpace
는 type을 가지며, 이는 XRReferenceSpaceType
입니다.
XRReferenceSpace
는 주로 requestReferenceSpace()
를
호출하여 획득하며,
이때 전달한 XRReferenceSpaceType
열거형 값이 지원됨을 확인한 뒤 인스턴스가 생성됩니다. type은 해당 reference space가 어떤 트래킹
동작을 보일지를 나타냅니다:
-
type에
viewer
를 전달하면XRReferenceSpace
인스턴스가 생성됩니다. 이는 네이티브 원점이 viewer의 위치와 방향을 트래킹하는 공간을 나타냅니다. 모든XRSession
은 반드시"viewer"
XRReferenceSpace
를 지원해야 합니다. -
type에
local
을 전달하면XRReferenceSpace
인스턴스가 생성됩니다. 이는 생성 시점의 viewer 근처에 네이티브 원점을 가지는 공간입니다. 정확한 위치와 방향은 플랫폼의 관행에 따라 초기화됩니다. 이 reference space를 사용할 때 사용자는 초기 위치에서 크게 이동하지 않는 것이 일반적이며, 트래킹도 그 목적에 맞게 최적화됩니다. 6DoF 트래킹을 지원하는 디바이스의 경우local
reference space는 원점이 사용자의 환경에 상대적으로 안정적으로 유지되도록 강조해야 합니다. -
type에
local-floor
을 전달하면XRReferenceSpace
인스턴스가 생성됩니다. 이는 사용자가 서 있을 수 있는 안전한 위치의 바닥에 네이티브 원점을 가지는 공간입니다.Y
축이 바닥에서0
이고,X
와Z
위치 및 방향은 플랫폼의 관행에 따라 초기화됩니다. 바닥 높이를 알 수 없는 경우 반드시 추정(estimated floor level)해야 하며, estimated floor level이 비기본값으로 결정되면 rounding되어야 하며, 지문 채취 방지를 위해 충분히 반올림되어야 합니다. 이 reference space 역시 사용자가 크게 움직이지 않는 것을 가정하며, 6DoF 트래킹의 경우 환경에 대한 원점 안정성이 강조되어야 합니다.참고:
"local-floor"
reference space의 바닥 높이가 지문 채취 방지를 위해 조정된다면, 1cm 단위로 반올림하는 것이 권장됩니다. -
type에
bounded-floor
을 전달하면XRBoundedReferenceSpace
인스턴스가 생성됩니다. 이는 바닥에 네이티브 원점을 두고, 사용자가boundsGeometry
로 주어진 사전 설정된 경계 내에서 이동하는 공간을 나타냅니다.bounded-floor
reference space의 트래킹은 네이티브 원점과boundsGeometry
가 사용자의 환경에 안정적으로 유지되도록 최적화됩니다. -
type에
unbounded
를 전달하면XRReferenceSpace
인스턴스가 생성됩니다. 이는 사용자가 환경 내에서 자유롭게, 심지어 시작점에서 멀리 떨어져 이동하는 것이 예상되는 공간입니다.unbounded
reference space의 트래킹은 사용자의 현재 위치 주변의 안정성에 최적화되어 있으며, 네이티브 원점은 시간이 지남에 따라 드리프트될 수 있습니다.
참고: 여러 종류의 XRReferenceSpace
를
지원하는 XR 시스템은 reference space의 Y축이 항상 서로 평행이고, 같은 방향을 가리키도록 유지해야 한다고 가정합니다(생성된 XRSession
전체
동안). 단, "viewer"
는
플랫폼의 관행과 무관하게 동작합니다. "unbounded"
reference space는 원점이 가까울 때는 Y축을 다른 reference space와 맞추어야 하지만, 사용자가 멀리 이동하면 달라질 수 있습니다.
"local"
reference space를 지원하는 디바이스는 반드시 "local-floor"
reference space도 지원해야 하며, 필요하면 에뮬레이션을 통해서라도 마찬가지입니다.
onreset
속성은 이벤트 핸들러 IDL 속성이며, reset
이벤트 타입에 해당합니다.
XRReferenceSpace
가 XRReferenceSpaceType
type 및 XRSession
session으로 요청될 때, 유저 에이전트는 반드시 다음 단계를 실행해서 reference space 생성을 해야 합니다:
-
referenceSpace를 다음과 같이 초기화합니다:
- type이
bounded-floor
인 경우: -
referenceSpace를 새
XRBoundedReferenceSpace
로 session의 관련 realm에서 생성합니다. - 그 외의 경우:
-
referenceSpace를 새
XRReferenceSpace
로 session의 관련 realm에서 생성합니다.
- type이
-
referenceSpace의 type을 type으로 초기화합니다.
-
referenceSpace의 session을 session으로 초기화합니다.
-
referenceSpace를 반환합니다.
XRSession
session에 대해 다음과 같이 실행합니다:
-
type이
viewer
이면true
를 반환합니다. -
type이
local
또는local-floor
이고, session이 몰입형 세션이면true
를 반환합니다. -
type이
local
또는local-floor
이고, XR 디바이스가 방향 데이터를 지원하면true
를 반환합니다. -
type이
bounded-floor
이고, session이 몰입형 세션이면 bounded reference space 지원 여부를 XR 디바이스에 대해 확인한 결과를 반환합니다. -
type이
unbounded
이고, session이 몰입형 세션이며, XR 디바이스가 사용자 근처에서 무제한 거리까지 안정적인 트래킹을 지원하면true
를 반환합니다. -
false
를 반환합니다.
getOffsetReferenceSpace(originOffset)
메서드가 호출되면 반드시 다음 단계를 실행해야 합니다:
-
base를 이 메서드를 호출한
XRReferenceSpace
로 둡니다. -
offsetSpace를 다음과 같이 초기화합니다:
- base가
XRBoundedReferenceSpace
의 인스턴스인 경우: -
offsetSpace를 새
XRBoundedReferenceSpace
로 base의 관련 realm에서 생성하고, offsetSpace의boundsGeometry
를 base의boundsGeometry
로 설정하되, 각 점에 originOffset의inverse
를 곱합니다. - 그 외의 경우:
-
offsetSpace를 새
XRReferenceSpace
로 base의 관련 realm에서 생성합니다.
- base가
-
offsetSpace의 원점 오프셋(origin offset)을 base의 원점 오프셋과 originOffset을 곱한 값으로 base의 관련 realm에서 설정합니다.
-
offsetSpace를 반환합니다.
참고: 많은 애플리케이션이 getOffsetReferenceSpace()
를 마우스, 키보드, 터치, 게임패드 입력 기반 씬 네비게이션 등에 활용할 것으로 예상됩니다. 이로 인해 getOffsetReferenceSpace()
호출이 최소 프레임마다 한 번 이상 반복될 수 있으므로, UA는 XRReferenceSpace
를
getOffsetReferenceSpace()
로
생성할 때 매우 가볍게 동작하도록 구현하는 것이 권장됩니다.
6.3. XRBoundedReferenceSpace
XRBoundedReferenceSpace
는 XRReferenceSpace
를 확장하여 boundsGeometry
를
포함합니다. 이는 사용자의 공간에 미리 설정된 경계(boundary)를 나타냅니다.
[SecureContext ,Exposed =Window ]interface :
XRBoundedReferenceSpace XRReferenceSpace {readonly attribute FrozenArray <DOMPointReadOnly >boundsGeometry ; };
XRBoundedReferenceSpace
의 원점(origin)은 반드시 바닥에 위치해야 하며, Y
축이 바닥에서 0
이어야 합니다. X
와 Z
위치 및 방향은 기본적으로 플랫폼의 관행에 따라 초기화되며, 일반적으로 방 중앙 근처에서 논리적인 "앞" 방향을 바라보도록 설정됩니다.
참고: 다른 XR 플랫폼에서는 bounded-floor
reference space에서 제공되는 트래킹을 "룸 스케일(room scale)" 트래킹이라고 부르기도 합니다. XRBoundedReferenceSpace
는 여러 방을 포함하는 공간, 바닥이 울퉁불퉁한 공간, 매우 넓은 개방 공간을 설명하기 위한 것이 아닙니다. 그런 시나리오를 다루어야 하는 콘텐츠는 unbounded
reference space를 사용해야 합니다.
각 XRBoundedReferenceSpace
는 네이티브 경계 기하(native bounds geometry)를 가지며, 이는
XRBoundedReferenceSpace
주변의 경계를 나타내고, 사용자가 안전하게 이동할 수 있는 영역을 설명합니다. 이 다각형 경계는 DOMPointReadOnly
배열로 제공되며, 안전 공간의 모서리를 이루는 점들의 루프를 나타냅니다. 각 점은 네이티브 원점 기준(미터 단위) 오프셋을 설명합니다. 점들은 위에서 아래(음의 Y축 방향)로 볼 때 시계방향으로
지정되어야 합니다. 각 점의 y
값은 반드시 0
이어야 하며, w
값은 반드시 1
이어야 합니다. 이 경계는 바닥에서 시작해 무한히 위로 뻗는 것으로 간주할 수 있습니다. 경계의 형태는 볼록(convex) 또는 오목(concave)일 수
있습니다.
네이티브 경계 기하의 각 점은 reference space의 네이티브 원점에서 합리적인 거리 내로 제한되어야 합니다.
참고: 네이티브 경계 기하의 점들은 모든 방향에서 네이티브 원점으로부터 15미터 내로 제한하는 것이 권장됩니다.
네이티브 경계 기하의 각 점은 지문 채취 방지를 위해 양자화(quantized)되어야 하며, 양자화된 점의 값이 플랫폼이 보고하는 경계 바깥에 위치해서는 안 됩니다.
참고: 네이티브 경계 기하의 점들은 5cm 단위로 양자화하는 것이 권장됩니다.
boundsGeometry
속성은 DOMPointReadOnly
객체들의 배열이며, 각 항목은 XRBoundedReferenceSpace
의
네이티브 경계 기하를 inverse
origin
offset으로 미리 곱한 값과 같습니다. 즉, XRBoundedReferenceSpace
좌표계에서 effective origin을 기준으로 동일한 경계를 제공합니다.
네이티브 경계 기하가 일시적으로 사용 불가한 경우(예: XR 디바이스
초기화 중, 트래킹 장기 손실, 미리 설정된 공간 간 이동 등), boundsGeometry
는
반드시 빈 배열을 반환해야 합니다.
참고: 경계나 바닥 높이가 reference space 요청 시점에 아직 확인되지 않았더라도, XR 디바이스가 이를 지원하는 것으로 알려진 경우 bounded reference space가 반환될 수 있습니다.
참고: 콘텐츠는 사용자가 boundsGeometry
를
넘어서 움직일 필요가 없도록 설계해야 합니다. 물리적 환경에 따라 사용자가 경계를 넘어서 이동할 수 있으며, 그 경우 위치 값이 경계 다각형 바깥이 될 수도 있습니다. 이는 오류 상황이 아니며,
페이지 콘텐츠에서 부드럽게 처리되어야 합니다.
참고: 콘텐츠가 boundsGeometry
시각화를 직접 제공하는 것은 권장되지 않습니다. 안전과 관련된 정보 제공은 유저 에이전트의 책임입니다.
7. 뷰(Views)
7.1. XRViewGeometry
XRViewGeometry
인터페이스 믹스인(XRViewGeometry interface mixin)이 포함된 객체들은 XR 디바이스가 사용자에게 이미지를 표시하는 디스플레이이거나, 실제 세계의 시각 정보를 수집하는
센서일 수 있습니다. 이러한 객체들은 뷰 기하(view
geometry)를 포함합니다.
뷰 기하(view geometry)는 뷰어 참조 공간(viewer reference space)의 좌표계에서 포함 객체(containing object)의 스크린 공간(screen space)으로 좌표를 변환하는 데 사용되는 내재적(intrinsics) 및 외재적(extrinsics) 값들의 집합에 해당합니다.
뷰 기하는 포함 객체(containing object)를 가지며, 이는 뷰 기하의 데이터가 적용되는 물리적 하드웨어입니다.
뷰 기하의 포함 객체는 스크린 공간을 가지며, 이는 포함 객체가 데이터를 읽거나 그리는 2차원 평면입니다.
뷰 기하는 뷰 오프셋(view
offset)을 가지며, 이는 XRRigidTransform
으로,
포함 객체가 뷰어 참조 공간의 좌표계에서
어느 위치·방향에 있는지 설명합니다.
참고: 뷰 오프셋 값에는 어떤 제약도 없으며, 각 뷰의 방향이 다를 수도 있습니다. 이는 눈 디스플레이가 비스듬하게 배치된 HMD(head-mounted device)에서 종종 나타나며, CAVE 렌더링 등 극단적인 경우에도 발생할 수 있습니다. 이로 인해 z-정렬(z-sorting)이나 컬링(culling) 등의 처리가 눈마다 따로 필요할 수 있습니다.
뷰 기하는 투영 행렬(projection matrix)을 가지며, 이는 포함 객체에 렌더링할 때 사용할 투영을 설명하는 행렬입니다. 이 투영 행렬에는 전단(shearing) 등 단순한 프러스텀으로는 정확히 설명할 수 없는 변환이 포함될 수도 있습니다.
참고: 이 행렬의 역행렬은 스크린 공간에서 픽셀을 읽어내고, 포함 객체를 원점으로 하는 좌표계로 변환하는 데에 적합합니다.
[SecureContext ,Exposed =Window ]interface mixin {
XRViewGeometry readonly attribute Float32Array projectionMatrix ; [SameObject ]readonly attribute XRRigidTransform transform ; };
XRViewGeometry
는 내부 투영 행렬(internal projection matrix)을 가지며, 이는 투영 행렬을 저장합니다. 초기값은 null
입니다.
참고: transform
은 여러 렌더링 라이브러리에서 카메라 객체 위치 지정에 사용할 수 있습니다. 전통적인 view 행렬이 필요하다면 transform.inverse.matrix
로 얻을 수
있습니다.
projectionMatrix
속성은 해당 뷰 기하의 투영 행렬입니다. 이 행렬은 반드시 수정하거나 분해하지 말고 그대로 사용할 것을
강력히 권장합니다. 제공된 투영 행렬을 렌더링에 사용하지 않으면 화면에 왜곡이 생기거나 정렬이 어긋나 사용자에게 불편함을 줄 수 있습니다. 이 속성은 투영 행렬 얻기 알고리즘으로 계산되어야 합니다.
transform
속성은 해당 객체의 XRRigidTransform
입니다.
이는 객체가 XRReferenceSpace
에서
어느 위치·방향에 있는지를 나타냅니다.
투영 행렬 얻기(obtain the projection matrix)를 XRViewGeometry
view geometry 에 대해 실행할 때:
-
view geometry의 내부 투영 행렬이
null
이 아니면 다음을 수행합니다:-
IsDetachedBuffer 연산을 내부 투영 행렬에 대해 실행한 결과가
false
이면, view geometry의 내부 투영 행렬을 반환합니다.
-
-
view geometry의 내부 투영 행렬을 새 행렬로 관련 realm에서 생성하고, view geometry의 projection matrix와 동일하게 만듭니다.
-
view geometry의 내부 투영 행렬을 반환합니다.
7.2. XRView
XRView
는 특정 프레임에 대한
XR 씬의 단일 뷰를 설명합니다.
뷰는 XR 디바이스가 사용자에게 이미지를 표시하는 디스플레이
또는 디스플레이 일부에 해당합니다. 뷰는 시야각, 눈 오프셋, 기타 광학 특성 등 뷰의
물리적 출력 특성에 잘 정렬된 콘텐츠를 렌더링하는 데 필요한 모든 정보를 제공합니다. 여러
뷰가 사용자의 시야에서 겹치는 영역을 포함할 수도 있습니다. XR 디바이스가 사용하는 뷰의 개수나 순서에 대해서, 또는 뷰의 개수가 XRSession
전체
기간 동안 일정하리라는 보장은 없습니다.
뷰는 eye라는 값을 가지며, 이는 XREye
로 이
뷰가 어느 눈에 표시될지 설명합니다. 뷰에 고유하게 연관된 눈이 없으면(예: 모노 디스플레이), 이 값은 반드시 "none"
이어야
합니다.
뷰는 active 플래그를 가지며, 이는 XRSession
의
생명주기 동안 변경될 수 있습니다. 기본 뷰(primary
view)는 반드시 active 플래그가
true
로 유지되어야 합니다.
참고: 많은 HMD는 왼쪽·오른쪽 눈 각각에 대해 두 개의 뷰를 요청하지만, 대부분의 매직 윈도우 디바이스는 한 개의 뷰만 요청합니다. 하지만 애플리케이션은 특정 뷰 구성을 가정해서는 안 됩니다. 예를 들어, 매직 윈도우 디바이스가 스테레오 출력이 가능하면 두 개의 뷰를 요청할 수 있지만, 성능상의 이유로 스테레오 모드를 끄면 한 개의 뷰로 돌아갈 수 있습니다. 비슷하게 HMD는 넓은 시야각이나 해상도가 다른 디스플레이를 위해 두 개보다 많은 뷰를 요청할 수도 있습니다.
뷰는 내부적으로 viewport
modifiable 플래그를 가지며, 이는 세션의 이 시점에서 requestViewportScale()
호출로 viewport 비율을 변경할 수 있는지를 나타냅니다. 이 플래그는 애니메이션 프레임 시작 시 true
로 설정되고, getViewport()
가
호출될 때 false
로 바뀝니다.
뷰는 내부적으로 requested
viewport scale 값을 가지며, 이 값은 이 뷰에 요청된 viewport 비율을 나타냅니다. 초기값은 1.0이고, 시스템이 동적 viewport 스케일링을 지원한다면
requestViewportScale()
메서드로 변경 가능합니다.
뷰는 내부적으로 current viewport
scale 값을 가지며, 이는 시스템이 내부적으로 사용하는 현재 viewport 비율을 나타냅니다. 초기값은 1.0이고, getViewport()
가
viewport 변경을 적용할 때 requested viewport scale과 일치하도록 갱신됩니다.
뷰는 reference space를 가지며, 이는 XRReferenceSpace
로
getViewerPose()
에서
이 뷰를 얻을 때 사용됩니다.
참고: 동적 viewport 스케일링을 사용하면 애플리케이션이 전체 viewport 대신 스케일
팩터를 적용해 뷰포트의 일부만 렌더링할 수 있습니다. 이는 매 프레임마다 효율적으로 변경될 수 있도록 설계되었습니다. 정확한 렌더링을 위해 XR 시스템과 애플리케이션이 활성 viewport에
대해 합의하는 것이 중요합니다. 애플리케이션은 하나의 애니메이션 프레임 안에서 requestViewportScale()
를
여러 번 호출할 수 있지만, 요청한 스케일은 해당 뷰의 getViewport()
가
호출될 때 적용됩니다. 애니메이션 프레임 내 첫 getViewport 호출이 변경을 적용하며(즉시 적용), 그 프레임 동안 해당 viewport를 고정시키고, 이후 프레임의 기본값으로
반영합니다. 시스템은 내부 성능 휴리스틱 또는 목표 프레임률에 따라 recommendedViewportScale
속성을 통해 권장값을 제공할 수도 있습니다.
enum {
XREye ,
"none" ,
"left" }; [
"right" SecureContext ,Exposed =Window ]interface {
XRView readonly attribute XREye eye ;readonly attribute unsigned long index ;readonly attribute double ?recommendedViewportScale ;undefined requestViewportScale (double ?); };
scale XRView includes XRViewGeometry ;
transform
은
해당 reference
space의 좌표계로 제공됩니다.
eye
속성은 해당 eye 정보를 설명합니다. 이 속성의 주요 목적은 미리 렌더링된 스테레오 콘텐츠가 각각의 눈에 맞는 콘텐츠를 정확히 표시하도록 보장하는
것입니다.
index
속성은 XRView
가 getViewerPose()
에
의해 views
배열에서 반환될 때의 오프셋을 나타냅니다.
옵션인 recommendedViewportScale
속성에는, UA가 requestViewportScale()
에
사용할 것을 권장하는 viewport 스케일 값이 들어 있습니다. 시스템이 권장값 휴리스틱이나 메서드를 구현하지 않으면 null
이 되고, null이 아니면 반드시
0.0보다 크고 1.0 이하의 수치여야 하며, 양자화(quantized)되어 세밀한 성능 또는 GPU 사용률 정보 노출을 방지해야 합니다.
참고: 권장 viewport scale은 가능한 값 목록 중 가장 가까운 값으로 반올림(quantize)하고, 경계값 근처에서는 히스테리시스(hysteresis)를 적용해 순간 변화가 일어나지 않게 하는 것이 좋습니다. (이로 인해 빠른 scale 변화가 시각적으로 거슬리거나 불편하지 않게 할 수 있습니다.)
각 XRView
는 session을 가지며, 이는 해당 뷰를 생성한 XRSession
입니다.
각 XRView
는 frame을 가지며, 이는 해당 뷰를 생성한 XRFrame
입니다.
각 XRView
는 underlying view를 가지며, 이는 이 객체가 나타내는 실제 뷰입니다.
requestViewportScale(scale)
메서드는 이 뷰포트의 requested viewport scale을 지정한 값으로 설정하도록 유저 에이전트에
요청합니다.
이 메서드를 XRView
xrview에 대해 호출하면, 유저 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
scale이 null 또는 undefined이면 단계를 중단합니다.
-
scale이 0.0 이하이면 단계를 중단합니다.
-
scale이 1.0보다 크면 scale을 1.0으로 설정합니다.
-
view를 xrview의 underlying view로 둡니다.
-
view의 requested viewport scale 값을 scale로 설정합니다.
참고: 이 메서드는 null
또는
undefined
인 scale 값을 무시하므로, 시스템에서 권장값을 제공하지 않더라도
view.requestViewportScale(view.recommendedViewportScale)
를 안전하게 사용할 수 있습니다.
active 플래그가 뷰 목록의
어떤 뷰에서든 변경되면, XRSession
session에 대해 다음 단계를 실행하여 뷰포트 업데이트를 할 수 있습니다:
-
layer를
renderState
의baseLayer
로 둡니다. -
layer가
null
이면 단계를 중단합니다. -
layer의 viewport 객체 목록을 빈 리스트로 설정합니다.
-
-
viewport를
XRViewport
로 두고, 스케일된 뷰포트 얻기를 view와 session에 연관된 전체 크기 뷰포트 목록에서 수행한 결과로 설정한다.
-
XRView
view와 XRSession
session에 대해 스케일링된 뷰포트 획득(obtain a scaled viewport) 알고리즘은 다음과 같습니다:
-
glFullSizedViewport를 전체 크기 뷰포트 목록에서 view에 연관된 WebGL viewport로 둡니다.
-
scale을 view의 current viewport scale로 둡니다.
-
유저 에이전트는 scale에 대해 최소 viewport scale factor를 적용해 clamp할 수 있습니다.
-
glViewport를 WebGL viewport의 새 인스턴스로 둡니다.
-
glViewport의
width
를 glFullSizedViewport의width
에 scale을 곱한 값 이하의 정수로 설정합니다. -
glViewport의
width
가 1보다 작으면 1로 설정합니다. -
glViewport의
height
를 glFullSizedViewport의height
에 scale을 곱한 값 이하의 정수로 설정합니다. -
glViewport의
height
가 1보다 작으면 1로 설정합니다. -
glViewport의
x
를 glFullSizedViewport의x
(포함)~glFullSizedViewport의x
+width
- glViewport의width
(포함) 사이의 정수로 설정합니다. -
glViewport의
y
를 glFullSizedViewport의y
(포함)~glFullSizedViewport의y
+height
- glViewport의height
(포함) 사이의 정수로 설정합니다. -
viewport를 새
XRViewport
로 session의 관련 realm에서 생성합니다. -
viewport의
x
를 glViewport의x
로 초기화합니다. -
viewport의
y
를 glViewport의y
로 초기화합니다. -
viewport의
width
를 glViewport의width
로 초기화합니다. -
viewport의
height
를 glViewport의height
로 초기화합니다. -
viewport를 반환합니다.
참고: 구체적인 정수 계산은 UA(유저 에이전트)에 위임됩니다. 단순히 width/height를 내림하고 x/y 오프셋을 그대로 적용하는 것도 유효하지만, 효율을 위해 2의 거듭제곱 픽셀 그리드에 맞추는 등 약간 조정할 수 있습니다. 스케일링된 뷰포트는 반드시 전체 크기 뷰포트 내에 완전히 포함되어야 하며, 위치·크기 계산은 세션 내에서 입력값이 동일하면 항상 동일한 결과를 반환해야 합니다.
7.3. 기본 뷰와 보조 뷰
뷰는 몰입형 경험을 위해 그리기가 반드시 필요한 경우 기본 뷰(primary view)입니다. 기본 뷰는 XRSession
전체
기간 동안 active 상태여야 합니다.
뷰는 콘텐츠가 해당 뷰를 렌더링하지 않아도 몰입형 경험이 가능할 때 보조 뷰(secondary view)입니다. 콘텐츠가 이 뷰를 렌더링하지 않을 경우, 유저 에이전트는 reprojection을 통해 이를 재구성할 수 있습니다. 보조 뷰는 "secondary-views" 기능이 활성화되지 않는 한 active가 될 수 없습니다.
보조 뷰의 예로는 비디오 캡처용 1인칭 관찰자 뷰, 또는 해상도와 시야가 다른 두 개의 쿼드 뷰(eye당 두 개) 등이 있습니다.
views
배열에 대한 잘못된 가정으로 인해 두 개 초과의 뷰가 주어지면 동작이 깨질 수 있습니다.
유저 에이전트가 reprojection 등 메커니즘을 통해 보조 뷰를 콘텐츠 대신 렌더링할 수 있으므로, 콘텐츠가 이런 보조 뷰를 직접 처리할 의도가 있는지, 아니면 그런 보조 뷰의 존재를 모르거나 처리하지 않을 의도인지를 구분하는 것이 바람직합니다.
이를 위해, 보조 뷰를 노출하는 유저 에이전트는 힌트로서 "secondary-views" 기능 디스크립터(feature descriptor)를 지원해야 합니다. 이 기능을 활성화한 콘텐츠는 다음을 수행해야 합니다:
-
views
배열의 크기가 프레임마다 바뀔 수 있음을 처리해야 합니다. 예를 들어 비디오 캡처가 활성화될 때 발생할 수 있습니다.
"secondary-views"가 활성화된 경우, 유저 에이전트는 필요에 따라 디바이스가 지원하는
보조 뷰를 XRSession
에
노출할 수 있습니다. 이 경우 유저 에이전트는 보조 뷰를 reprojection으로 재구성하지 않고 콘텐츠가 렌더하는 대로 사용해야 합니다.
참고: 최대 호환성을 위해 콘텐츠에서는 optionalFeatures
를 통해 "secondary-views"를 활성화하는 것이 권장됩니다.
보조 뷰의 프레임률이 더 낮을 경우, XRSession
은 다음
중 하나 이상의 동작을 할 수 있습니다:
-
보조 뷰가 활성화된 동안 전체 애플리케이션 프레임률을 낮출 수 있습니다.
-
views
배열에 일부 프레임만 보조 뷰를 포함할 수 있습니다. 이 경우 기본 뷰가 없는 프레임은 없어야 합니다. -
일부 프레임에서 보조 뷰의 렌더링 결과를 조용히 무시할 수 있습니다.
7.4. XRViewport
XRViewport
객체는 그래픽 표면의 뷰포트(사각형 영역)를 설명합니다.
[SecureContext ,Exposed =Window ]interface {
XRViewport readonly attribute long x ;readonly attribute long y ;readonly attribute long width ;readonly attribute long height ; };
x
와 y
속성은 표면 원점으로부터의 오프셋을,
width
와 height
속성은 뷰포트의 사각형 크기를 정의합니다.
뷰포트 값의 해석은 뷰포트가 연관된 그래픽 API의 관행에 따라 달라집니다:
-
XRWebGLLayer
와 함께 사용할 때x
와y
속성은 뷰포트 사각형의 좌하단 모서리(픽셀 단위)를 지정하며, 뷰포트 사각형은x
에서 오른쪽으로width
픽셀,y
에서 위로height
픽셀만큼 확장됩니다. 이 값들은 WebGL viewport 함수에 바로 전달할 수 있습니다.
XRView
의 모든 항목을
반복하면서, 각 XRViewerPose
에
대해 XRViewport
를
XRWebGLLayer
에서
가져와, 각 항목에 대해 적절한 WebGL
뷰포트를 설정하여 렌더링에 사용합니다.
xrSession. requestAnimationFrame(( time, xrFrame) => { const viewer= xrFrame. getViewerPose( xrReferenceSpace); gl. bindFramebuffer( xrWebGLLayer. framebuffer); for ( xrViewof viewer. views) { let xrViewport= xrWebGLLayer. getViewport( xrView); gl. viewport( xrViewport. x, xrViewport. y, xrViewport. width, xrViewport. height); // WebGL draw calls will now be rendered into the appropriate viewport. } });
8. 기하 프리미티브(Geometric Primitives)
8.1. 행렬(Matrices)
WebXR은 행렬(matrix)의 형태로 다양한 변환을 제공합니다. WebXR은 행렬 통신 시 WebGL의 관행을 따르며, 4x4 행렬은 16개 요소의 Float32Array
(열 우선 저장, column major)로 제공되며, 행렬은 컬럼 벡터에 대해 왼쪽에서 곱하는 방식으로 적용됩니다. 이들은 WebGL의 uniformMatrix4fv
함수에 바로 전달하거나, DOMMatrix
로
변환하거나, 다양한 외부 수학 라이브러리와 함께 사용할 수 있습니다.
Float32Array
로
배치됩니다:
[a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15]
이 행렬을 DOMPointReadOnly
타입의 컬럼 벡터에 다음과 같이 변환 연산으로 적용하면:
{x:X, y:Y, z:Z, w:1}
다음 결과를 얻습니다:
a0 a4 a8 a12 * X = a0 * X + a4 * Y + a8 * Z + a12 a1 a5 a9 a13 Y a1 * X + a5 * Y + a9 * Z + a13 a2 a6 a10 a14 Z a2 * X + a6 * Y + a10 * Z + a14 a3 a7 a11 a15 1 a3 * X + a7 * Y + a11 * Z + a15
8.2. 정규화(Normalization)
벡터 또는 쿼터니언을 정규화(normalize)해야 하는 알고리즘이 여럿 있으며, 이는 각 컴포넌트의 크기를 합쳐 1.0
이 되도록 스케일하는 것을 의미합니다.
정규화(normalize)를 컴포넌트 리스트에 적용할 때 UA는 다음 단계를 실행해야 합니다:
-
length를 각 컴포넌트 제곱의 합의 제곱근으로 둡니다.
-
length가
0
이면InvalidStateError
를 throw하고 단계를 중단합니다. -
각 컴포넌트를 length로 나눈 값으로 설정합니다.
8.3. XRRigidTransform
XRRigidTransform
은 position
과 orientation
으로 설명되는 변환(transform)입니다.
XRRigidTransform
을 해석할 때 orientation
이 항상 position
보다 먼저 적용됩니다.
XRRigidTransform
은 내부 행렬(internal matrix)을 가지며, 이는 행렬입니다.
[SecureContext ,Exposed =Window ]interface {
XRRigidTransform constructor (optional DOMPointInit = {},
position optional DOMPointInit = {}); [
orientation SameObject ]readonly attribute DOMPointReadOnly position ; [SameObject ]readonly attribute DOMPointReadOnly orientation ;readonly attribute Float32Array matrix ; [SameObject ]readonly attribute XRRigidTransform inverse ; };
XRRigidTransform(position, orientation)
생성자가 호출될 때 반드시 다음 단계를 실행해야 합니다:
-
transform을 새
XRRigidTransform
객체로 현재 realm에서 생성합니다. -
transform의
position
을 새DOMPointReadOnly
객체로 현재 realm에서 생성합니다. -
position 또는 orientation의 값 중 하나라도
NaN
또는infinity
등 비유한수이면TypeError
를 throw하고 단계를 중단합니다. -
transform의
position
의x
값에 position의 x dictionary 값,y
값에 y dictionary 값,z
값에 z dictionary 값,w
값에 w dictionary 값을 설정합니다. -
transform의
orientation
을 새DOMPointReadOnly
객체로 현재 realm에서 생성합니다. -
transform의
orientation
의x
값에 orientation의 x dictionary 값,y
값에 y dictionary 값,z
값에 z dictionary 값,w
값에 w dictionary 값을 설정합니다. -
transform의 내부 행렬을
null
로 둡니다. -
transform을 반환합니다.
position
속성은 변환의 평행이동 성분을 미터 단위 3차원 점으로 나타냅니다.
position
의
w
속성은 반드시 1.0
이어야 합니다.
orientation
속성은 변환의 회전 성분을 설명하는 쿼터니언입니다. orientation
은 반드시 길이 1.0
으로 정규화되어야 합니다.
matrix
속성은 position
과 orientation
속성으로 설명되는 변환을 행렬로 반환합니다. 이 속성은 반드시 행렬 얻기 알고리즘으로 계산되어야 합니다.
참고: 이 행렬을 컬럼 벡터에 선행 곱(premultiply)하면 orientation
에 해당하는 3D 회전이 먼저 적용되고, position
만큼 평행이동됩니다. 수학적으로는 컬럼 벡터 표기에서 M = T * R
이며, T
는 position
에 해당하는 평행이동 행렬이고 R
은 orientation
에 해당하는 회전 행렬입니다.
XRRigidTransform
transform에 대해 행렬 얻기(obtain the matrix) 알고리즘은 다음과 같습니다:
-
transform의 내부 행렬이
null
이 아니면 다음을 수행합니다:-
IsDetachedBuffer 연산을 내부 행렬에 대해 실행한 결과가
false
이면 transform의 내부 행렬을 반환합니다.
-
-
translation을 행렬로,
position
에 해당하는 컬럼 벡터 평행이동 행렬로 둡니다. 수학적으로position
이(x, y, z)
이면 이 행렬은 다음과 같습니다: -
rotation을 행렬로,
orientation
에 해당하는 컬럼 벡터 회전 행렬로 둡니다. 수학적으로orientation
이 단위 쿼터니언(qx, qy, qz, qw)
일 때 이 행렬은 다음과 같습니다: -
transform의 내부 행렬을 새
Float32Array
로 transform의 관련 realm에서, translation과 rotation을 translation이 왼쪽(translation * rotation
)이 되도록 곱한 결과로 설정합니다. 수학적으로 이 행렬은 다음과 같습니다: -
transform의 내부 행렬을 반환합니다.
inverse
속성은 XRRigidTransform
transform에 대해, transform으로 변환된 객체에 다시 적용하면 원래 자세로 돌려놓는 XRRigidTransform
을
transform의 관련 realm에서 반환합니다.
이 속성은 lazy 평가가 권장됩니다. inverse
로 반환된 XRRigidTransform
의 inverse
는
반드시 transform을 반환해야 합니다.
XRRigidTransform
의 position
이 { x: 0, y: 0, z: 0 w: 1 }
이고 orientation
이 { x: 0, y: 0, z: 0, w: 1 }
인 경우를 단위 변환(identity transform)이라고 합니다.
XRRigidTransform
B와 A를 Realm realm에서 곱하기 알고리즘은 다음과 같습니다:
-
result를 새
XRRigidTransform
객체로 realm에서 생성합니다. -
result의
matrix
에 새Float32Array
를 realm에서 생성, B의matrix
를 왼쪽에서 A의matrix
에 곱한 결과로 설정합니다. -
result의
orientation
에 새DOMPointReadOnly
를 realm에서 생성, result의matrix
의 좌상단 3x3 부분행렬이 나타내는 쿼터니언으로 설정합니다. -
result의
position
에 새DOMPointReadOnly
를 realm에서 생성, result의matrix
의 4번째 컬럼에 해당하는 벡터로 설정합니다. -
result를 반환합니다.
result는 A의 소스 공간에서 B의 목적지 공간으로의 변환입니다.
참고: 이것은 XRRigidTransform
을 구성하는 것과 같으며, orientation
은 A와 B의 orientation 합성, position
은 A의 position을 B의 orientation으로 회전시킨 뒤 B의 position을 더한 값과 같습니다.
9. 자세(Pose)
9.1. XRPose
XRPose
는 XRSpace
를 기준으로 한 공간
내 위치와 방향을 설명합니다.
[SecureContext ,Exposed =Window ]interface { [
XRPose SameObject ]readonly attribute XRRigidTransform transform ; [SameObject ]readonly attribute DOMPointReadOnly ?linearVelocity ; [SameObject ]readonly attribute DOMPointReadOnly ?angularVelocity ;readonly attribute boolean emulatedPosition ; };
transform
속성은 기준 XRSpace
에 대한 위치와
방향을 설명합니다.
linearVelocity
속성은 기준 XRSpace
에 대해 초당
미터(m/s) 단위의 선속도를 설명합니다. 유저 에이전트가 이 값을 채울 수 없는 경우 null
을 반환할 수 있습니다.
angularVelocity
속성은 기준 XRSpace
에 대해 초당
라디안(rad/s) 단위의 각속도를 설명합니다. 유저 에이전트가 이 값을 채울 수 없는 경우 null
을 반환할 수 있습니다.
emulatedPosition
속성은 transform
이 센서 판독에 기반한 실시간 트래킹 6DoF 자세를 나타낼 때는
false
이고, position
값에 목/팔 모델 등 계산 오프셋(computed offset)이 포함될 때는 true
입니다. 추정 바닥 높이는
XRPose
가 계산 오프셋을
포함하는지 여부를 판단할 때 고려되지 않아야 합니다.
9.2. XRViewerPose
XRViewerPose
는 XRPose
로, XR 디바이스가 트래킹하는
XR 씬의 뷰어(viewer)의 상태를 설명합니다. 뷰어는 트래킹된 하드웨어, 하드웨어에 대한 사용자의 머리 위치, 또는 XR
씬에서 일련의 뷰포인트를 계산하는 다른 방법을 나타낼 수 있습니다. XRViewerPose
는
반드시 XRReferenceSpace
를
기준으로만 질의할 수 있습니다.
XRPose
의 값들 외에도,
뷰포인트 및 투영 행렬을 나타내는 강체 변환(rigid transform)을 포함하는 뷰(view) 배열을 제공합니다. 이 값들은 XR 씬의 프레임을 렌더링할 때 애플리케이션에서 사용해야 합니다.
[SecureContext ,Exposed =Window ]interface :
XRViewerPose XRPose { [SameObject ]readonly attribute FrozenArray <XRView >views ; };
views
배열은 XR 장면의 각 뷰포인트를 설명하는 XRView
들의 시퀀스이며,
XRViewerPose
가
질의된 XRReferenceSpace
를
기준으로 합니다. 배열에 있는 XR 장면의 모든 view를 렌더링해야 XR 디바이스에 올바르게
표시됩니다. 각 XRView
에는
뷰포인트와 프로젝션 행렬을 나타내는 강체 변환이 포함되어 있으며, 필요할 때 레이어에서 XRViewport
를
질의하는 데 사용할 수 있습니다.
참고: XRViewerPose
의
transform
값은 씬의 관전자 뷰(spectator view)나 다중 사용자 상호작용용 뷰어의 그래픽적 표현 위치 지정에 사용할 수 있습니다.
10. 입력
10.1. XRInputSource
XRInputSource
는 XR 입력 소스를 나타내며, 이는
사용자가 뷰어와 동일한 가상 공간에서 특정 동작을 수행할 수 있도록 하는 모든
입력 메커니즘입니다. XR 입력 소스의 예로는
핸드헬드 컨트롤러, 광학적으로 트래킹되는 손, 뷰어의 포즈를 기반으로 동작하는
시선 기반 입력 방식 등이 있습니다. 전통적인 게임패드, 마우스, 키보드처럼 XR 디바이스와 명시적으로 연결되지 않은 입력 메커니즘은 XR 입력 소스로 간주해서는 안 됩니다.
enum {
XRHandedness ,
"none" ,
"left" };
"right" enum {
XRTargetRayMode "gaze" ,"tracked-pointer" ,"screen" ,"transient-pointer" }; [SecureContext ,Exposed =Window ]interface {
XRInputSource readonly attribute XRHandedness handedness ;readonly attribute XRTargetRayMode targetRayMode ; [SameObject ]readonly attribute XRSpace targetRaySpace ; [SameObject ]readonly attribute XRSpace ?gripSpace ; [SameObject ]readonly attribute FrozenArray <DOMString >profiles ;readonly attribute boolean skipRendering ; };
참고: XRInputSource
인터페이스는 WebXR Gamepads Module에 의해 확장되기도 합니다.
handedness
속성은 해당 XR 입력 소스가 어느 손에 할당되어 있는지(있는 경우)를 나타냅니다. 자연스러운
handedness가 없는 입력 소스(예: HMD 장착 컨트롤러)나 handedness를 알 수 없는 경우 이 속성은 반드시 "none"
으로
설정해야 합니다.
targetRayMode
속성은 타겟 레이를 생성하는 방식을 설명하며, 필요하다면
애플리케이션이 타겟 레이를 사용자에게 어떻게 보여줄지 알려줍니다.
-
gaze
는 타겟 레이가 뷰어에서 시작해 뷰어가 바라보는 방향을 따른다는 의미입니다. (HMD 맥락에서는 보통 "시선 입력(gaze input)" 장치로 불립니다.) -
tracked-pointer
는 타겟 레이가 핸드헬드 디바이스나 손 트래킹 메커니즘에서 시작되며, 사용자가 손 또는 기기를 사용해 포인팅하고 있음을 나타냅니다. 타겟 레이의 방향은 플랫폼 별 인체공학 가이드라인을 따라야 하며, 없다면 사용자의 집게손가락을 곧게 뻗었을 때의 방향을 따라야 합니다.XRSystem
이 핸드헬드 디바이스의 일부가 실제 접촉 지점(예: 펜팁)임을 인지하면, 해당 지점에서 타겟 레이가 시작되어야 합니다. -
screen
은 입력 소스가 인라인 세션의 출력 컨텍스트와 연결된 캔버스 요소에서 발생한 상호작용(예: 마우스 클릭, 터치 이벤트)임을 나타냅니다. -
transient-pointer
는 입력 소스가 특정 하드웨어가 아닌 운영체제 상의 상호작용 의도에 의해 생성된 것임을 나타냅니다. 예로는 민감한 정보(시선 등)에 기반한 사용자 의도, 웹드라이버가 생성한 입력, 보조 기술에서 생성된 입력 등이 있습니다. 이는 보조 기술이 기본 입력으로도 사용되는 경우에만 사용되어야 하며, W3C 디자인 원칙상 보조 기술 사용 사실이 드러나지 않도록 해야 합니다.
targetRaySpace
속성은 XRSpace
타입으로, 네이티브 원점이 해당
XRInputSource
의
선호 포인팅 레이(보통 -Z
축 방향)의 위치와 방향을 targetRayMode
에
따라 트래킹합니다.
targetRayMode
가
"transient-pointer"
인
입력 소스의 경우, targetRaySpace
는
상호작용 시작 시점의 타겟을 향하는 레이를 나타냅니다. 해당 pose는 이 XRInput의 gripSpace 내에서 정적이어야 합니다.
gripSpace
속성은 XRSpace
타입으로, 가상의
객체가 사용자의 손에 들려 있는 것처럼 렌더링되도록 해야 하는 pose를 트래킹하는 네이티브 원점을 가집니다. 사용자가 막대기를 쥐고 있다면, 이 XRSpace
의 네이티브 원점은
손가락이 말려있는 중심에 위치하며, -Z
축은 막대기 길이 방향으로 엄지 방향을 가리킵니다. X
축은 손등에 수직이며, 오른손 손등은
+X
, 왼손 손등은 -X
방향입니다. Y
축은 X
와 Z
의 관계로 정해지며,
+Y
는 대략 사용자의 팔 방향입니다.
skipRendering
속성은 이 입력이 화면에 보이지만 현재 세션에서 추가로
렌더링할 필요가 없음을 나타냅니다. skipRendering
이 true이고 targetRayMode가 "tracked-pointer"라면, 유저 에이전트는 해당 XR 입력 소스가 반드시 사용자에게 표시되도록 해야 합니다.
컨트롤러가 사용자에게 표시되는 예로는 디스플레이와 사용자 사이에 컨트롤러가 있거나, 디스플레이가 투명하거나, 운영체제에서 컨트롤러를 렌더링하는 경우 등이 있습니다.
skipRendering
은 컨트롤러 등 입력 소스를 별도로 렌더링하지 않아도 된다는 힌트입니다. pick ray와 커서는 여전히 렌더링되어야 합니다.
targetRayMode
가 "transient-pointer"
인
입력 소스의 경우, gripSpace
는
관련된 사용자 제스처가 있다면 그 제스처에, 없다면 사용자가 제어하는 다른 space(예: ViewerSpace, gripSpace, 다른 XRInput의 targetRaySpace 등)로
설정되어야 합니다. 이를 통해 사용자가 여전히 targetRaySpace를 조작할 수 있습니다.
gripSpace
는 입력 소스가 본질적으로 트래킹 불가(예: targetRayMode
가
"gaze"
또는 "screen"
인
경우)라면 반드시 null
이어야 합니다.
profiles
속성은 입력 소스의 선호 시각 표현과 동작을 모두 나타내는 리스트 형식의 input profile name들입니다.
input profile name은 공백 없는 ASCII 소문자 DOMString
으로,
여러 단어는 하이픈(-
)으로 결합됩니다. 장치 제조사의 용어를 가능하면 그대로 사용해 서술적 이름을 정해야 하며, 플랫폼에서 USB vendor/product ID 등
적절한 식별자를 제공한다면 사용할 수 있습니다. 단일 장치만 고유하게 식별하는 값(예: 시리얼 넘버)은 사용 금지입니다. input profile
name에는 handedness 정보가 포함되면 안 됩니다. 여러 유저 에이전트가 동일 디바이스를 노출할 경우 같은 input profile
name을 보고하려고 노력해야 하며, WebXR Input
Profiles Registry가 관리 권장 위치입니다.
profiles는 구체성 높은 순서대로 제시됩니다. 첫 번째 이후 input profile name들은 대체 표현(더 일반적이거나 이전 버전 등)을 의미하며, 모든 profile들은 서로의 layout의 superset/subset이어야 합니다.
XRSession
의
mode가 "inline"
이면,
profiles
는
반드시 빈 리스트여야 합니다.
유저 에이전트는 상황에 따라 적절한 generic input profile name이나 빈 리스트만 보고할 수 있습니다. 예를 들어 입력 장치를 신뢰성 있게 식별할 수 없거나, 일치하는 프로필이 없거나, 사용 장치 노출을 감추려는 경우입니다.
예를 들어 Samsung HMD Odyssey 컨트롤러는 표준 Windows Mixed Reality 컨트롤러의 변형 디자인으로, 입력 레이아웃이
동일합니다. 따라서 Samsung HMD Odyssey 컨트롤러의 profiles
는
["samsung-odyssey", "microsoft-mixed-reality", "generic-trigger-squeeze-touchpad-thumbstick"]
과
같이 될 수 있습니다. 첫 번째 프로필이 가장 구체적으로 외형을 나타내며, 두 번째는 대체, 마지막은 가장 일반적인 타입입니다. (트리거, 스퀴즈 버튼, 터치패드, 썸스틱이 있는 컨트롤러임을
의미)
Valve Index 컨트롤러는 HTC Vive 컨트롤러와 호환되지만 추가 버튼과 축이 있습니다. 이 경우 profiles
는
["valve-index", "htc-vive", "generic-trigger-squeeze-touchpad-thumbstick"]
이 될 수 있습니다. 이때
"valve-index"는 "htc-vive"의 superset이며, 외형 차이는 허용된 것으로 간주합니다. 마지막은 마찬가지로 일반 fallback입니다.
(문자열은 예시이며 실제
프로필 이름은 WebXR
Input Profiles Registry에서 관리됩니다.)
참고: XRInputSource
들은
XRSession
의
inputSources
배열에서 "라이브"로 유지됩니다. 즉, 그 값들은 인플레이스 갱신됩니다. 그러므로 한 프레임에서 XRInputSource의 속성 참조를 저장하고 이후 프레임에서 비교하는 것은 상태 변화를
감지하는 데 쓸 수 없습니다. 상태를 프레임 간 비교하려면 값을 복사해서 사용해야 합니다.
XR 입력 소스는 기본 입력 소스(primary input
source)일 수 있으며, 이는 기본 동작(primary action)을 지원함을 의미합니다. 기본 동작은 플랫폼별 동작으로, 트리거, 터치패드, 버튼 누르기, 음성 명령, 손 제스처
등입니다. 이 때 selectstart
,
selectend
,
select
이벤트가 발생합니다. 플랫폼 가이드에 기본 입력이 정의되어 있다면 그것을, 그렇지 않으면 UA에서 임의로 선택합니다. 장치는 최소 하나의 기본 입력 소스를 지원해야 합니다.
XR 입력 소스는 트래킹 입력 소스(tracked input source)일 수 있으며, 이는 기본 동작을 지원하지 않는 입력입니다. 주로 pose 데이터를 제공하는 용도입니다. 참고: 트래킹 입력 소스의 예로는 사용자의 다리나 소품에 부착된 트래커, 제스처 인식이 없는 손 트래킹 등이 있습니다.
XR 입력 소스
source가 XRSession
session에서 기본
동작을 시작할 때, UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 입력 소스 이벤트 발생 (이름:
selectstart
, frame frame, source source)를 추가합니다.
XR 입력 소스
source가 XRSession
session에서 기본
동작을 끝낼 때 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 다음 단계를 추가합니다:
-
입력 소스 이벤트 발생 (이름:
select
, frame frame, source source) -
입력 소스 이벤트 발생 (이름:
selectend
, frame frame, source source)
-
각 XR 입력 소스는 기본 스퀴즈 동작(primary
squeeze action)을 정의할 수 있습니다. 기본 스퀴즈 동작은 플랫폼별 동작으로, grip 트리거 누르기, 손 쥐기 제스처 등이며, squeezestart
,
squeezeend
,
squeeze
이벤트가 발생합니다. 플랫폼 가이드에 권장 스퀴즈 동작이 정의되어 있다면 그것을, 그렇지 않으면 UA가 임의로 선택할 수 있습니다.
XR 입력 소스
source가 XRSession
session에서 기본 스퀴즈 동작을 시작할 때 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 입력 소스 이벤트 발생 (이름:
squeezestart
, frame frame, source source)를 추가합니다.
XR 입력 소스
source가 XRSession
session에서 기본 스퀴즈 동작을 끝낼 때 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 다음 단계를 추가합니다:
-
입력 소스 이벤트 발생 (이름:
squeeze
, frame frame, source source) -
입력 소스 이벤트 발생 (이름:
squeezeend
, frame frame, source source)
-
플랫폼별 동작에 따라 기본 동작 또는 기본 스퀴즈 동작이 중단/취소될 수 있습니다. 예를 들어, XR 입력 소스가 기본 동작 또는 기본 스퀴즈 동작이 진행 중에 XR 디바이스에서 제거될 수 있습니다.
XR 입력 소스
source가 XRSession
session에서 기본
동작이 취소된 경우 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 입력 소스 이벤트 발생 (
XRInputSourceEvent
, 이름:selectend
, frame frame, source source)을 추가합니다.
XR 입력 소스
source가 XRSession
session에서 기본 스퀴즈 동작이 취소된 경우 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, time을 동작 발생 시간으로 설정합니다. -
태스크 큐에 입력 소스 이벤트 발생 (
XRInputSourceEvent
, 이름:squeezeend
, frame frame, source source)을 추가합니다.
10.2. 일시적 입력(Transient input)
일부 XR 디바이스는 일시적 입력 소스(transient input sources)를 지원할 수 있으며, 이러한 경우 XR 입력 소스는 일시적 동작(transient action)을 수행하는 동안에만 의미를 가집니다. 즉, 기본 입력 소스의 기본 동작이나, 트래킹 입력 소스의 디바이스별 보조 동작(auxiliary action)을 의미합니다.
예를 들어, "inline"
XRSession
에서
마우스, 터치, 또는 스타일러스 입력이 발생하는 경우를 들 수 있습니다. 이 경우 반드시 XRInputSource
를
일시적으로 생성해야 하며, targetRayMode
가
screen
으로
설정되어야 합니다. 이 입력은 주요 동작으로
간주되며, 주 포인터에 대해, 그리고 주 포인터가 아닌 경우에는 비주요 보조 동작으로 처리됩니다.
또 다른 예로는, 운영체제에서 사용자의 민감한 정보(예: 시선 기반 상호작용)로부터 파생된 입력 의도가 직접적으로 노출될 수 없는 경우가 있습니다. 이 경우 XRInputSource
의
일시적 인스턴스가 생성되며, targetRayMode
가
transient-pointer
로
설정되어 기본 동작(primary
action)으로 처리됩니다.
일시적 입력 소스는 일시적 동작이 지속되는 동안에만 세션의 활성 XR 입력 소스 목록에 존재합니다.
일시적 입력 소스는 비일시적 기본 동작 알고리즘 대신 아래 순서로 일시적 동작을 처리합니다:
일시적 입력
소스 source가 XRSession
session에서 일시적
동작을 시작할 때 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, 동작 발생 시간을 기준으로 합니다. -
태스크 큐에 다음 단계를 추가합니다:
-
필요한 경우, XR 입력 소스 동작에 의해 생성된
"pointerdown"
이벤트를 발생시킵니다. -
XR 입력 소스 추가를 활성 XR 입력 소스 목록에 수행합니다.
-
일시적 동작이 기본 동작이라면, 입력 소스 이벤트 발생 (이름:
selectstart
, frame frame, source source)을 실행합니다.
-
일시적 입력
소스 source가 XRSession
session에서 일시적
동작을 끝낼 때 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, 동작 발생 시간을 기준으로 합니다. -
태스크 큐에 다음 단계를 추가합니다:
-
일시적 동작이 기본 동작이라면, 입력 소스 이벤트 발생 (이름:
select
, frame frame, source source)을 실행합니다. -
필요한 경우, XR 입력 소스 동작에 의해 생성된
"click"
이벤트를 발생시킵니다. -
일시적 동작이 기본 동작이라면, 입력 소스 이벤트 발생 (이름:
selectend
, frame frame, source source)을 실행합니다. -
XR 입력 소스 제거를 활성 XR 입력 소스 목록에서 수행합니다.
-
필요한 경우, XR 입력 소스 동작에 의해 생성된
"pointerup"
이벤트를 발생시킵니다.
-
일시적 입력
소스 source가 XRSession
session에서 일시적
동작이 취소된 경우 UA는 반드시 다음 단계를 실행해야 합니다:
-
frame을 새
XRFrame
으로 session의 관련 realm에서 생성,session
session, 동작 발생 시간을 기준으로 합니다. -
태스크 큐에 다음 단계를 추가합니다:
-
일시적 동작이 기본 동작이라면, 입력 소스 이벤트 발생 (이름:
selectend
, frame frame, source source)을 실행합니다. -
XR 입력 소스 제거를 활성 XR 입력 소스 목록에서 수행합니다.
-
필요한 경우, XR 입력 소스 동작에 의해 생성된
"pointerup"
이벤트를 발생시킵니다.
-
10.3. XRInputSourceArray
XRInputSourceArray
는 리스트 형태의 XRInputSource
들을 나타냅니다.
frozen array type 대신, 리스트의 내용이 시간에 따라 변할 수 있는 경우(예: XRSession
의
inputSources
속성 등)에 사용됩니다.
[SecureContext ,Exposed =Window ]interface {
XRInputSourceArray iterable <XRInputSource >;readonly attribute unsigned long length ;getter XRInputSource (unsigned long ); };
index
XRInputSourceArray
의
length
속성은 XRInputSourceArray
에
몇 개의 XRInputSource
가
포함되어 있는지 나타냅니다.
XRInputSourceArray
의
인덱스 속성 getter(indexed property getter)는 지정된 인덱스의
XRInputSource
를
반환합니다.
11. 레이어(Layers)
참고: 이 명세에서는 XRWebGLLayer
레이어만 정의되어 있지만, 향후 명세 확장에서는 추가적인 레이어 타입과 해당 레이어가 사용하는 이미지 소스가 추가될 수 있습니다.
11.1. XRLayer
[SecureContext ,Exposed =Window ]interface :
XRLayer EventTarget {};
XRLayer
는 XRWebGLLayer
및 향후 확장에서 도입될 기타 레이어 타입의 기본 클래스입니다.
11.2. XRWebGLLayer
XRWebGLLayer
는 WebGL 프레임버퍼를 제공하여 3D 그래픽의 하드웨어 가속 렌더링이 XR 디바이스에 표시될 수 있도록 하는 레이어입니다.
typedef (WebGLRenderingContext or WebGL2RenderingContext );
XRWebGLRenderingContext dictionary {
XRWebGLLayerInit boolean =
antialias true ;boolean =
depth true ;boolean =
stencil false ;boolean =
alpha true ;boolean =
ignoreDepthValues false ;double = 1.0; }; [
framebufferScaleFactor SecureContext ,Exposed =Window ]interface :
XRWebGLLayer XRLayer {constructor (XRSession ,
session XRWebGLRenderingContext ,
context optional XRWebGLLayerInit = {}); // Attributes
layerInit readonly attribute boolean antialias ;readonly attribute boolean ignoreDepthValues ;attribute float ?fixedFoveation ; [SameObject ]readonly attribute WebGLFramebuffer ?framebuffer ;readonly attribute unsigned long framebufferWidth ;readonly attribute unsigned long framebufferHeight ; // MethodsXRViewport ?getViewport (XRView ); // Static Methods
view static double getNativeFramebufferScaleFactor (XRSession ); };
session
각 XRWebGLLayer
는 context 객체를 가지며, 초기값은 null
이고, 이는 WebGLRenderingContext
혹은 WebGL2RenderingContext
의
인스턴스입니다.
각 XRWebGLLayer
는 session을 가지며, 이는 해당 레이어를 생성한 XRSession
입니다.
XRWebGLLayer(session, context, layerInit)
생성자가 호출될 때 반드시 다음 단계를 실행해야 합니다:
-
layer를 새
XRWebGLLayer
객체로 session의 관련 realm에서 생성합니다. -
session의 ended 값이
true
라면InvalidStateError
를 throw하고 단계를 중단합니다. -
context가 손실(lost)된 경우
InvalidStateError
를 throw하고 단계를 중단합니다. -
session이 immersive session이고 context의 XR compatible 불리언이
false
라면,InvalidStateError
를 throw하고 단계를 중단합니다. -
layer의 context를 context로 초기화합니다.
-
layer의 session을 session으로 초기화합니다.
-
layer의
ignoreDepthValues
를 다음과 같이 초기화합니다:- layerInit의
ignoreDepthValues
값이false
이고 XR Compositor가 depth 값을 사용할 경우: -
layer의
ignoreDepthValues
를false
로 초기화합니다. - 그 외의 경우:
-
layer의
ignoreDepthValues
를true
로 초기화합니다.
- layerInit의
-
layer의 composition enabled 불리언을 다음과 같이 초기화합니다:
- session이 inline session인 경우:
-
layer의 composition enabled를
false
로 초기화합니다. - 그 외의 경우:
-
layer의 composition enabled 불리언을
true
로 초기화합니다.
-
- layer의 composition enabled 불리언이
true
일 때: -
-
scaleFactor를 layerInit의
framebufferScaleFactor
로 둡니다. -
여기서 user agent는 필요에 따라 scaleFactor를 조정(예: 2의 제곱수로 맞추기 등)할 수 있습니다.
-
framebufferSize를 권장 WebGL 프레임버퍼 해상도에 각 width/height를 scaleFactor로 곱한 값으로 둡니다.
-
layer의
framebuffer
를 새WebGLFramebuffer
로 context의 관련 realm에서, opaque framebuffer로 framebufferSize 크기와 context, session을 session으로, layerInit의depth
,stencil
,alpha
값을 사용해 생성합니다. -
session의 XR 디바이스에 맞는 자원(예: GPU 메모리 버퍼 등)을 할당·초기화합니다.
-
자원 생성에 실패하면
OperationError
를 throw하고 단계를 중단합니다.
- 그 외의 경우:
-
-
layer의
antialias
를 layer의context
의 실제 context 파라미터antialias
값으로 초기화합니다. -
layer의
framebuffer
를null
로 초기화합니다.
-
- layer의 composition enabled 불리언이
-
layer를 반환합니다.
참고: XRWebGLLayer
의
composition enabled 불리언이 false
로 설정된 경우,
XRWebGLLayerInit
객체의 모든 값은 무시됩니다. 이미 WebGLRenderingContext
의
기본 프레임버퍼가 해당 context의 실제 context 파라미터로 할당되어 있으며, 이는 재정의할 수 없기 때문입니다.
context
속성은 WebGLRenderingContext
로, 이 XRWebGLLayer
가 생성될 때 사용된 context입니다.
각 XRWebGLLayer
는 composition enabled 불리언을 가지며, 초기값은 true
입니다.
false
로 설정되면, XRWebGLLayer
는 자체 WebGLFramebuffer
를
할당해서는 안 되며, XRWebGLLayer
의
모든 framebuffer
관련 속성은 context의
기본 프레임버퍼 속성을 그대로 반영해야 합니다.
framebuffer
속성은 XRWebGLLayer
의
인스턴스에 대해 WebGLFramebuffer
인스턴스이며, composition enabled가 true
일 때 opaque로 표시되고, 그렇지
않으면 null
입니다. framebuffer
의 크기는 XRWebGLLayer
가 생성된 이후 개발자가 변경할 수 없습니다.
opaque framebuffer는
표준 WebGLFramebuffer
와
동일하게 동작하지만, 다음과 같은 차이로 기본 프레임버퍼처럼
동작합니다:
-
opaque framebuffer는 WebGL 1.0에서도 안티앨리어싱을 지원할 수 있습니다.
-
opaque framebuffer의 attachment는 검사하거나 변경할 수 없습니다.
framebufferTexture2D
나framebufferRenderbuffer
,deleteFramebuffer
,getFramebufferAttachmentParameter
를 opaque framebuffer에 대해 호출하면 반드시INVALID_OPERATION
오류가 발생해야 합니다. -
opaque framebuffer는 관련 session을 가지며, 이는 해당 framebuffer가 생성된
XRSession
입니다. -
opaque framebuffer는
requestAnimationFrame()
콜백 외부에서는 incomplete 상태로 간주됩니다. 자신의 session의requestAnimationFrame()
콜백이 아닐 때checkFramebufferStatus
를 호출하면 반드시FRAMEBUFFER_UNSUPPORTED
오류가 발생해야 하며, clear/draw/read 시도 시INVALID_FRAMEBUFFER_OPERATION
오류가 발생해야 합니다. -
opaque framebuffer가
depth
true
로 초기화되면 depth buffer가 붙습니다. -
opaque framebuffer가
stencil
true
로 초기화되면 stencil buffer가 붙습니다. -
opaque framebuffer의 color buffer는
alpha
가true
일 때만 알파 채널을 가집니다. -
XR Compositor는 opaque framebuffer의 색상을 premultiplied alpha로 간주합니다. 이는
premultipliedAlpha
값과 무관합니다.
참고: User agent는 true
로 설정된 depth
와
stencil
값을 반드시 존중해야 하며, 이는 WebGL에서 드로잉 버퍼 생성과 유사한 동작입니다.
opaque framebuffer에
연결된 버퍼는 최초 생성 시 또는 각 XR
animation frame 처리 전 아래 표의 값으로 반드시 clear되어야 합니다. 이는 WebGL context의 기본 프레임버퍼와 동일한
동작입니다. opaque
framebuffer는 WebGL context의 preserveDrawingBuffer
값과 관계없이 항상 clear됩니다.
버퍼 | Clear 값 |
---|---|
Color | (0, 0, 0, 0) |
Depth | 1.0 |
Stencil | 0 |
참고: 구현체는 개발자가 다른 프로세스의 버퍼 내용을 얻지 못한다는 보장을 할 수 있다면, opaque framebuffer의 암시적 clear 동작을 최적화해 생략할 수 있습니다. 예를 들어 개발자가 명시적으로 clear를 수행하면 암시적 clear는 필요 없습니다.
XRWebGLLayer
를 alpha
true
로 생성하면 framebuffer
는 RGBA
색상 포맷의 텍스처로 지원되어야 합니다.
XRWebGLLayer
를 alpha
false
로 생성하면 framebuffer
는 RGB
색상 포맷의 텍스처로 지원되어야 합니다.
하지만 XR Compositor
는 framebuffer
의
버퍼 픽셀을 SRGB8_ALPHA8
또는 SRGB8
colorFormat
으로
처리해야 합니다.
참고: 즉, XR Compositor는 RGBA
나 RGB
텍스처 백킹에 대해 감마 변환을 수행하면 안 됩니다. 그렇지 않으면 최종 렌더링된 픽셀이 너무 밝아져 일반 2D WebGLRenderingContext
렌더링과 일치하지 않습니다.
XRWebGLLayer
가 immersive session의
baseLayer
로
설정될 때, opaque
framebuffer의 내용은 XR animation frame이 완료된 직후 immersive XR 디바이스에 표시됩니다. 단, 이전 XR animation frame
이후 아래 중 하나가 발생한 경우에 한합니다:
-
immersive session의
baseLayer
가 변경된 경우. -
clear
,drawArrays
,drawElements
, 또는 이와 유사하게 프레임버퍼 색상값에 영향을 주는 렌더링 연산이 opaque framebuffer가 현재 바인딩된WebGLRenderingContext
에 대해 호출된 경우.
opaque framebuffer가 immersive XR 디바이스에 표시되기 전, UA는 모든 렌더링 연산이 해당 opaque framebuffer에 flush되었는지 보장해야 합니다.
각 XRWebGLLayer
는 target framebuffer를 가지며, composition
enabled가 true
면 framebuffer
,
아니면 context의 기본
프레임버퍼입니다.
framebufferWidth
및 framebufferHeight
속성은 target
framebuffer의 attachments의 가로/세로 크기를 반환합니다.
antialias
속성은 target
framebuffer가 UA가 선택한 방식으로 안티앨리어싱을 지원하면 true
, 아니면 false
입니다.
ignoreDepthValues
속성이 true
면, XR Compositor는 렌더링 시 depth
buffer attachment 값을 사용해서는 안 됩니다. false
면 해당 depth buffer 내용이 XR Compositor에 의해 사용되며, 씬의 깊이 정보가 반영되어야 함을 의미합니다.
버퍼에 저장되는 depth 값은 0.0
~1.0
사이여야 하며, 0.0
은 depthNear
,
1.0
은 depthFar
거리를 의미합니다. 중간 값은 선형 보간됩니다(WebGL 기본 동작, 자세한 내용은 depthRange 함수
참고).
참고: 씬의 depth buffer가 compositor에서 사용 가능하면, 일부 플랫폼에서 reprojection 품질이나 시각적 편안함 개선이 가능합니다.
fixedFoveation
속성은 XR Compositor의 foveation(가변 해상도) 정도를 제어합니다. UA나
디바이스가 이 속성을 지원하지 않으면 get 시 null
을 반환하고, set은 no-op이어야 합니다. fixedFoveation
값을 0 미만으로 설정하면 0, 1 초과로 설정하면 1이 됩니다. 0은 최소, 1은 최대 foveation입니다. 해석 방식은 UA에 따라 다를 수 있습니다. 값이 변경되면 다음 XRFrame
에 반영됩니다.
참고: fixed foveation은 사용자의 시야 가장자리에서 렌더링 해상도를 줄여 GPU fill 성능 한계를 극복할 수 있는 기술입니다. 전력 소비를 줄이고, 텍스처 해상도를 높일 수 있어 낮은 대비의 배경 이미지에 효과적이지만, 텍스트나 세밀한 이미지는 덜 효과적입니다. 프레임마다 조절해 성능/품질 트레이드오프를 최적화할 수 있습니다.
각 XRWebGLLayer
는 전체 크기 뷰포트
목록(list of full-sized viewports)을 반드시 가지고, 이는 리스트로 각 view마다 하나의 WebGL
viewport를 포함합니다. 여기에 현재 active가 아니지만 세션에서 active가 될 수 있는 secondary view도 포함됩니다. 각 뷰포트의 width
와
height
는
0보다 커야 하며, target framebuffer 경계를 넘으면 안 됩니다. 뷰포트는 겹치면 안 됩니다. composition enabled가 false
면, 전체
크기 뷰포트 목록은 context의 전체 기본 프레임버퍼를 덮는 단일 WebGL
viewport만 포함해야 합니다.
각 XRWebGLLayer
는 뷰포트 객체 목록(list of
viewport objects)을 반드시 가지며, 현재 노출된 각 active view마다 하나의 XRViewport
를
포함합니다.
getViewport()
는 주어진 XRView
가 이 레이어에 렌더링 시 사용할 XRViewport
를
조회합니다.
getViewport(view)
메서드가 XRWebGLLayer
layer에서 호출되면, 아래 단계를 반드시 실행해야 합니다:
-
session을 view의 session으로 둡니다.
-
frame을 session의 animation frame으로 둡니다.
-
session이 layer의 session과 다르면
InvalidStateError
를 throw하고 중단합니다. -
frame의 active 불리언이
false
면InvalidStateError
를 throw하고 중단합니다. -
view의 frame이 frame과 다르면
InvalidStateError
를 throw하고 중단합니다. -
viewport modifiable 플래그가
true
이고, view의 requested viewport scale이 current viewport scale과 다르면:-
뷰포트 객체 목록에서 view와 연관된
XRViewport
를 스케일된 뷰포트 얻기 결과로 설정합니다.
-
view의 viewport modifiable 플래그를 false로 설정합니다.
-
viewport를 뷰포트 객체 목록에서 view에 해당하는
XRViewport
로 둡니다. -
viewport를 반환합니다.
참고: viewport modifiable 플래그는
current viewport scale이 변경되지 않아도 false로 설정됩니다. 이렇게 하면
getViewport(view)
호출은 해당 애니메이션 프레임 내에서 항상 일관된 값을 반환하여, 최초 조회된 값이 해당 프레임 동안 고정됩니다. requestViewportScale()
을
getViewport()
이후 호출하면, 요청값은 다음 프레임에서 getViewport()
가 다시 호출될 때만 적용됩니다.
각 XRSession
은 네이티브
WebGL 프레임버퍼 해상도(native WebGL framebuffer resolution)를 식별해야 하며, 이는 XR 디바이스의 실제 픽셀 해상도와 일치하는 WebGL 프레임버퍼의
픽셀 해상도입니다.
XRSession
session의 네이티브 WebGL 프레임버퍼 해상도는 다음 단계로 결정됩니다:
-
session의 mode가
"inline"
이 아니면, 네이티브 WebGL 프레임버퍼 해상도를 세션의 모든XRView
를 담을 수 있는 프레임버퍼 픽셀과, 물리적 디스플레이 픽셀(최대 배율 영역) 간 1:1 비율로 설정하고 종료합니다. 위와 같이 네이티브 해상도를 구할 방법이 없다면, 권장 WebGL 프레임버퍼 해상도를 사용할 수 있습니다. -
session의 mode가
"inline"
이면, 네이티브 WebGL 프레임버퍼 해상도를 session의renderState
의 output canvas의 물리적 디스플레이 픽셀 크기로 설정하고, 캔버스 크기 또는 output canvas가 변경될 때마다 재평가합니다.
또한 XRSession
은 권장 WebGL 프레임버퍼 해상도(recommended WebGL framebuffer
resolution)를 식별해야 하며, 이는 모든 세션의 XRView
를 포함할 수 있으면서,
평균적인 애플리케이션에 대해 성능과 품질의 균형을 제공하는 WebGL 프레임버퍼 해상도의 최적 추정값을 나타냅니다. 이 값은 네이티브 WebGL
프레임버퍼 해상도보다 작거나, 크거나, 같을 수 있습니다. 새로운 opaque framebuffer
는 이 해상도로 생성되며, 가로와 세로는 XRWebGLLayerInit
의
framebufferScaleFactor
값으로 각각 스케일링됩니다.
참고: user agent는 권장 WebGL 프레임버퍼 해상도를 추정하는 방법을 자유롭게 선택할 수 있습니다.
플랫폼별로 권장 크기를 질의하는 방법이 있다면 사용하는 것이 권장되지만, 필수는 아닙니다. framebufferScaleFactor
와
getNativeFramebufferScaleFactor()
에서 사용하는 스케일 팩터는 가로와 세로 각각에 적용되므로, 값이 2면 전체 픽셀 수는 4배가 됩니다. 만약 플랫폼이 픽셀 수 기반의 면적 렌더 스케일을 제공한다면, WebXR 스케일 팩터로
변환하려면 제곱근을 사용해야 합니다.
getNativeFramebufferScaleFactor(session)
메서드가 호출될 때 반드시 다음 단계를 실행해야 합니다:
-
session을 this로 둡니다.
-
session의 ended 값이
true
이면,0.0
을 반환하고 단계를 중단합니다. -
session의 권장 WebGL 프레임버퍼 해상도의 가로, 세로를 각각 곱하면 session의 네이티브 WebGL 프레임버퍼 해상도가 되는 값을 반환합니다.
11.3. WebGL 컨텍스트 호환성
WebGL 컨텍스트가 몰입형 XR 이미지를 위한 소스로 사용되기 위해서는, 해당 몰입형 XR 디바이스에 대해 호환되는 그래픽 어댑터(compatible graphics adapter)에서 생성되어야
합니다. 호환되는 그래픽 어댑터가 무엇인지는 플랫폼마다 다르지만, 일반적으로 해당 그래픽 어댑터가 몰입형 XR 디바이스에 지연
없이 이미지를 제공할 수 있음을 의미합니다. WebGL 컨텍스트가 이미 호환되는 그래픽 어댑터에서 생성되지 않았다면, 해당 어댑터에서 다시 생성해야 XRWebGLLayer
와
함께 사용할 수 있습니다.
참고: XR 플랫폼에 GPU가 하나뿐이라면, 해당 GPU가 플랫폼에서 제공하는 몰입형 XR 디바이스와 호환된다고 안전하게 간주할 수 있으며, 따라서 하드웨어 가속 WebGL 컨텍스트도 모두 호환됩니다. 통합 그래픽과 별도 GPU가 모두 있는 PC에서는 일반적으로 별도 GPU가 호환되는 그래픽 어댑터로 간주됩니다(더 높은 성능을 제공하기 때문). 그래픽 어댑터가 여러 개 설치된 데스크탑 PC에서는 몰입형 XR 디바이스가 물리적으로 연결된 어댑터가 호환되는 그래픽 어댑터로 간주됩니다.
참고: "inline"
세션은 캔버스와 동일한 그래픽 어댑터를 사용하므로 xrCompatible
컨텍스트가 필요하지 않습니다.
partial dictionary WebGLContextAttributes {boolean =
xrCompatible false ; };partial interface mixin WebGLRenderingContextBase { [NewObject ]Promise <undefined >makeXRCompatible (); };
사용자 에이전트가 이 명세를 구현할 때, 반드시 모든 WebGLRenderingContextBase
에
대해, 초기값 false
로 XR
호환(XR compatible) 불리언을 설정해야 합니다. XR 호환 불리언이 true
가 되면, 해당 컨텍스트는 현재 몰입형 XR 디바이스에서 요청된 모든 XRSession
의
레이어와 함께 사용할 수 있습니다.
참고: 이 플래그는 느린 동기적 동작을 유발하므로 사용이 권장되지 않습니다. 비동기적 해결책으로
makeXRCompatible()
사용을 고려하세요.
XR 호환 불리언은 컨텍스트 생성 시 또는 생성 후에도
설정할 수 있으며, 컨텍스트 손실이 발생할 수 있습니다. 생성 시 XR 호환 불리언을 설정하려면, WebGL 컨텍스트 요청 시 xrCompatible
컨텍스트 속성을 true
로 설정해야 합니다. 만약 요청하는 문서의 origin에 "xr-spatial-tracking" permissions
policy가 허용되지 않았다면, xrCompatible
는 아무 효과가 없습니다.
xrCompatible
플래그가 WebGLContextAttributes
에
대해 true
로 설정되면, 사용자 에이전트에게 WebGL 컨텍스트 생성 시
해당 호환되는 그래픽 어댑터를 사용하도록 요청하게 됩니다. 이 과정이 성공하면, 생성된 컨텍스트의 XR 호환 불리언이 true로 설정됩니다. 몰입형 XR 디바이스를 얻기
위해서는 ensure an immersive XR device is selected를
호출해야 합니다.
참고: ensure an immersive XR device is selected는
병렬로 실행되어야 하므로, 메인 스레드에서 느린 동기 동작을 유발합니다. 사용자 에이전트는 대신 makeXRCompatible()
사용을 요청하는 경고를 콘솔에 출력해야 합니다.
XRWebGLLayer
를
생성합니다.
function onXRSessionStarted( xrSession) { const glCanvas= document. createElement( "canvas" ); const gl= glCanvas. getContext( "webgl" , { xrCompatible: true }); loadWebGLResources(); xrSession. updateRenderState({ baseLayer: new XRWebGLLayer( xrSession, gl) }); }
컨텍스트 생성 후 XR 호환 불리언을 설정하려면
makeXRCompatible()
메서드를 사용해야 합니다.
참고: 일부 시스템에서는 이 플래그가 고성능 별도 GPU를 활성화하거나, 모든 명령을 온디바이스
GPU로 프록시할 수 있습니다. XR 사용 여부가 결정되지 않은 상황이라면, 몰입형 세션을 시작할 때만 makeXRCompatible()
호출을 권장합니다.
makeXRCompatible()
메서드는 WebGLRenderingContextBase
가 몰입형 XR 디바이스에 대해
호환되는
그래픽 어댑터에서 실행되고 있음을 보장합니다.
이 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 합니다:
-
요청 문서의 origin이 "xr-spatial-tracking" permissions policy를 사용할 수 없다면, resolve promise를 반환하고 중단한다. XR 권한 정책이 비활성화된 경우, XR 디바이스가 없는 것처럼 동작해야 하며,
makeXRCompatible()
은 set-and-forget 방식이어야 하기 때문이다. -
promise를 이
WebGLRenderingContextBase
의 Realm에서 생성된 새 Promise로 둔다. -
context를 this로 둔다.
-
아래 단계를 병렬로 실행한다:
-
device를 ensure an immersive XR device is selected 결과로 둔다.
-
context의 XR 호환 불리언을 아래와 같이 설정한다:
- 만약 context의 WebGL 컨텍스트 손실 플래그가 설정되어 있으면:
-
작업 큐에 추가하여 context의 XR 호환 불리언을
false
로 설정하고, promise를 reject하며InvalidStateError
로 반환한다. - device가
null
인 경우: -
작업 큐에 추가하여 context의 XR 호환 불리언을
false
로 설정하고, promise를 reject하며InvalidStateError
로 반환한다. - context의 XR 호환 불리언이
true
인 경우: -
작업 큐에 추가하여 promise를 resolve한다.
- context가 device에 대해 호환되는 그래픽 어댑터에서 생성된 경우:
-
작업 큐에 추가하여 context의 XR 호환 불리언을
true
로 설정하고 promise를 resolve한다. - 그 외의 경우:
-
WebGL 작업 소스에 작업 큐 추가하여 아래 단계 실행:
-
context를 강제로 손실시킨다.
-
WebGL 명세에 따라 컨텍스트 손실 처리:
-
canvas를 context의 canvas로 둔다.
-
context의 WebGL 컨텍스트 손실 플래그가 설정되어 있으면, 중단한다.
-
context의 WebGL 컨텍스트 손실 플래그를 설정한다.
-
context에서 생성된 각
WebGLObject
인스턴스의 invalidated 플래그를 설정한다. -
"WEBGL_lose_context"를 제외한 모든 확장 기능을 비활성화한다.
-
WebGL 작업 소스에 작업 큐 추가하여 아래 단계 실행:
-
WebGL 컨텍스트 이벤트 e를 이름 "webglcontextlost"로 canvas에 발생시키고,
statusMessage
는 ""로 설정한다. -
e의 canceled flag가 설정되지 않았다면, promise를 reject하고
AbortError
로 반환하며, 중단한다. -
아래 단계를 병렬로 실행한다.
-
device에 대해 호환되는 그래픽 어댑터에서 복원 가능한 드로잉 버퍼를 대기한다.
-
WebGL 작업 소스에 작업 큐 추가하여 아래 단계 실행:
-
device에 대해 호환되는 그래픽 어댑터에서 컨텍스트를 복원한다.
-
context의 XR 호환 불리언을
true
로 설정한다.
-
-
-
-
-
-
-
promise를 반환한다.
또한, WebGL 컨텍스트가 손실될 때는 "webglcontextlost" 이벤트가 발생하기 전에 아래 단계를 실행합니다:
-
컨텍스트의 XR 호환 불리언을
false
로 설정합니다.
XRWebGLLayer
를
생성합니다.
const glCanvas= document. createElement( "canvas" ); const gl= glCanvas. getContext( "webgl" ); loadWebGLResources(); glCanvas. addEventListener( "webglcontextlost" , ( event) => { // WebGL 컨텍스트를 복원할 수 있음을 나타냅니다. event. canceled= true ; }); glCanvas. addEventListener( "webglcontextrestored" , ( event) => { // 컨텍스트 손실 후에는 WebGL 리소스를 다시 생성해야 합니다. loadWebGLResources(); }); async function onXRSessionStarted( xrSession) { // 사용할 캔버스 컨텍스트가 디바이스와 호환되는지 확인합니다. // 컨텍스트 손실이 발생할 수 있습니다. await gl. makeXRCompatible(); xrSession. updateRenderState({ baseLayer: new XRWebGLLayer( xrSession, gl) }); }
12. 이벤트(Events)
이 명세서에서 큐에 추가된 모든 작업(tasks queued)의 작업 소스(task source)는 별도의 명시가 없는 한 XR 작업 소스(XR task source)입니다.
12.1. XRSessionEvent
XRSessionEvent
는
XRSession
의
상태 변화가 발생했음을 알리기 위해 발생합니다.
[SecureContext ,Exposed =Window ]interface :
XRSessionEvent Event {(
constructor DOMString ,
type XRSessionEventInit ); [
eventInitDict SameObject ]readonly attribute XRSession session ; };dictionary :
XRSessionEventInit EventInit {required XRSession ; };
session
session
속성은 이벤트를 발생시킨 XRSession
을
나타냅니다.
12.2. XRInputSourceEvent
XRInputSourceEvent
는
XRInputSource
의
상태 변화가 발생했음을 알리기 위해 발생합니다.
[SecureContext ,Exposed =Window ]interface :
XRInputSourceEvent Event {(
constructor DOMString ,
type XRInputSourceEventInit ); [
eventInitDict SameObject ]readonly attribute XRFrame frame ; [SameObject ]readonly attribute XRInputSource inputSource ; };dictionary :
XRInputSourceEventInit EventInit {required XRFrame ;
frame required XRInputSource ; };
inputSource
inputSource
속성은 이 이벤트를 발생시킨 XRInputSource
를
나타냅니다.
frame
속성은 이벤트가 발생한 시점의 XRFrame
을 나타냅니다. 이
값은 과거의 데이터를 나타낼 수 있습니다. getViewerPose()
는
frame
에서
호출 시 예외를 발생시켜야 합니다.
사용자 에이전트가 name, XRFrame
frame, XRInputSource
source로 입력 소스 이벤트를 발생시켜야 할 때 다음 단계를 수행해야 합니다:
-
XRInputSourceEvent
event를type
name,frame
frame,inputSource
source로 생성한다. -
frame의 active 불리언을
true
로 설정한다. -
프레임 업데이트를 적용한다(frame).
-
frame의 active 불리언을
false
로 설정한다.
12.3. XRInputSourcesChangeEvent
XRInputSourcesChangeEvent
는
XRSession
에서
사용 가능한 활성 XR 입력 소스 목록의 변경을 알리기 위해 발생합니다.
[SecureContext ,Exposed =Window ]interface :
XRInputSourcesChangeEvent Event {(
constructor DOMString ,
type XRInputSourcesChangeEventInit ); [
eventInitDict SameObject ]readonly attribute XRSession session ; [SameObject ]readonly attribute FrozenArray <XRInputSource >added ; [SameObject ]readonly attribute FrozenArray <XRInputSource >removed ; };dictionary :
XRInputSourcesChangeEventInit EventInit {required XRSession ;
session required sequence <XRInputSource >;
added required sequence <XRInputSource >; };
removed
session
속성은 이벤트를 발생시킨 XRSession
을
나타냅니다.
added
속성은 이벤트 시점에 XRSession
에
추가된 XRInputSource
의
목록입니다.
removed
속성은 이벤트 시점에 XRSession
에서
제거된 XRInputSource
의
목록입니다.
12.4. XRReferenceSpaceEvent
XRReferenceSpaceEvent
는
XRReferenceSpace
의
상태 변화가 발생했음을 알리기 위해 발생합니다.
[SecureContext ,Exposed =Window ]interface :
XRReferenceSpaceEvent Event {(
constructor DOMString ,
type XRReferenceSpaceEventInit ); [
eventInitDict SameObject ]readonly attribute XRReferenceSpace referenceSpace ; [SameObject ]readonly attribute XRRigidTransform ?transform ; };dictionary :
XRReferenceSpaceEventInit EventInit {required XRReferenceSpace ;
referenceSpace XRRigidTransform ?=
transform null ; };
referenceSpace
속성은 이벤트를 발생시킨 XRReferenceSpace
를
나타냅니다.
선택적 transform
속성은 이벤트 이후 referenceSpace
의
네이티브 원점(native
origin)의 위치와 방향을 이벤트 이전 좌표계에서 설명합니다. XRSystem
이 이전과
새로운 좌표계의 차이를 알 수 없는 경우 이 속성은 null
일 수 있습니다.
참고: referenceSpace
또는 referenceSpace
가
예를 들어 헤드셋이 두 위치 사이에서 벗겨졌다가 다시 착용된 경우 등에서 변경될 수 있습니다. 이런 경우, 경험이 월드-락 콘텐츠에 의존한다면 사용자에게 경고하고 씬을 재설정해야 합니다.
12.5. XRVisibilityMaskChangeEvent
由于视锥体并不总是与矩形显示器精确相交,XRLayer
的整个区域可能不会被显示。该事件将通知体验哪些 XRView
区域被展示给用户。
当用户代理需要告知体验 XRLayer
的显示区域发生变化时,会触发 XRVisibilityMaskChangeEvent
事件。
体验可以选择只绘制该区域,这有助于提升性能。
注意:体验必须在 requestSession
的 promise 解决期间注册该事件,否则事件可能会触发且遮罩信息会丢失。
[SecureContext ,Exposed =Window ]interface :
XRVisibilityMaskChangeEvent Event {(
constructor DOMString ,
type XRVisibilityMaskChangeEventInit ); [
eventInitDict SameObject ]readonly attribute XRSession session ;readonly attribute XREye eye ;readonly attribute unsigned long index ; [SameObject ]readonly attribute Float32Array vertices ; [SameObject ]readonly attribute Uint32Array indices ; };dictionary :
XRVisibilityMaskChangeEventInit EventInit {required XRSession ;
session required XREye ;
eye required unsigned long ;
index required Float32Array ;
vertices required Uint32Array ; };
indices
session
属性表示生成该事件的 XRSession
。
eye
属性表示该遮罩所应用的 XREye
。
index
属性表示该遮罩应用到的 XRView
在 视图列表
中的偏移量。
vertices
属性是一个 列表,包含
X
、Y
坐标。体验必须假定 Z
坐标为 -1
。每组
X
、Y
、Z
坐标描述一个顶点。如果该数组为空,则应绘制 XRView
的整个区域。
indices
属性是一个 列表,用于描述 vertices
顶点列表中的索引。这些索引将描述该眼睛的 XRView
应绘制的区域。如果该数组为空,则应绘制 XRView
的整个区域。
该区域必须使用 projectionMatrix
(XRView
的 eye
)和默认
XRRigidTransform
进行绘制。
注意:这意味着该区域不得使用当前 XRView
的 XRRigidTransform
(eye
)进行绘制。
12.6. 이벤트 타입(Event Types)
사용자 에이전트는 다음과 같은 새로운 이벤트를 반드시 제공합니다. 이벤트의 등록과 발생(fire)은 DOM 이벤트의 일반적인 동작을 따라야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, devicechange
이벤트를 XRSystem
객체에 대해
발생시켜야 합니다. 이는 immersive XR device의 가용성이 변경되었음을 나타내기 위한 것이며, 단 문서의 origin이 "xr-spatial-tracking" permissions
policy 사용이 허용되지 않은 경우에는 예외입니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, visibilitychange
이벤트를 XRSessionEvent
를
사용하여 XRSession
에
대해, 해당 XRSession
의 visibility state가 변경될 때마다 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, end
이벤트를 XRSessionEvent
를
사용하여 XRSession
에
대해, 세션이 애플리케이션 또는 사용자 에이전트에 의해 종료될 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, inputsourceschange
이벤트를 XRInputSourcesChangeEvent
를
사용하여 XRSession
에
대해, 세션의 list of active XR input sources가 변경될 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, trackedsourceschange
이벤트를 XRInputSourcesChangeEvent
를
사용하여 XRSession
에
대해, 세션의 list of active XR tracked sources가 변경될 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, selectstart
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary action을 시작할 때
발생시켜야 합니다.
이 이벤트는 해당 타입이어야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, selectend
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary action을
종료하거나, XRInputSource가 primary action을 시작한 뒤 연결이
끊어질 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, select
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary action을 완전히
완료했을 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, squeezestart
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary
squeeze action을 시작할 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, squeezeend
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary
squeeze action을 종료하거나, XRInputSource가 primary squeeze action을 시작한 뒤 연결이 끊어질 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, squeeze
이벤트를 XRInputSourceEvent
를
사용하여 XRSession
에
대해, XRInputSource
중 하나가 primary
squeeze action을 완전히 완료했을 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, frameratechange
이벤트를 XRSessionEvent
를
사용하여 XRSession
에
대해, XR Compositor가 XRSession
의 internal nominal framerate를 변경할 때 발생시켜야 합니다.
사용자 에이전트는 이벤트를 발생시켜야 하며, reset
이벤트를 XRReferenceSpaceEvent
를
사용하여 XRReferenceSpace
에
대해 발생시켜야 하며,
이는 native
origin 또는 effective origin에 불연속성이 발생한 경우(즉, 사용자 환경에 대해 origin의 위치 또는
방향에 중대한 변화가 있을 때)입니다. (예: 사용자가 XR 장치를 재보정한 후, 또는 XR 장치가 추적을 잃었다가 다시 추적을 시작하여 origin을 자동으로 이동시키는 경우) reset
이벤트는 XRBoundedReferenceSpace
의
boundsGeometry
가
변경될 때도 반드시 발생해야 합니다.
reset
이벤트는 viewer의 포즈에 불연속성이 발생해도 XRReferenceSpace
의
origin 물리적 매핑이 안정적으로 유지되는 한(예: viewer가 같은
트래킹 영역 내에서 잠시 추적을 잃었다가 다시 찾는 경우)에는 발생하면 안 됩니다. 또한, unbounded
reference space가 사용자의 근처에서 공간의 안정성을 유지하기 위해 native origin을 조금씩 조정하는 경우에도, 명백한 불연속성이 아니라면 이벤트는 발생하면 안 됩니다. 이
이벤트는 새로운 origin을 사용하는 어떤 XR animation frame보다 먼저 dispatch되어야 합니다. reset
이벤트는 해당 이벤트를 발생시키는 reference space의 모든 offset reference space에도 dispatch되어야 하며, offset XRBoundedReferenceSpace
의
boundsGeometry
또한 다시 계산되어야 합니다.
참고: 이는 세션이 XRReferenceSpace
에
reset
리스너가 등록되어 있다면 해당 reference space에 강한 참조(strong reference)를 유지해야 함을 의미합니다.
참고: viewer 위치의 갑작스러운 이동(jump)은 애플리케이션이 emulatedPosition
불리언을 관찰함으로써 처리할 수 있습니다. viewer 위치의 점프가
emulatedPosition
이
true
에서 false
로 바뀌는 시점과 일치하면, 이는 viewer가 추적을 다시 획득했고, 새 위치가 이전에 에뮬레이션된 값들로부터의 보정임을 나타냅니다. 사용자가 실제로 움직이지 않고 가상
세계 내에서만 이동할 수 있는 "텔레포테이션" 기능이 없는 경험에서는 일반적으로 이 동작이 애플리케이션이 원하는 동작입니다. 그러나 "텔레포테이션" 기능이 있는 경험에서는 추적 복구 후 viewer의 위치를 다시 원래 위치로 점프시키는 것이 불필요하게 어색할 수
있습니다. 이런 경우, 애플리케이션은 추적이 복구되었을 때, viewer의
현재 가상 위치로부터 경험을 계속 진행시키고, 위치의 갑작스런 점프를 텔레포트 오프셋에 반영할 수 있습니다. 이를 위해 개발자는 getOffsetReferenceSpace()
를
호출하여, effective origin을 이전 프레임 이후 viewer 위치가 점프한 만큼 조정한 대체 reference space를 생성할 수 있습니다.
13. 보안, 프라이버시, 그리고 편안함에 대한 고려사항
WebXR 디바이스 API는 강력한 새로운 기능을 제공하며, 이로 인해 사용자 에이전트가 완화해야 하는 몇 가지 고유한 프라이버시, 보안, 그리고 편안함에 대한 위험이 발생합니다.
13.1. 민감한 정보
XR 맥락에서 민감한 정보에는
사용자 설정 데이터(예: 동공 간 거리(IPD))와 XRPose
와 같은 센서 기반
데이터가 포함되지만 이에 국한되지 않습니다. 모든 몰입형 세션은 사용자의 포즈가 렌더링에 필요하기 때문에 어느 정도의 민감한 데이터를 노출하게 됩니다.
그러나 경우에 따라 동일한 민감한 정보가 "inline"
세션을 통해서도 노출될 수 있습니다.
13.2. 사용자 의도
사용자 의도란 특정 행동이 사용자의 의도에 따라 이루어졌으며 동의가 있었음을 나타내는 신호입니다.
민감한 정보를 노출하거나 사용자 경험에 중대한 영향을 미치는 행동을 허용하기 전에 사용자 의도를 반드시 확인해야 할 때가 많습니다. 이러한 의도는 여러 방식으로 전달되거나 관찰될 수 있습니다.
참고: 사용자 의도를 판단하는 일반적인 방법은 UI 컨트롤의 일시적 활성화입니다. 보통 "VR 입장" 버튼이 이에 해당합니다. 활성화가 일시적이므로, XR 세션을 요청하는 브라우징 컨텍스트는 UI 컨트롤을 포함하는 컨텍스트의 상위이거나 동일 출처 도메인의 하위여야 하며, 최근에 해당 브라우징 컨텍스트의 활성 문서였어야 합니다.
13.2.1. 사용자 활성화
일시적 활성화는 일부 시나리오에서 사용자 의도의 표시로 사용될 수 있습니다.13.2.2. 웹 애플리케이션 실행
일부 환경에서는 페이지가 애플리케이션으로 제공되어 몰입형 콘텐츠 실행을 명시적으로 의도할 수 있습니다. 이 경우 웹 애플리케이션 실행도 사용자 의도의 표시로 사용될 수 있습니다.13.2.3. 묵시적 및 명시적 동의
묵시적 동의란 사용자 에이전트가 명시적으로 묻지 않고 사용자의 동의를 판단하는 경우를 말합니다. 예를 들어, 웹 애플리케이션의 설치 상태, 방문 빈도 및 최근성, 또는 사용자가 몰입형 경험에 들어가고자 하는 명확한 신호를 보낸 사용자 에이전트 정의 동작 등이 있습니다. XR 데이터의 민감성을 고려할 때, 묵시적 신호에 의존할 때는 각별한 주의가 필요합니다.
명시적 동의란 사용자 에이전트가 명시적으로 동의를 요청하여 사용자의 동의를 판단하는 경우를 말합니다. 명시적 동의를 받을 때, 사용자 에이전트는 요청하는 내용을 설명하고 사용자가 거부할 수 있는 옵션을 제공합니다. 사용자 동의 요청은 보호되는 기능과 사용자 에이전트의 선택에 따라 다양한 시각적 형태로 제시될 수 있습니다. 웹 애플리케이션의 설치 상태는 설치 시 명시적 동의가 요청된 경우 명시적 동의의 신호로 간주될 수 있습니다.
13.2.4. 동의의 지속 기간
특정 명시적 동의가 특정 origin에 대해 부여되면, 이 동의는 브라우징 컨텍스트가 종료될 때까지 유지되는 것이 권장됩니다. 사용자 에이전트는 사용자 의도에 대한 묵시적 또는 명시적 신호에 따라 이 동의 기간을 연장하거나 단축할 수 있지만, 특히 묵시적 신호에 의존할 때는 주의가 필요합니다. 예를 들어, 몰입형 콘텐츠 실행을 명시적으로 의도하여 설치된 웹 애플리케이션의 경우 사용자의 동의를 지속하는 것이 적절할 수 있지만, 몰입형 콘텐츠가 부가 기능인 경우에는 그렇지 않을 수 있습니다.사용자 에이전트가 사용자의 동의를 얼마나 오래 유지하든, 민감한 정보는 XRSession
이 종료되지 않은 경우에만 노출되어야 합니다.
13.3. 세션 중간 동의
사용자 에이전트가 기능 사용을 위해 명시적 동의를 요청하게 하는 여러 비-XR API가 있습니다. 만약 활성 몰입형 세션이 있는 동안 사용자 에이전트가 사용자의 동의를 요청해야 한다면, 사용자에게 동의 요청을 표시하기 전에 반드시 세션을 종료해야 합니다. 해당 기능에 대한 사용자의 동의가 활성 몰입형 세션이 생성되기 전에 이미 부여된 경우에는 세션을 종료할 필요가 없습니다.
참고: 이 제한은 모든 사용자 에이전트 간의 동작 일관성을 보장하기 위한 것으로, 사용자 에이전트가 세션 중간 명시적 동의를 어떻게 관리해야 하는지에 대한 합의가 이루어질 때까지 유지됩니다. 장기적인 요구사항은 아닙니다.
13.4. 데이터 조정
경우에 따라, 데이터 조정(예: 쓰로틀링, 양자화, 반올림, 제한 또는 기타 방식으로 XR 디바이스에서 보고되는 데이터를 조작하는 것)을 통해 보안 및 프라이버시 위협을 완화할 수 있습니다. 이는 사용자 의도가 확인된 상황에서도 지문 채취를 방지하기 위해 필요할 수 있습니다. 단, 데이터 조정 완화책은 사용자 불편을 초래하지 않는 상황에서만 사용해야 합니다.
13.4.1. 쓰로틀링
쓰로틀링은 민감한 정보를 원래보다 낮은 빈도로 보고하는 것입니다. 이 완화책은 사이트가 사용자 의도 추론, 위치 추론, 또는 사용자 프로파일링을 수행하는 능력을 줄일 수 있습니다. 그러나 적절히 사용하지 않으면 쓰로틀링은 사용자 불편을 초래할 위험이 큽니다. 또한 많은 상황에서 완전한 완화책이 되지 못할 수 있습니다.13.4.2. 반올림, 양자화, 퍼징
반올림, 양자화, 퍼징은 원시 데이터를 개발자에게 반환하기 전에 수정하는 세 가지 완화책입니다. 반올림은 데이터를 표현하는 자릿수를 줄여 정밀도를 낮춥니다. 양자화는 연속적인 데이터를 이산적인 값의 집합으로 제한합니다. 퍼징은 데이터에 약간의 무작위 오류를 도입하는 것입니다. 이 완화책들은 지문 채취를 방지하는 데 유용하며, 특히 사용자에게 눈에 띄는 불편을 주지 않는 경우에 효과적입니다.13.4.3. 제한
제한은 데이터가 특정 범위 내에 있을 때만 보고하는 것입니다. 예를 들어, 사용자가 승인된 위치에서 특정 거리 이상 벗어났을 때 위치 포즈 데이터 보고를 제한하는 것이 가능합니다. 이 완화책을 적용할 때는 사용자 경험이 부정적으로 영향을 받지 않도록 주의해야 합니다. 범위 끝에서 '하드 스톱'을 피하는 것이 바람직하며, 이는 사용자 경험에 방해가 될 수 있기 때문입니다.13.5. 보호되는 기능
API에서 노출되는 민감한 정보는 위협 프로필과 이에 대한 보호가 필요한 범주로 나눌 수 있습니다.
13.5.1. 몰입성(Immersiveness)
사용자는 몰입형 세션이 생성되는 시점을 직접 제어할 수 있어야 합니다. 그 이유는 세션 생성이 사용자의 기기에 침습적인 변화를 일으키기 때문입니다. 예를 들어, 몰입형 세션을 시작하면 XR 디바이스 센서가 활성화되고, 디바이스의 디스플레이 접근 권한을 가져오며, 몰입형 콘텐츠를 표시하기 시작해 다른 애플리케이션의 XR 하드웨어 접근을 종료시킬 수 있습니다. 또한 일부 시스템에서는 상당한 전력 또는 성능 오버헤드가 발생하거나, 상태 트레이 또는 스토어프론트가 실행될 수 있습니다.특정 global object에 대해 몰입형 세션 요청이 허용되는지 판단하려면, 사용자 에이전트는 다음 단계를 반드시 수행해야 합니다:
"inline"
세션을 시작하는 경우에는 동일한 요구사항이 자동으로 적용되지는 않지만, 세션의 요청된 기능에 따라 추가 요구사항이 적용될 수 있습니다.
특정 global object에 대해 인라인 세션 요청이 허용되는지 판단하려면, 사용자 에이전트는 다음 단계를 반드시 수행해야 합니다:
-
세션 요청에 필수 기능 또는 선택 기능이 포함되어 있고, 요청이 global object가 일시적 활성화 상태이거나 웹 애플리케이션 실행 중이 아닐 때 이루어진 경우,
false
를 반환합니다. -
global object가
Window
가 아닌 경우,false
를 반환합니다. -
true
를 반환합니다.
13.5.2. 포즈(Poses)
센서 데이터 기반일 때,XRPose
및
XRViewerPose
는 입력 스니핑, 시선 추적, 지문 채취 등 다양한 방식으로 악용될 수 있는 민감한 정보를 노출합니다.
XRSession
session에 포즈를 보고할 수 있는지 판단하려면, 사용자 에이전트는 다음 단계를 반드시 수행해야 합니다:
-
session의
visibilityState
값이이면,
false
를 반환합니다. -
포즈 데이터를 반환할 수 있는지 다음과 같이 판단합니다:
참고: 포즈가 지문 채취가 불가능한 데이터임을 사용자 에이전트가 어떻게 판단하는지는 사용자 에이전트의 재량에 맡깁니다.
XRViewerPose
와
XRPose
의 주요 차이점은
XRView
정보가 포함된다는
점입니다.
둘 이상의 view가 존재하고 이들 간의 물리적 관계가 사용자가 설정할 수 있는 경우, 이 view들 간의 관계는 사용자를 프로파일링하거나 지문 채취(fingerprinting)가 가능하므로
민감 정보로 간주됩니다.
만약 XRView
들 간의 관계가
XR 디바이스를 고유하게 식별할 수 있다면, 사용자 에이전트는 지문
채취를 방지하기 위해 반드시 XRView
데이터를 익명화해야
합니다. 익명화 방법은 사용자 에이전트의 재량에 따릅니다.
참고: 또한, XRView
들 간의 관계가 사용자가
설정한 동공 거리(IPD)에 영향을 받는 경우, 사용자 에이전트는 세션 생성 시 XRView
데이터를 보고하기 전에
명시적 동의를 요구하는 것이 강력히
권장됩니다.
13.5.3. Reference spaces
사용되는 reference space에 따라 여러 유형의 민감한 정보가 애플리케이션에 노출될 수 있습니다.-
6DoF 트래킹을 지원하는 디바이스에서,
"local"
reference space는 보행 분석(gait analysis)에 사용될 수 있어 사용자 프로파일링 및 지문 채취가 가능합니다. -
6DoF 트래킹을 지원하는 디바이스에서,
"local-floor"
reference space도 보행 분석에 사용될 수 있어 사용자 프로파일링 및 지문 채취가 가능합니다. 또한"local-floor"
reference space는 바닥 높이가 정해져 있으므로, 사이트가 사용자의 키를 추론하여 프로파일링 및 지문 채취에 활용할 수 있습니다. -
"bounded-floor"
reference space는 크기가 충분히 제한된 경우 개발자가 지리적 위치를 파악할 수는 없지만, 바닥 높이가 정해져 있고 사용자가 이동할 수 있으므로 사이트가 사용자의 키를 추론하거나 보행 분석을 통해 프로파일링 및 지문 채취가 가능합니다. 또한 bounded reference space에서 보고되는 경계를 이용해 지문 채취가 가능할 수 있습니다. -
"unbounded"
reference space는 가장 많은 공간 데이터를 노출하며, 사용자 프로파일링 및 지문 채취로 이어질 수 있습니다. 예를 들어, 이 데이터로 사용자의 특정 지리적 위치를 파악하거나 보행 분석을 수행할 수 있습니다.
이로 인해 다양한 reference space 유형은 노출되는 민감한 정보가 안전하게 처리되도록 생성에 제한이 있습니다:
대부분의 reference space는 해당 공간 사용에 대한 사용자 의도가 명시적 동의 또는 묵시적 동의로 명확히 파악되어야 합니다. 자세한 내용은 기능 요구사항 표를 참고하세요.
"local"
,
"local-floor"
,
"bounded-floor"
reference space들이 서로 연관될 수 있는 경우, 반드시 공통 native origin을 공유해야 합니다. 이 제한은 "unbounded"
reference space 생성이 제한된 경우에만 적용됩니다.
두 공간 space와 baseSpace 간에 포즈 제한이 필요한지 판단하려면, 사용자 에이전트는 다음 단계를 반드시 수행해야 합니다:
-
space 또는 baseSpace 중 하나가
XRBoundedReferenceSpace
이고, 다른 공간의 native origin이 native bounds geometry에서 사용자 에이전트가 정한 합리적인 거리보다 더 멀리 떨어져 있다면, true를 반환합니다. -
space 또는 baseSpace 중 하나가
XRReferenceSpace
이고, type이"local"
또는"local-floor"
이며, 두 공간의 native origin 간 거리가 사용자 에이전트가 정한 합리적인 거리보다 크면,true
를 반환합니다. -
false
를 반환합니다.
참고: 문서 가시성 요구사항은 [DEVICE-ORIENTATION]에 기반합니다.
참고: "local"
또는 "local-floor"
reference space 기준으로 보고되는 포즈는 15미터 이내로
XRReferenceSpace
의
native
origin에서 제한하는 것이 권장됩니다.
참고: XRBoundedReferenceSpace
기준으로 보고되는 포즈는 native bounds geometry에서
1미터 이내로 제한하는 것이 권장됩니다.
13.6. 신뢰된 환경(Trusted Environment)
신뢰된 UI(Trusted UI)란 사용자 에이전트가 제공하며 사용자는 상호작용할 수 있지만, 페이지에서는 상호작용할 수 없는 인터페이스를 의미합니다. 사용자 에이전트는 신뢰된 UI를 반드시 지원해야 합니다.
신뢰된 UI는 다음과 같은 속성을 반드시 가져야 합니다:
-
위조(spoof)가 불가능해야 합니다.
-
표시되는 요청/콘텐츠의 출처가 어디인지 명확히 나타내야 합니다.
-
사용자와 공유하는 비밀에 의존하는 경우, 이 비밀은 혼합현실 캡처(예: 카메라로 볼 수 있는 제스처 등)로 관찰될 수 없어야 합니다.
-
동일한 사용자 에이전트 내의 몰입형 경험들 간에 일관성을 유지해야 합니다.
일반적으로 신뢰된 UI를 지원하려는 사용자 에이전트에는 두 가지
선택지가 있습니다. 하나는 신뢰된 몰입형
UI(trusted immersive UI)로, 몰입형 모드를 종료하지 않고 제공되는 신뢰된 UI입니다. 신뢰된 몰입형 UI를 구현하는 것은 XRWebGLLayer
버퍼가 XR 디바이스 디스플레이
전체를 채우고, 사용자 에이전트가 자체적으로 픽셀을 "예약"하지 않기 때문에 어려울 수 있습니다. 사용자 에이전트는 신뢰된 몰입형 UI를 반드시 지원할 필요는 없으며, 대신 몰입형
모드를 일시 중지/종료하고 비몰입형 신뢰된 UI를 사용자에게
표시할 수 있습니다.
-
몰입형 모드가 아닐 때 표시되는 기본 2D 모드 브라우저
-
위조 방지를 위해 예약된 하드웨어 버튼으로만 상호작용할 수 있는, 몰입형 모드 내에서 표시되는 프롬프트
-
몰입형 세션을 일시 중지하고, 프롬프트를 표시할 수 있는 네이티브 시스템 환경을 보여주는 경우
입력 정보(머리 자세, 입력 자세 등)를 읽을 수 있는 기능은 신뢰
UI의 무결성에 위험을 초래할 수 있습니다. 페이지가 사용자가 신뢰 UI와 상호작용하는 동안(예: 키보드 입력 추정 포함) 내린 선택을 염탐하기 위해 이 정보를 사용할 수 있기 때문입니다. 이
위험을 방지하기 위해 사용자 에이전트는 사용자가 신뢰 UI(몰입형 또는 비몰입형, 예:
URL 바 또는 시스템 다이얼로그 등)와 상호작용할 때 모든 XRSession
의 visibility state를
또는
"visible-blurred"
로
설정해야 합니다.
또한 악의적인 페이지가 다른 페이지의 입력을 감시하지 못하도록, 사용자 에이전트는 현재 포커스된 영역이 XRSession
을
생성한 문서에 속하지 않는 경우, 해당 XRSession
의 visibility state를 으로
설정해야 합니다.
특정 신뢰된 UI 인스턴스에 대해 과
"visible-blurred"
중 어떤 값을 사용할지 선택할 때, 사용자 에이전트는 머리 포즈 정보가 보안 위험이 되는지 반드시 고려해야 합니다. 예를 들어, 신뢰된 UI에서 텍스트 입력(특히 비밀번호 입력)이 포함된 경우, 사용자가 입력하는 동안 머리
포즈를 통해 입력한 텍스트가 유출될 수 있습니다. 이런 경우, 사용자 에이전트는 시선 추적 관련 정보 노출도 중단해야 합니다.
사용자 에이전트는 권한 프롬프트를 표시할 때 반드시 신뢰된 UI를 사용해야 합니다.
가상 환경이 사용자의 머리 움직임을 낮은 지연과 높은 프레임률로 일관되게 추적하지 못하면, 사용자가 방향 감각을 잃거나 신체적으로 불편함을 느낄 수 있습니다. 페이지가 항상 일관되고 성능 좋은 콘텐츠를 제공하도록 강제할 수 없으므로, 사용자 에이전트는 반드시 추적 가능한 신뢰된 환경과 페이지 콘텐츠와 비동기적으로 동작하는 XR Compositor를 제공해야 합니다. 컴포지터는 신뢰된 콘텐츠와 신뢰되지 않은 콘텐츠를 합성하는 역할을 합니다. 만약 콘텐츠가 성능이 부족하거나 프레임을 제출하지 않거나 예기치 않게 종료되더라도, 사용자 에이전트는 반응성 있는 신뢰된 UI를 계속 표시할 수 있어야 합니다.
또한, 페이지 콘텐츠는 성능과 무관하게 사용자를 불편하게 만들 수 있습니다. 잘못 적용된 트래킹, 깜빡이는 색상, 불쾌감·공포·위협을 주는 콘텐츠 등은 사용자가 XR 경험을 빠르게 종료하고 싶게 만들 수 있습니다. 이런 경우 XR 디바이스를 제거하는 것이 항상 빠르거나 실용적이지 않을 수 있으므로, 사용자 에이전트는 반드시 예약된 하드웨어 버튼을 누르거나 제스처를 수행하는 등 WebXR 콘텐츠를 빠져나와 사용자 에이전트의 신뢰된 UI를 표시할 수 있는 조치를 제공해야 합니다.
13.7. 컨텍스트 격리(Context Isolation)
신뢰된 UI는 반드시 페이지에서 사용하는 렌더링 컨텍스트(예: WebGL 렌더링 컨텍스트 등)와는 독립적으로, 상태가 격리된 렌더링 컨텍스트에서 그려져야 합니다. 이는 페이지가 신뢰된 UI의 컨텍스트 상태를 손상시켜 추적 환경을 제대로 렌더링하지 못하게 하거나, 신뢰된 UI의 이미지를 캡처해 개인 정보가 유출되는 것을 방지하기 위함입니다.
또한, CORS 관련 취약점을 방지하기 위해 각 브라우징 컨텍스트는 API에서 반환되는 객체(예: XRSession
등)의
새로운 인스턴스를 보게 됩니다. context와 같은 속성이 한 XRWebGLLayer
에서
설정되어도, relevant realm이 다른 XRWebGLLayer
에서는
읽을 수 없어야 하며, relevant realm이 동일
출처가 아닌 경우에도 마찬가지입니다. 이와 유사하게, API에서 호출되는 메서드는 다른 브라우징 컨텍스트에 관찰 가능한 상태 변화를 일으켜서는 안 됩니다. 예를 들어, 시스템 수준의 방향 재설정 메서드는 노출되지
않으며, 악의적인 페이지가 이를 반복 호출해 다른 페이지의 트래킹을 방해할 수 없도록 해야 합니다. 단, 사용자 제스처나 시스템 메뉴로 트리거된 시스템 수준의 방향 재설정은 사용자 에이전트가
반드시 존중해야 합니다.
참고: 이는 한 브라우징 컨텍스트가 몰입형 모드에 진입하거나, 디바이스 잠금을 획득하거나, devicechange 이벤트를 다른 브라우징 컨텍스트에 발생시키는 등, 상태 변화에는 적용되지 않습니다.
13.8. 지문 채취(Fingerprinting)
이 API는 사용자가 사용할 수 있는 하드웨어와 그 기능을 기술하므로, 필연적으로 지문 채취에 활용될 수 있는 추가 표면을 제공합니다. 이를 완전히 방지하는 것은 불가능하지만, 사용자 에이전트는 문제를 완화하기 위한 조치를 취해야 합니다. 본 명세는 사용 가능한 하드웨어 보고를 한 번에 하나의 디바이스로 제한하여, 여러 헤드셋이 연결된 드문 경우를 지문 채취 신호로 사용하는 것을 방지합니다. 또한, 보고되는 디바이스는 문자열 식별자를 제공하지 않으며, XRSession이 생성되기 전까지는 디바이스의 기능에 대한 정보도 거의 노출하지 않습니다. XRSession 생성 시 민감한 정보가 노출될 때는 추가 보호가 필요합니다.
13.8.1. isSessionSupported()
의
지문 채취 고려사항
isSessionSupported()
는 사용자 활성화 없이 호출될 수 있으므로, 지문 채취 벡터로 사용될 수 있습니다.
"xr-session-supported"
강력한 기능(powerful feature)은 isSessionSupported()
API 접근을 제한합니다.
"xr-session-supported" 권한 관련 알고리즘과 타입은 다음과 같이 정의됩니다:
- permission descriptor type
-
dictionary
:XRSessionSupportedPermissionDescriptor PermissionDescriptor {XRSessionMode
; };mode name
forXRPermissionDescriptor
is "xr-session-supported"입니다.
13.8.2. "xr-session-supported" 자동 부여 시 고려사항
웹에서 프라이버시와 개인화는 종종 상충합니다. 이 절에서는 그 균형점을 어디에 둘 수 있는지, 그리고 사용자 에이전트가 isSessionSupported()
를 통해 사이트에 브라우저의 WebXR 기능을 프라이버시 저하 없이 알릴 수 있는 시점에 대한 지침을 제공합니다.
"xr-session-supported"는 아래 기준에 따라 일부 시스템에서 자동으로 부여될 수 있습니다. 이는 더 나은 사용자 경험을 제공하고 권한 피로(permission fatigue)를 완화할 수 있습니다.
여러 사용자 에이전트가 동일한 userAgent
와 appVersion
을
보고한다면, 이 집합은 user agent string으로 구분 불가(indistinguishable by user
agent string)하다고 합니다. 이런 집합은 보통 브라우저 버전과 실행 중인 플랫폼/디바이스로 식별되지만, 연결된 외부 디바이스 상태로는 구분할 수 없습니다.
user agent string으로 구분 불가 개념을 활용해 지문 채취 위험을
적절히 평가할 수 있습니다.
일부 user agent string으로 구분 불가 사용자 에이전트는 특정
XRSessionMode
의
세션을 절대 지원하지 않음(never
support)으로 간주합니다.
예: 모바일 AR을 지원하지 않는 것으로 알려진 휴대폰 모델에서 실행되는 사용자 에이전트 등 이런 경우, isSessionSupported()
가 항상 해당 XRSessionMode
를 지원하지 않는다고 보고해도 지문 채취 위험이 거의 없습니다. 왜냐하면 모든 해당 디바이스가 일관된 값을 보고하고, 디바이스 종류와 모델은 userAgent
등 다른 방법으로도 추론할 수 있기 때문입니다.
따라서 이런 시스템에서는 사용자 에이전트가 해당 XRSessionMode
에
대해 "xr-session-supported"를 자동으로 거부해야 합니다.
다른 user agent string으로 구분 불가 사용자 에이전트는 특정
XRSessionMode
의
세션을 대체로 지원함(usually
support)으로 간주합니다.
예: VR 헤드셋 내에서만 실행되는 WebXR 지원 사용자 에이전트는, 사용자가 명시적으로 차단하지 않는 한 "immersive-vr"
세션을 지원할 가능성이 높음 이런 경우, 해당 XRSessionMode
를 지원하지 않는다고 보고하는 것이 정확하더라도, 오히려 사용자를 더 고유하게 식별할 수 있는 정보를 제공할 수 있습니다. 따라서 항상 해당 XRSessionMode
가 사용 가능하다고 보고하고, requestSession()
이 실패하도록 하는 것이 프라이버시 보호에 더 적합하며, 사용자가 혼란을 겪을 가능성도 낮습니다. 이런 시스템에서는 해당 XRSessionMode
에
대해 "xr-session-supported"를 자동으로 부여해야 합니다.
XR 기능의 가용성이 매우 다양한(예: XR 주변기기를 지원하는 데스크톱 시스템 등) user agent string으로 구분 불가 사용자 에이전트는 지문 채취
위험이 가장 높습니다. 이런 디바이스의 사용자 에이전트는 isSessionSupported()
API가 추가적인 지문 채취 정보를 제공하지 않도록 "xr-session-supported"를 자동으로 부여해서는 안 됩니다.
-
isSessionSupported()
호출 시 명시적 동의(권한 프롬프트 캐시 등 포함)를 항상 판단한다. -
"xr-session-supported"를 자동으로 부여하되,
isSessionSupported()
가 실제 XR 하드웨어/소프트웨어가 없어도 항상true
를 반환하도록 한다. 이 경우 사용성은 떨어질 수 있으나, XR 콘텐츠를 볼 수 없는 사용자에게도 페이지가 XR 콘텐츠를 광고하게 됨. -
isSessionSupported()
가 적절한 하드웨어가 있을 때 명시적 동의를 요청하고, 하드웨어가 없을 때는 적당히 무작위로 지연 후false
를 반환한다. 이때 콘텐츠는 XR 하드웨어가 연결되지 않은 경우와 사용자가 명시적 동의를 거부한 경우를 구분할 수 없어야 한다.
어떤 방식을 선택하든, 명시적 동의 없이 XR 하드웨어에 대한 추가 정보를 노출해서는 안 됩니다.
14. 통합(Integrations)
14.1. 권한 정책(Permissions Policy)
이 명세는 정책 제어 기능(policy-controlled feature)을 정의합니다. 이 기능은 공간
추적(spatial tracking)이 필요한 XRSession
이
requestSession()
을
통해 반환될 수 있는지, 그리고 공간 추적이 필요한 세션 모드 지원 여부가 isSessionSupported()
또는 devicechange 이벤트로 표시될 수 있는지 제어합니다. 이 기능은 navigator.xr
객체에 적용됩니다.
이 기능의 식별자는 "xr-spatial-tracking"
입니다.
이 기능의 기본 허용 목록(default allowlist)은
["self"]
입니다.
참고: 문서의 origin이 "xr-spatial-tracking"
permissions policy를 사용할 수 없는 경우, 모든 몰입형 세션이 차단됩니다. 모든 몰입형 세션은 공간 추적을 필요로
하기 때문입니다. 인라인 세션은 여전히 허용되지만,
"viewer"
XRReferenceSpace
만
사용할 수 있도록 제한됩니다.
14.2. Permissions API 통합
[permissions] API는 웹사이트가 사용자에게 권한을 요청하고, 어떤 권한이 부여되었는지 질의할 수 있는 일관된 방법을 제공합니다.
"xr"
강력한
기능(powerful feature)의 권한 관련 알고리즘과 타입은 다음과 같이 정의됩니다:
- permission descriptor type
-
dictionary
:XRPermissionDescriptor PermissionDescriptor {XRSessionMode
;mode sequence <DOMString >
;requiredFeatures sequence <DOMString >
; };optionalFeatures name
forXRPermissionDescriptor
는 "xr"입니다. - permission result type
-
[
Exposed =Window ]interface
:XRPermissionStatus PermissionStatus {attribute FrozenArray <DOMString >
; };granted - permission query algorithm
-
"xr" 권한을
XRPermissionDescriptor
descriptor와XRPermissionStatus
status로 질의하려면, UA는 다음 단계를 반드시 수행해야 합니다:-
status의
state
를 descriptor의 permission state로 설정합니다. -
status의
state
가"denied"
이면, status의granted
를 빈FrozenArray
로 설정하고, 이 단계를 중단합니다. -
result를 요청된 기능 해석 결과로 설정합니다. 인자로는 descriptor의
requiredFeatures
,optionalFeatures
,mode
를 사용합니다. -
result가
null
이면 다음을 수행합니다:-
status의
granted
를 빈FrozenArray
로 설정합니다. -
이 단계를 중단합니다.
-
-
result의 필드 (consentRequired, consentOptional, granted)를 가져옵니다.
-
status의
granted
를 granted로 설정합니다. -
consentRequired와 consentOptional이 모두 비어 있다면, status의
state
를"granted"
로 설정하고 이 단계를 중단합니다.
-
- permission request algorithm
-
"xr" 권한 요청을
XRPermissionDescriptor
descriptor와XRPermissionStatus
status로 수행하려면, UA는 다음 단계를 반드시 수행해야 합니다:-
status의
granted
를 빈FrozenArray
로 설정합니다. -
requiredFeatures를 descriptor의
requiredFeatures
로 설정합니다. -
optionalFeatures를 descriptor의
optionalFeatures
로 설정합니다. -
device를 현재 디바이스 획득 결과로 설정합니다. 인자로는 mode, requiredFeatures, optionalFeatures를 사용합니다.
-
result를 요청된 기능 해석 결과로 설정합니다. 인자로는 requiredFeatures, optionalFeatures,
mode
를 사용합니다. -
result가
null
이면 다음을 수행합니다: -
result의 필드 (consentRequired, consentOptional, granted)를 가져옵니다.
-
이 시점에서 사용자 에이전트는 consentRequired 및 consentOptional에 포함된 기능 사용에 대해 사용자의 권한을 요청할 수 있습니다. 이 프롬프트 결과는 해당 기능 활성화에 대한 사용자 의도 신호 판단에 포함되어야 합니다.
-
consentRequired의 각 feature에 대해 다음을 수행합니다:
-
consentOptional의 각 feature에 대해 다음을 수행합니다:
-
status의
granted
를 granted로 설정합니다. -
granted의 모든 요소를 device의 granted features 집합에 추가합니다. (해당 mode에 대해)
참고: 사용자 에이전트는 사용자 의도 신호를 판단할 때, 요청된 모든 기능에 대한 권한 프롬프트를 한 번에 묶어서 보여줄 수도 있고, 하나씩 순차적으로 보여줄 수도 있습니다.
참고: 웹 애플리케이션의 사용자 의도를 판단할 때, 사용자 에이전트는 반드시 해당 앱이 사용자가 명시적으로 웹 애플리케이션으로 실행했는지 확인해야 하며, 단순히 origin이 설치된 웹 애플리케이션과 일치하는지만 확인해서는 안 됩니다.
-
요청된 기능
해석(resolve the requested features)을 requiredFeatures와 optionalFeatures,
XRSessionMode
mode에 대해 수행하려면, 사용자 에이전트는 다음 단계를 반드시 수행해야 합니다:
-
device를 mode, requiredFeatures, optionalFeatures에 대해 현재 디바이스 얻기의 결과로 설정한다.
-
previouslyEnabled를 device의 허용된 기능 집합(set of granted features) 중 mode에 해당하는 것으로 설정한다.
-
device가
null
이거나 device의 지원 모드 목록(list of supported modes)에 mode가 포함되어 있지 않으면 다음 단계를 실행한다:-
튜플(tuple) (consentRequired, consentOptional, granted)을 반환한다.
-
-
mode와 연관된 기본 기능(default features) 테이블에 있는 모든 기능 기술자(feature descriptor)를 granted에 이미 존재하지 않는 경우 추가한다.
-
requiredFeatures의 각 feature에 대해 다음 단계를 수행한다:
-
feature가
null
이면 다음 항목으로 continue한다. -
feature가 올바른 기능 기술자(feature descriptor)가 아니면
null
을 반환한다. -
feature가 이미 granted에 있으면 다음 항목으로 continue한다.
-
요청 문서의 origin이 feature requirements 테이블에 따라 feature에 필요한 권한 정책(permissions policy) 사용이 허용되지 않으면
null
을 반환한다. -
session의 XR 디바이스가 feature가 설명하는 기능을 지원할 수 없거나 사용자 에이전트가 그 기능을 거부한 경우
null
을 반환한다. -
feature가 설명하는 기능이 명시적 동의(explicit consent)를 필요로 하며 feature가 previouslyEnabled에 없다면 consentRequired에 추가한다.
-
그 외에는 feature를 granted에 추가한다.
-
-
optionalFeatures의 각 feature에 대해 다음 단계를 수행한다:
-
feature가
null
이면 다음 항목으로 continue한다. -
feature가 올바른 기능 기술자(feature descriptor)가 아니면 다음 항목으로 continue한다.
-
feature가 이미 granted에 있으면 다음 항목으로 continue한다.
-
요청 문서의 origin이 feature requirements 테이블에 따라 feature에 필요한 권한 정책(permissions policy) 사용이 허용되지 않으면 다음 항목으로 continue한다.
-
session의 XR 디바이스가 feature가 설명하는 기능을 지원할 수 없거나 사용자 에이전트가 그 기능을 거부한 경우 다음 항목으로 continue한다.
-
feature가 설명하는 기능이 명시적 동의(explicit consent)를 필요로 하며 feature가 previouslyEnabled에 없다면 consentOptional에 추가한다.
-
그 외에는 feature를 granted에 추가한다.
-
-
튜플(tuple)
(|consentRequired|, |consentOptional|, |granted|)
을 반환한다.
변경 사항
2022년 3월 31일자 Candidate Recommendation Snapshot 이후 변경 사항
-
XRSession의 granted features 노출 (GitHub #1296)
-
isSystemKeyboardSupported 속성 지원 추가 (GitHub #1314)
-
visibile-blurred에서 getPose 동작 명확화 (GitHub #1332)
-
Transient intent 추가 (GitHub #1343)
-
XRInputSource가 다른 곳에서 보이는지 나타내는 속성 초안 추가 (GitHub #1353)
-
rgb와 srgb 동작 명확화 (GitHub #1359)
2020년 7월 24일자 Working Draft 이후 변경 사항
-
predictedDisplayTime 수정 및 inline 동작 정의 (GitHub #1230)
-
XRFrame.predictedDisplayTime 추가 (GitHub #1217)
-
targetFrameRate 및 supportedFrameRates 지원 추가 (GitHub #1201)
-
foveation 지원 추가 (
fixedFoveation
(GitHub #1195)) -
세션이 명시적으로 요청했거나 모드에 따라 암묵적으로 부여된 기능만 사용하도록 제한 (GitHub #1189)
-
암묵적 사용자 의도 예시 강화 (GitHub #1188)
-
각속도 및 선속도 지원 추가 (GitHub #1182)
-
XRReferenceSpaces에 대한 플랫폼 규칙 일관성 보장 (GitHub #1180)
-
composition disabled 플래그를 composition enabled로 반전 (GitHub #1172)
-
이미 종료된 세션에서 end()가 반환하는 promise 거부 (GitHub #1170)
-
requestAnimationFrame 중 세션 종료 감지 (GitHub #1169)
-
recommendedViewportScale에 양자화 요구 (GitHub #1151)
-
sessionsupported pref autogranting을 비규범적으로 변경 (GitHub #1146)
-
비시각적 사용을 포함하는 XR 디바이스 정의 추가 (GitHub #927)
-
최근 프라이버시 논의 결론 반영 (GitHub #1124)
-
isSessionSupported가 사용자 의도 대신 권한 사용하도록 전환 (GitHub #1136)
-
최소 viewport scale이 변경될 수 있음을 명확화 (GitHub #1134)
-
지문 채취 관련 PR 개선 (GitHub #1133)
-
requestViewportScale/recommendedViewportScale 추가 (GitHub #1132)
-
프레임버퍼 scale factor가 width/height에 각각 적용됨을 명확화 (GitHub #1131)
-
pending render state가 항상 적용되도록 보장 (GitHub #1128)
-
xr-spatial-tracking permissions policy에서 context XR 호환성 제한 (GitHub #1126)
-
updateRenderState 변경 적용 시점 변경 (GitHub #1111)
2019년 10월 10일자 Working Draft 이후 변경 사항
신규 기능:
-
secondary views 기능 추가 (GitHub #1083)
-
XRRenderStateInit에 layers 시퀀스 추가 (GitHub #999)
-
입력 소스를 primary/auxiliary로 분리 (GitHub #929)
-
squeeze 이벤트 정의 (GitHub #893)
변경 사항:
-
Primary view는 항상 활성 상태여야 함 (GitHub #1105)
-
makeXRCompatible()에서 context loss를 올바르게 처리 (GitHub #1097)
-
active view 개념 도입 (GitHub #1096)
-
프레임 및 viewport 캐싱을 명시적으로 수정 (GitHub #1093)
-
다양한 객체 캐싱 허용 (GitHub #1088)
-
framebufferScaleFactor 클램핑 허용 (GitHub #1084)
-
"immersive device 선택 보장"의 스레딩 특성 명확화, xrCompatible 폐기 (GitHub #1081)
-
native origin 관련 일부 내용 명확화 (GitHub #1071)
-
문서 가시성 체크를 UA 선택으로 변경 (GitHub #1067)
-
'check the layers state' 알고리즘 추가 (GitHub #1064)
-
null 및 emulated pose 관련 다양한 변경 (GitHub #1058)
-
XRInputSource/frame에서 올바른 입력 프레임 의미 명시 (GitHub #1053)
-
XRRigidTransform에 대한 검증 추가 (GitHub #1043)
-
빈 입력 프로필 배열 사용 시점 소폭 변경 (GitHub #1037)
-
trusted ui에서 visible-blurred 사용 허용, 텍스트 입력 유출 주의 (GitHub #1034)
-
window.rAF() 관련 일부 내용 명확화 (GitHub #1033)
-
작업 및 promise 처리 방식 정리 (GitHub #1032)
-
render state가 전달되지 않으면 updateRenderState() 단락 실행 (GitHub #1031)
-
responsible, active, focused document 사용 제거 (GitHub #1030)
-
context isolation에서 browsing context와 realm 관련 상황 명확화 (GitHub #1029)
-
reset 이벤트가 offset space에서 동작함을 명시 (GitHub #1024)
-
각 객체가 생성되는 realm을 명확히 명시 (GitHub #1023)
-
rAF() 콜백 인자에 현재 타임스탬프 사용 (GitHub #1015)
-
세션 feature 요청 시 session 파라미터 불필요 (GitHub #1012)
-
rAF 내에서 rAF 콜백 취소 허용 (GitHub #1005)
-
opaque framebuffer가 특정 세션을 참조함을 언급 (GitHub #1004)
-
promise가 resolve된 후에만 초기 inputsourcechange 이벤트 발생 (GitHub #1002)
-
framebufferScaleFactor의 효과 문서화 (GitHub #993)
-
depth||stencil 요청 시 depth&&stencil 결과 허용 (GitHub #987)
-
isSessionSupported 반환값에 더 많은 유연성 허용 (GitHub #986)
-
inline 디바이스를 통한 tracking/input 데이터 노출 시점 명확화 (GitHub #985)
-
viewport shape에 상식적 제한 추가 (GitHub #976)
-
preserveDrawingBuffer가 이곳에 영향 없음 명시 (GitHub #975)
-
inline 세션의 visiblityState 동작 명확화 (GitHub #974)
-
opaque framebuffer가 dirty로 간주되는 시점 정의 (GitHub #970)
-
디바이스 변경 시 inline 디바이스 갱신 가능성 명시 (GitHub #947)
-
bounded reference space 동작 명확화 (GitHub #938)
-
XR 호환성 알고리즘 다수 수정 (GitHub #921)
-
trusted UI 섹션 보완 (GitHub #875)
-
depthNear 및 depthFar 사용 방식 명확화 (GitHub #888)
-
local-floor 공간이 추정 높이를 사용할 때 emulatedPosition이 true가 아님을 명확화 (GitHub #871)
2019년 2월 5일자 First Public Working Draft 이후 변경 사항
신규 기능:
-
XRInputSource->profiles에 입력 프로필 이름 목록 추가 (GitHub #695)
-
XREye에 none 변형 추가 (GitHub #641)
-
명시적 inline XR 디바이스 추가 (GitHub #737)
-
데이터 조정 및 보호 기능을 통한 Pose 프라이버시 고려사항 추가 (GitHub #761)
-
Reference space 프라이버시 고려사항 추가 (GitHub #762)
-
민감 정보 및 사용자 의도 정의 (GitHub #757)
-
필수 및 선택적 기능(기능 의존성) 정의 (GitHub #749)
-
트래킹 손실 및 복구 처리 (GitHub #559)
-
blur/focus를 visibilitychange로 변경 (GitHub #687)
-
입력 소스 이벤트 순서 정의 (GitHub #629)
-
입력 소스 목록 유지 방식 설명 (GitHub #628)
-
origin offset을 불변으로 지정 (GitHub #612)
-
XRRenderState에 inlineVerticalFieldOfView 추가 (GitHub #519)
-
Gamepad 통합 문서화 (GitHub #553)
-
XRWebGLLayer에 ignoreDepthValues 속성 추가 (GitHub #548)
-
XRSpace에 XREnvironmentBlendMode.viewerSpace 추가 (GitHub #522)
-
XRPose 및 관련 리팩터링 추가 (GitHub #496)
제거된 기능:
-
canvas inline을 single로 변경, XRPresentationContext 제거 (GitHub #656)
-
XRLayer 기본 타입 제거 (GitHub #688)
-
XRWebGLLayer.requestViewportScaling() 제거 (GitHub #631)
-
XRWebGLLayer에서 context 속성 제거 (GitHub #707)
-
요청 값만 반영하는 속성 제거 (GitHub #574)
-
XRSessionCreationOptions 제거 (GitHub #566)
변경 사항:
-
XRWebGLLayer의 필수 clear 동작 설명 (GitHub #866)
-
XRWebGLLayer 프레임버퍼가 항상 premultiplied alpha를 사용하도록 명시 (GitHub #840)
-
reset 이벤트의 변환 방향 명확화 (GitHub #843)
-
기능 요구사항 충족 방식 정의 (GitHub #839)
-
필요 시 세션이 immersive가 아닌 inline인지 확인 (GitHub #834)
-
현재 stereo inline 세션 비허용 (GitHub #829)
-
projectionMatrix에서 detached buffer 처리 (GitHub #830)
-
makeXRCompatible()에서 immersive 디바이스 선택 보장 (GitHub #809)
-
features를 'any' 시퀀스로 변경 (GitHub #807)
-
'fire an input source' 알고리즘 링크, frame 명시적 생성 (GitHub #797)
-
스펙 및 explainer에서 Environment blend mode 제거 (GitHub #804)
-
각 메서드에 대한 설명 제공 (GitHub #798)
-
UA가 수동 디바이스 활성화 단계를 표시하도록 요구 (GitHub #799)
-
compositor 관련 설명 보완 (GitHub #805)
-
강체 변환 행렬 산출을 위한 행렬 수학 명확화 (GitHub #806)
-
UA가 clip plane을 제한할 수 있도록 허용 (GitHub #802)
-
getViewport()에서 오래된 XRView 사용 금지 (GitHub #796)
-
depth/alpha/stencil 값 사용 방식 명시 (GitHub #800)
-
profiles 변경 시 입력 소스 이벤트 발생 (GitHub #795)
-
reset 이벤트 발생 시점 명확화 (GitHub #637)
-
requestReferenceSpace()가 쿼리를 거부할 수 있는 시점 명시 (GitHub #651)
-
XRRay.matrix를 고유하게 만들고 산출 단계 추가 (GitHub #655)
-
promise 반환에 TAG 권고사항 적용 (GitHub #700)
-
requestSession()의 경쟁 조건 부분을 메인 스레드로 이동 (GitHub #706)
-
exclusive access에서 작은 오버레이 UI 허용 명확화 (GitHub #709)
-
'end the session'과 'shut down the session' 병합, 명확화, onend 이벤트 추가 (GitHub #710)
-
inline 세션에서 XR compat 플래그 체크하지 않음 (GitHub #705)
-
position DOMPointInit 검증 (GitHub #568)
-
native origin 명시적 정의 (GitHub #621)
-
buttonIndex 제거 (GitHub #741)
-
"immersive-ar" 및 XRRay 참조 제거 (GitHub #784)
-
XRInputSource.gamepad에 대한 참조 explainer 및 index.bs에서 제거 (GitHub #782)
-
잘못된 view로 getViewport() 호출 시 오류 발생 (GitHub #771)
-
세션 중간 동의 요청 차단 (GitHub #767)
-
XRPresentationContext 생성 명세화 (GitHub #501)
-
inputSources getter를 메서드에서 속성으로 변경 (GitHub #624)
-
필수 gamepad 인덱스를 -1로 변경 (GitHub #690)
-
detached array 처리 (GitHub #684)
-
민감 UI가 WebXR 콘텐츠를 숨기도록 요구 (GitHub #742)
-
xr-standard gamepad 매핑을 더 엄격하게 지정 (GitHub #735)
-
XRRay.matrix 산출 알고리즘 수정 (GitHub #728)
-
XRRay.matrix 알고리즘에서 detached array 수정 (GitHub #716)
-
requestSession()에서 지원되지 않는 모드 처리 단순화 (GitHub #714)
-
XRRenderState 관련 일부 명확화 (GitHub #703)
-
'list of pending render states'를 'pending render state'로 대체 (GitHub #701)
-
gamepad placeholder 버튼 및 축 정의 보완 (GitHub #661)
-
터치패드가 터치되지 않을 때 보고해야 하는 값 명확화 (GitHub #660)
-
getPose 인자 referenceSpace를 baseSpace로 이름 변경 (GitHub #659)
-
변환 곱셈 순서 수정 (GitHub #649)
-
local 및 local-floor 트래킹 가정 명확화 (GitHub #648)
-
사용 가능한 공간 단순화 (GitHub #626)
-
requestSession: 먼저 사용자 활성화 확인 (GitHub #685)
-
boundsGeometry가 effective origin 기준으로 동작하도록 변경 (GitHub #613)
-
views 배열이 채워지는 방식 명시 (GitHub #614)
-
Gamepad id가 unknown이어야 하는 경우 식별 (GitHub #615)
-
XRSpace, get(Viewer)Pose 정의 전면 개정 (GitHub #609)
-
supportsSessionMode를 supportsSession으로 이름 변경 (GitHub #595)
-
reference space 타입 및 인터페이스 통합 (GitHub #587)
-
inverse 속성이 항상 동일한 객체 반환 (GitHub #586)
-
세션 종료 시 미해결 promise 거부 (GitHub #585)
-
projection matrix에 shear 포함 가능 명시 (GitHub #575)
-
updateRenderState가 throw할 수 있는 예외 설명 (GitHub #511)
-
requestSession() 및 세션 초기화 편집 (GitHub #601)
-
XRRigidTransform의 inverse를 메서드에서 속성으로 변경 (GitHub #560)
-
합성 시 depth 값 사용 시점 명시 (GitHub #563)
-
Stationary 하위 타입 지원은 all-or-nothing으로 변경 (GitHub #537)
-
outputContext를 XRRenderState로 이동 (GitHub #536)
-
getViewerPose가 non-rAF XRFrame에서 오류를 throw하도록 명시 (GitHub #535)
-
viewMatrix 제거 및 XRTransform.inverse() 추가 (GitHub #531)
-
XRHandedness enum을 '' 대신 'none' 사용으로 변경 (GitHub #526)
-
tracked-pointer ray의 권장 인체공학 명시 (GitHub #524)
-
XRRay 생성자 명확화 및 정규화 정의 (GitHub #521)
-
identity reference space에 대한 명세 텍스트 추가 (GitHub #520)
-
immersive 세션이 거부되는 시점 명확화 (GitHub #360)
-
base layer 없이 frame 콜백이 호출되지 않도록 명시 (GitHub #512)
15. 감사의 글
WebXR Device API 명세에 기여해주신 다음 분들께 감사드립니다:
그리고 이 모든 여정을 시작하게 해주신 Vladimir Vukicevic (Unity)께 특별히 감사드립니다!