WebXR 깊이 감지 모듈

W3C 작업 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-webxr-depth-sensing-1-20260825/
최신 공개 버전:
https://www.w3.org/TR/webxr-depth-sensing-1/
편집자 초안:
https://immersive-web.github.io/depth-sensing/
이전 버전:
이력:
https://www.w3.org/standards/history/webxr-depth-sensing-1/
피드백:
GitHub
편집자:
(Google)
이전 편집자:
(Google)
참여:
이슈 제출 (열린 이슈)
메일링 리스트 아카이브
W3C의 #immersive-web IRC

초록

Depth Sensing API는 WebXR Device API의 기능을 확장하는 모듈입니다. 이는 앱이 더 몰입감 있는 경험을 제공하기 위해 지원되는 XR 장치가 계산한 depth 정보를 얻을 수 있게 합니다. Depth Sensing API의 예시 use case에는 가상 객체와 실제 세계의 물리적 상호작용 시뮬레이션, occlusion, 그리고 사용자 환경에 대한 향상된 인식을 활용할 수 있는 비시각적 애플리케이션이 포함되지만 이에 한정되지는 않습니다.

이 문서의 상태

이 섹션은 발행 시점의 문서 상태를 설명합니다. 현재 W3C 발행물과 이 기술 보고서의 최신 개정판 목록은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

Immersive Web Working Group은 그룹이 아직 처리하지 않은 모든 버그 보고 목록을 관리합니다. 이 초안은 Working Group에서 아직 논의되어야 하는 일부 pending issue를 강조합니다. 이러한 issue의 결과에 대해서는, 유효한지 여부를 포함하여 어떤 결정도 내려지지 않았습니다. 미해결 issue에 대해 제안된 명세 텍스트를 포함한 pull request를 강력히 권장합니다.

이 문서는 Immersive Web Working GroupRecommendation track을 사용하여 Working Draft로 발행했습니다. 이 문서는 W3C Recommendation이 되는 것을 목표로 합니다.

Working Draft로 발행되었다고 해서 W3C 및 그 회원의 보증을 의미하지는 않습니다. 이는 초안 문서이며 언제든지 다른 문서에 의해 업데이트, 대체 또는 폐기될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 부적절합니다.

이 문서는 W3C Patent Policy에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 그룹의 deliverables와 관련하여 이루어진 모든 patent disclosures의 공개 목록을 관리합니다. 해당 페이지에는 patent disclosure를 위한 안내도 포함되어 있습니다. 개인이 Essential Claim(s)을 포함한다고 믿는 patent에 대해 실제 지식을 가지고 있는 경우, W3C Patent Policy의 6절에 따라 그 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C Process Document의 적용을 받습니다.

1. 소개

Virtual Reality 및 Augmented Reality가 더 널리 보급됨에 따라, 사용자가 위치한 환경에 대한 더 자세한 정보에 접근할 수 있게 하는 새 기능들이 native API에 도입되고 있습니다. Depth Sensing API는 그러한 기능 중 하나를 WebXR Device API에 가져오며, WebXR 기반 경험의 작성자가 사용자의 장치에서 사용자 환경의 실제 세계 geometry까지의 거리에 대한 정보를 얻을 수 있게 합니다.

이 문서는 독자가 WebXR Device APIWebXR Augmented Reality Module 명세에 익숙하다고 가정합니다. 이 문서는 이들 위에 추가 기능을 제공하여 XRSessions에 기능을 더하기 때문입니다.

1.1. 용어

이 문서에서는 AR을 증강 현실(Augmented Reality)을 나타내는 약어로, VR을 가상 현실(Virtual Reality)을 나타내는 약어로 사용한다.

이 문서에서는 XR 장치에서 반환되거나 API 자체에서 반환되는 깊이 정보를 포함하는 바이트 배열을 지칭할 때 "깊이 버퍼", "깊이 버퍼 데이터", "깊이 데이터"와 같은 용어를 서로 바꾸어 사용한다. 깊이 버퍼의 구체적인 내용에 관한 자세한 정보는 명세의 data, texture, 및 texture 항목에서 확인할 수 있다.

이 문서에서는 뷰의 왼쪽 위 모서리에 원점이 있고 X축은 오른쪽으로 증가하며 Y축은 아래쪽으로 증가하는 좌표계를 지칭할 때 정규화된 뷰 좌표라는 용어를 사용한다.

네이티브 깊이 버퍼네이티브 깊이 감지에 의해 생성되는 구현 정의 저장소로서 원시 깊이 값을 포함한다. 이는 CPU에서 접근 가능한 할당 영역 또는 네이티브 API 텍스처일 수 있으며 작성자에게 직접 노출되지 않는다. 이는 너비, 높이 및 데이터 형식을 가지며, 하나의 2차원 레이어 또는 크기가 동일한 여러 2차원 배열 레이어로 구성된다. 특정 XRView에 대해 반환된 비레이어형 네이티브 깊이 버퍼는 해당 뷰의 깊이 값을 포함한다. 레이어형 네이티브 깊이 버퍼는 획득되는 시점의 XRSession뷰 목록의 각 항목마다 하나의 배열 레이어를 반드시 포함해야 하며, 해당 레이어는 그 뷰들과 동일한 순서로 대응해야 한다.

네이티브 깊이 정보네이티브 깊이 감지를 질의한 구현 정의 결과이다. 여기에는 네이티브 깊이 버퍼, 그 값을 미터로 변환하기 위한 배율, 깊이 좌표 변환 행렬, 그리고 버퍼를 생성한 센서의 투영 행렬transform이 포함된다.

2. 초기화

2.1. Feature descriptor

애플리케이션은 적절한 feature descriptor를 전달하여 XRSession에서 depth sensing이 활성화되도록 요청할 수 있습니다. 이 module은 depth sensing feature를 위한 새 valid feature descriptor로 새 문자열 depth-sensing을 도입합니다.

장치가 capable of supporting depth sensing feature라고 할 수 있으려면, 장치가 native depth sensing capability를 노출해야 합니다. inline XR device는 depth sensing feature를 capable of supporting하는 것으로 취급해서는 안 됩니다.

Depth sensing feature는 feature policy의 적용을 받으며, 요청 문서의 origin에서 "xr-spatial-tracking" policy가 허용되어야 합니다.

2.2. 의도된 depth type, data usage 및 data format

enum XRDepthType {
  "raw",
  "smooth",
};
enum XRDepthUsage {
  "cpu-optimized",
  "gpu-optimized",
};
enum XRDepthDataFormat {
  "luminance-alpha",
  "float32",
  "unsigned-short",
};

다음 표는 다양한 data format을 소비할 수 있는 방법을 요약합니다:

데이터 형식 WebGL 형식 WebGPU 형식 깊이 버퍼 항목의 크기 CPU에서의 사용 GPU에서의 사용
"luminance-alpha" LUMINANCE_ALPHA 지원되지 않음 8비트의 2배 dataUint16Array로 해석 WebGL에서 Luminance 및 Alpha 채널을 검사하여 단일 값을 다시 조립한다. Luminance 채널에는 최하위 바이트가 포함된다.
"float32" R32F "r32float" 32비트 dataFloat32Array로 해석 Red 채널을 검사하고 해당 값을 사용한다.
"unsigned-short" R16UI "r16uint" 16비트 dataUint16Array로 해석 Red 채널을 검사하고 해당 값을 사용한다.

"luminance-alpha" 데이터 형식은 XRGPUDepthInformation과 함께 사용해서는 안 된다.

2.3. Session configuration

dictionary XRDepthStateInit {
  required sequence<XRDepthUsage> usagePreference;
  required sequence<XRDepthDataFormat> dataFormatPreference;
  sequence<XRDepthType> depthTypeRequest;
  boolean matchDepthView = true;
};

usagePreference는 session에 대해 원하는 depth sensing usage를 설명하는 데 사용되는 XRDepthUsage들의 ordered sequence입니다.

dataFormatPreference는 session에 대해 원하는 depth sensing data format을 설명하는 데 사용되는 XRDepthDataFormat들의 ordered sequence입니다.

depthTypeRequest는 session에 대해 원하는 depth sensing type을 설명하는 데 사용되는 XRDepthType들의 ordered sequence입니다. 이 요청은 사용자 에이전트가 무시할 수 있습니다.

matchDepthView는 depth information의 viewXRView와 정렬되어야 함을 요청합니다. 이것이 true이면, XRSystem은 현재 frame을 반영하는 depth information을 반환하는 것이 좋습니다. 이것이 false이면, XRSystem은 이전 시점에 capture된 depth information을 반환할 수 있습니다.

NOTE: matchDepthViewfalse이면, 작성자는 XRDepthInformationview를 사용하여 reprojection을 수행하는 것이 좋습니다.

XRSessionInit dictionary는 새 depthSensing key를 추가하여 확장됩니다. 이 key는 XRSessionInit에서 optional이지만, depth-sensingrequiredFeatures 또는 optionalFeatures 중 하나에 포함된 경우에는 반드시 제공되어야 합니다.

partial dictionary XRSessionInit {
  XRDepthStateInit depthSensing;
};

Depth sensing feature가 required feature이지만 애플리케이션이 depthSensing key를 제공하지 않은 경우, 사용자 에이전트는 이를 unresolved required feature로 취급하고 requestSession(mode, options) promise를 NotSupportedError로 reject해야 합니다. optional feature로 요청된 경우, 사용자 에이전트는 feature request를 무시하고 새로 생성된 session에서 depth sensing을 활성화하지 않아야 합니다.

Depth sensing feature가 required feature이지만 XRDepthStateInit으로 호출된 finding supported configuration combination 알고리즘의 결과가 null이면, 사용자 에이전트는 이를 unresolved required feature로 취급하고 requestSession(mode, options) promise를 NotSupportedError로 reject해야 합니다. optional feature로 요청된 경우, 사용자 에이전트는 feature request를 무시하고 새로 생성된 session에서 depth sensing을 활성화하지 않아야 합니다.

Depth sensing이 활성화된 상태로 XRSession이 생성되면, depthUsage, depthDataFormat, 및 depthType attribute는 XRDepthStateInit으로 호출된 finding supported configuration combination 알고리즘의 결과로 설정되어야 합니다. depthActive는 기본적으로 true여야 합니다.

Note: 이 알고리즘의 의도는 preferences를 가장 제한적인 것에서 가장 덜 제한적인 것으로 처리하는 것입니다. 따라서 먼저 단일 항목만 표시된 항목을 처리하고, 그다음 여러 항목, 마지막으로 preference가 표시되지 않은 경우를 처리합니다.

depthStateInit dictionary가 주어졌을 때 depth sensing API를 위한 supported configuration combination을 찾기 위해, 사용자 에이전트는 다음 알고리즘을 실행해야 합니다:
  1. depthTypeRequestdepthStateInit 안의 depthTypeRequest key에 포함된 값으로 둡니다. 이것이 설정되어 있지 않으면 빈 sequence로 둡니다.

  2. selectedTypenull로 둡니다

  3. usagePreferencedepthStateInit 안의 usagePreference key에 포함된 값으로 둡니다

  4. selectedUsagenull로 둡니다.

  5. dataFormatPreferencedepthStateInit 안의 dataFormatPreference key에 포함된 값으로 둡니다

  6. selectedDataFormatnull로 둡니다.

  7. processingOrder를 (preferences, selection) 쌍의 sequence로 둡니다. 여기서 selection은 이전 단계에서 도입된 변수 중 하나에 대한 reference입니다: [(depthTypeRequest, selectedType), (usagePreference,selectedUsage),(dataFormatPreference,selectedDataFormat)]

  8. processingOrder 안의 각 (preferences, selection)에 대해 다음 단계를 수행합니다

    1. preferences가 단일 값만 포함하면, selection을 그 값으로 설정합니다.

  9. processingOrder 안의 각 (preferences, selection)에 대해 다음 단계를 수행합니다:

    1. selectionnull이 아니면, 다음 entry로 계속합니다.

    2. preferences sequence가 비어 있으면, 다음 entry로 계속합니다.

    3. preferences 안의 각 preference에 대해 다음 단계를 수행합니다:

    4. preferenceselectedType,selectedUsage,selectedDataFormat의 다른 값들이 장치의 native depth sensing capabilities에 의해 supported depth sensing configuration으로 간주되지 않으면, 다음 entry로 계속합니다.

    5. selectionpreference로 설정하고 이 nested steps를 중단합니다.

  10. processingOrder 안의 각 (preferences, selection)에 대해 다음 단계를 수행합니다:

    1. selectionnull이 아니면, 다음 entry로 계속합니다.

    2. selectionselectedType,selectedUsage,selectedDataFormat의 다른 값들과 함께 preferred native depth sensing capability에 의해 결정된 값으로 설정합니다.

  11. selectedType,selectedUsage,selectedDataFormat 중 하나라도 null이면, null을 반환하고 이 단계를 중단합니다.

  12. selectedType,selectedUsage,selectedDataFormat이 장치의 native depth sensing capabilities에 의해 supported depth sensing configuration으로 간주되면, selectedType,selectedUsage,selectedDataFormatdepth sensing configuration을 반환하고 이 단계를 중단합니다.

  13. depthTypeRequest가 빈 목록이 아니면, 이를 빈 목록으로 설정하고 이 단계를 반복합니다.

  14. null을 반환하고 이 단계를 중단합니다.

지원되는 구성 조합을 찾을WebGPU 호환 세션의 경우, "gpu-optimized" 사용과 "luminance-alpha" 데이터 형식을 결합한 구성은 지원되는 깊이 감지 구성으로 간주해서는 안 된다.

참고: 사용자 에이전트는 기존의 모든 사용 및 데이터 형식 조합을 지원할 필요가 없다. 이는 데이터를 효율적인 방식으로 제공할 수 있도록 하기 위한 것이며, 기반 플랫폼에 따라 달라진다. 이 결정은 애플리케이션 개발자에게 추가적인 부담을 준다. 이는 API 복잡성을 숨기는 라이브러리를 만들어 완화할 수 있으며, 그 과정에서 성능을 희생할 수도 있다.

깊이 감지 API를 지원할 수 있는 사용자 에이전트는 적어도 하나의 XRDepthUsage 모드를 반드시 지원해야 한다. 깊이 감지 API를 지원할 수 있는 사용자 에이전트는 "luminance-alpha" 데이터 형식을 반드시 지원해야 하며, 다른 형식도 지원할 수 있다.

다음 코드는 깊이 감지 API가 필요한 세션을 요청하는 방법을 보여준다. 이 예제에서는 호출자가 CPU 및 GPU 최적화 사용 모두와 "luminance-alpha" 및 "float32" 형식 모두를 처리할 수 있으며, CPU와 "luminance-alpha"를 우선한다고 가정한다.
const session = await navigator.xr.requestSession("immersive-ar", {
  requiredFeatures: ["depth-sensing"],
  depthSensing: {
    usagePreference: ["cpu-optimized", "gpu-optimized"],
    dataFormatPreference: ["luminance-alpha", "float32"],
  },
});
partial interface XRSession {
  readonly attribute XRDepthUsage depthUsage;
  readonly attribute XRDepthDataFormat depthDataFormat;
  readonly attribute XRDepthType? depthType;
  readonly attribute boolean? depthActive;

  undefined pauseDepthSensing();
  undefined resumeDepthSensing();
};

depthUsage는 세션이 구성된 깊이 감지 사용 방식을 설명한다. 깊이 감지가 활성화되지 않은 세션에서 이 속성에 접근하면 사용자 에이전트는 반드시 InvalidStateError를 발생시켜야 한다.

depthDataFormat은 세션이 구성된 깊이 감지 데이터 형식을 설명한다. 깊이 감지가 활성화되지 않은 세션에서 이 속성에 접근하면 사용자 에이전트는 반드시 InvalidStateError를 발생시켜야 한다.

depthType은 세션이 구성된 깊이 감지 유형을 설명한다. 깊이 감지가 활성화되지 않은 세션에서 이 속성에 접근하면 사용자 에이전트는 반드시 InvalidStateError를 발생시켜야 한다. 런타임이 하나의 XRDepthType만 지원하거나 그 밖의 이유로 depthTypeRequest를 무시한 경우 이는 null을 반환할 수 있다.

depthActive는 현재 깊이 감지 활성 상태를 반환한다. 깊이 감지가 활성화되지 않은 세션에서 이 속성에 접근하면 사용자 에이전트는 반드시 InvalidStateError를 발생시켜야 한다. 이 값이 false이면 사용자 에이전트는 깊이 데이터를 가져오려는 시도를 반드시 거부해야 한다. 이 값이 true이면 사용자 에이전트는 유효한 깊이 데이터 또는 null을 반환할 수 있다.

resumeDepthSensing()XRSession session에서 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. sessionended 값이 true이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  2. framesession애니메이션 프레임으로 둔다.

  3. frame활성 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  4. depth-sensing 기능 설명자가 sessionXR 장치session 모드에 대한 활성화된 기능 목록포함되어 있지 않으면, NotSupportedError발생시키고 이 단계를 중단한다.

  5. 깊이 감지 활성 상태true이면 이 단계를 중단한다.

  6. 깊이 감지 활성 상태true로 설정한다.

pauseDepthSensing()XRSession session에서 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.
  1. sessionended 값이 true이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  2. framesession애니메이션 프레임으로 둔다.

  3. frame활성 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  4. depth-sensing 기능 설명자가 sessionXR 장치session 모드에 대한 활성화된 기능 목록포함되어 있지 않으면, NotSupportedError발생시키고 이 단계를 중단한다.

  5. 깊이 감지 활성 상태false이면 이 단계를 중단한다.

  6. 깊이 감지 활성 상태false로 설정한다.

3. Depth data 얻기

3.1. XRDepthInformation

[SecureContext, Exposed=Window]
interface XRDepthInformation {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;

  [SameObject] readonly attribute XRRigidTransform normDepthBufferFromNormView;
  readonly attribute float rawValueToMeters;
};

XRDepthInformation includes XRViewGeometry;

width attribute는 depth buffer의 width(즉 column 수)를 포함합니다.

height attribute는 depth buffer의 height(즉 row 수)를 포함합니다.

normDepthBufferFromNormView attribute는 depth buffer에 index할 때 적용되어야 하는 XRRigidTransform을 포함합니다. matrix가 나타내는 transformation은 coordinate system을 normalized view coordinates에서 normalized depth buffer coordinates로 변경하며, 이후 depth buffer의 widthheight로 scaling하여 absolute depth buffer coordinates를 얻을 수 있습니다.

Note: 애플리케이션이 결과 depth buffer를 mesh에 대한 texturing에 사용하려는 경우, mesh vertices의 texture coordinates가 normalized view coordinates로 표현되었는지, 또는 적절한 coordinate system change가 shader에서 수행되는지를 보장하도록 주의해야 합니다.

rawValueToMeters attribute는 meter 단위의 depth를 얻기 위해 depth buffer의 raw depth value에 곱해야 하는 scale factor를 포함합니다.

transform은 연결된 viewreference space 안에서 제공됩니다.

sensor가 연결된 view와 정렬되어 있으면, XRViewGeometry에서 포함된 모든 값은 연결된 view가 반환하는 값과 동일한 값을 반환해야 합니다.

XRDepthInformation에는 연결된 view가 있으며, 이는 sensor에 가장 가까운 XRView이고, XRDepthInformation을 retrieve하는 데 사용됩니다.

XRDepthInformation에는 연결된 sensor가 있으며, 이는 depth information이 얻어진 XRViewGeometrycontaining object입니다.

XRDepthInformation에는 depth buffer data를 포함하는 연결된 depth buffer가 있습니다. 서로 다른 XRDepthInformation들은 depth buffer 안에 서로 다른 concrete type의 객체를 저장할 수 있습니다.

XRDepthInformation 또는 이를 상속하는 모든 interface의 depth buffer에 접근하려고 할 때, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. depthInformation을 member에 접근한 instance로 둡니다.

  2. viewdepthInformationview로 둡니다.

  3. frameviewframe으로 둡니다.

  4. frameactive가 아니면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  5. frameanimationFrame이 아니면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  6. depthInformation의 member에 접근하는 데 필요한 일반 단계를 계속 진행합니다.

3.2. XRCPUDepthInformation

[Exposed=Window]
interface XRCPUDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute ArrayBuffer data;

  float getDepthInMeters(float x, float y);
};

data attribute는 필요한 경우 WebGL texture에 upload하기 적합한 raw format의 depth buffer information을 포함합니다. data는 padding 없이 row-major format으로 저장되며, 각 entry는 sensor의 near plane에서 users' environment까지의 거리에 대응하며, 단위는 지정되지 않습니다. 각 data entry의 크기와 type은 depthDataFormat에 의해 결정됩니다. 값은 rawValueToMeters를 곱하여 unspecified units에서 meters로 변환할 수 있습니다. normDepthBufferFromNormViewnormalized view coordinates에서 depth buffer의 coordinate system으로 transform하는 데 사용할 수 있습니다. 접근 시, depth buffer에 접근하는 알고리즘을 실행해야 합니다.

Note: 애플리케이션은 data array의 contents를 변경하려고 해서는 안 됩니다. 이는 getDepthInMeters(x, y) method가 반환하는 결과가 잘못될 수 있기 때문입니다.

getDepthInMeters(x, y) method는 coordinates에서 depth를 얻기 위해 사용할 수 있습니다. 호출 시, depth buffer에 접근하는 알고리즘을 실행해야 합니다.

getDepthInMeters(x, y) method가 XRCPUDepthInformation depthInformation에서 x, y로 호출되면, 사용자 에이전트는 다음 단계를 실행하여 coordinates에서 depth를 얻어야 합니다:

  1. viewdepthInformationview로, frameviewframe으로, sessionframesession으로 둡니다.

  2. x1.0보다 크거나 0.0보다 작으면, RangeErrorthrow하고 이 단계를 중단합니다.

  3. y1.0보다 크거나 0.0보다 작으면, RangeErrorthrow하고 이 단계를 중단합니다.

  4. normalizedViewCoordinates를 space 안의 3-dimensional point를 나타내는 vector로 둡니다. 여기서 x coordinate는 x로, y coordinate는 y로, z coordinate는 0.0으로, w coordinate는 1.0으로 설정됩니다.

  5. normalizedDepthCoordinatesnormalizedViewCoordinates vector에 depthInformationnormDepthBufferFromNormView를 왼쪽에서 premultiply한 결과로 둡니다.

  6. depthCoordinatesnormalizedDepthCoordinates를 scaling한 결과로 둡니다. 여기서 x coordinate는 depthInformationwidth로 곱하고 y coordinate는 depthInformationheight로 곱합니다.

  7. columndepthCoordinatesx coordinate 값으로 둡니다. 이를 integer로 truncate하고 [0, width-1] integer range로 clamp합니다.

  8. rowdepthCoordinatesy coordinate 값으로 둡니다. 이를 integer로 truncate하고 [0, height-1] integer range로 clamp합니다.

  9. indexrowwidth를 곱하고 column을 더한 값으로 둡니다.

  10. byteIndexindex에 depth data format의 크기를 곱한 값으로 둡니다.

  11. rawDepthdatabyteIndex index에서 찾은 값으로 둡니다. 이는 sessiondepthDataFormat에 따라 number로 해석됩니다.

  12. rawValueToMetersdepthInformationrawValueToMeters와 같게 둡니다.

  13. rawDepthrawValueToMeters를 곱한 값을 반환합니다.

partial interface XRFrame {
  XRCPUDepthInformation? getDepthInformation(XRView view);
};

getDepthInformation(view) method는 XRFrame에서 호출될 때, 애플리케이션이 frame에 관련된 CPU depth information을 얻기를 원한다는 것을 나타냅니다.

getDepthInformation(view) 메서드가 XRFrame frame에서 XRView view와 함께 호출되면, 사용자 에이전트는 다음 단계를 실행하여 CPU 깊이 정보를 얻어야 한다.

  1. sessionframesession으로 둔다.

  2. depth-sensing 기능 설명자가 sessionXR 장치session 모드에 대한 활성화된 기능 목록포함되어 있지 않으면, NotSupportedError발생시키고 이 단계를 중단한다.

  3. frameactive 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  4. frameanimationFrame 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  5. frameviewframe과 일치하지 않으면, InvalidStateError발생시키고 이 단계를 중단한다.

  6. sessiondepthUsage"cpu-optimized"가 아니면, InvalidStateError를 발생시키고 이 단계를 중단한다.

  7. depthInformationframeview가 주어졌을 때 CPU 깊이 정보 인스턴스를 생성한 결과로 둔다.

  8. depthInformation을 반환한다.

XRFrame frameXRView view가 주어졌을 때 CPU 깊이 정보 인스턴스를 생성하기 위해 사용자 에이전트는 다음 단계를 반드시 실행해야 한다.

  1. resultXRCPUDepthInformation의 새 인스턴스로 둔다.

  2. timeframetime으로 둔다.

  3. sessionframesession으로 둔다.

  4. devicesessionXR 장치로 둔다.

  5. depthActivefalse이면 null을 반환하고 이 단계를 중단한다.

  6. nativeDepthInformation을 지정된 view에 대해 time 시점에 유효한 깊이 정보를 device에 질의하여 얻은 네이티브 깊이 정보로 두며, 이때 sessiondepthType, depthUsage, 및 depthDataFormat을 고려한다.

  7. nativeDepthInformationnull이면 null을 반환하고 이 단계를 중단한다.

  8. nativeDepthBuffernativeDepthInformation네이티브 깊이 버퍼로 둔다.

  9. nativeDepthBuffer가 깊이 데이터에 대한 접근을 차단하기 위한 사용자 에이전트의 기준을 충족하면, null을 반환하고 이 단계를 중단한다.

  10. nativeDepthBuffer가 깊이 버퍼에서 사용할 수 있는 정보의 양을 제한하기 위한 사용자 에이전트의 기준을 충족하면, 그에 따라 nativeDepthBuffer를 조정한다.

  11. resultwidthnativeDepthBuffer의 너비로 초기화한다.

  12. resultheightnativeDepthBuffer의 높이로 초기화한다.

  13. resultnormDepthBufferFromNormViewnativeDepthInformation깊이 좌표 변환 행렬을 기반으로 하는 새로운 XRRigidTransform으로 초기화한다.

  14. resultrawValueToMetersnativeDepthInformation에서 제공한 배율로 초기화한다.

  15. resultdatanativeDepthBuffer에서 가져온 view의 원시 깊이 값 복사본으로 초기화한다.

  16. resultviewview로 초기화한다.

  17. resulttransformview참조 공간에서 time 시점의 센서 포즈로 초기화한다.

  18. result를 반환한다.

다음 코드는 XRFrameRequestCallback 안에서 depth data를 얻을 수 있는 방법을 보여줍니다. Depth sensing이 활성화되어 있고, usage가 "cpu-optimized"로, data format이 "luminance-alpha"로 설정된 session이라고 가정합니다:
const session = ...;          // Session created with depth sensing enabled.
const referenceSpace = ...;   // Reference space created from the session.

function requestAnimationFrameCallback(t, frame) {
  session.requestAnimationFrame(requestAnimationFrameCallback);

  const pose = frame.getViewerPose(referenceSpace);
  if (pose) {
    for (const view of pose.views) {
      const depthInformation = frame.getDepthInformation(view);
      if (depthInformation) {
        useCpuDepthInformation(view, depthInformation);
      }
    }
  }
}

XRCPUDepthInformation을 얻고 나면, 이는 view plane에서 사용자 환경까지의 거리를 알아내는 데 사용할 수 있습니다(자세한 내용은 § 4 결과 해석 섹션 참조). 아래 코드는 normalized view coordinates (0.25, 0.75)에서 depth를 얻는 방법을 보여줍니다:

function useCpuDepthInformation(view, depthInformation) {
  const depthInMeters = depthInformation.getDepthInMeters(0.25, 0.75);
  console.log("Depth at normalized view coordinates (0.25, 0.75) is:",
    depthInMeters);
}

3.3. XRWebGLDepthInformation

[Exposed=Window]
interface XRWebGLDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute WebGLTexture texture;

  readonly attribute XRTextureType textureType;
  readonly attribute unsigned long? imageIndex;
};

texture attribute는 opaque texture로서 depth buffer information을 포함합니다. 각 texel은 sensor의 near plane에서 users' environment까지의 거리에 대응하며, 단위는 지정되지 않습니다. 각 data entry의 크기와 type은 depthDataFormat에 의해 결정됩니다. 값은 rawValueToMeters를 곱하여 unspecified units에서 meters로 변환할 수 있습니다. normDepthBufferFromNormViewnormalized view coordinates에서 depth buffer의 coordinate system으로 transform하는 데 사용할 수 있습니다. 접근 시, XRDepthInformationdepth buffer에 접근하는 알고리즘을 실행해야 합니다.

textureType attribute는 texture가 TEXTURE_2D 또는 TEXTURE_2D_ARRAY type인지 설명합니다.

imageIndex attribute는 texture array 안의 offset을 반환합니다. 이는 textureTypeTEXTURE_2D_ARRAY와 같을 때 정의되어야 하며, TEXTURE_2D이면 undefined여야 합니다.

partial interface XRWebGLBinding {
  XRWebGLDepthInformation? getDepthInformation(XRView view);
};

getDepthInformation(view) method는 XRWebGLBinding에서 호출될 때, 애플리케이션이 frame에 관련된 WebGL depth information을 얻기를 원한다는 것을 나타냅니다.

getDepthInformation(view) method가 XRWebGLBinding binding에서 XRView view와 함께 호출되면, 사용자 에이전트는 다음 단계를 실행하여 WebGL depth information을 얻어야 합니다:

  1. sessionbindingsession으로 둡니다.

  2. frameviewframe으로 둡니다.

  3. sessionframesession과 일치하지 않으면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  4. depth-sensing feature descriptor가 sessionXR devicesession modelist of enabled featurescontained되어 있지 않으면, NotSupportedErrorthrow하고 이 단계를 중단합니다.

  5. sessiondepthUsage"gpu-optimized"가 아니면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  6. frameactive boolean이 false이면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  7. frameanimationFrame boolean이 false이면, InvalidStateError를 throw하고 이 단계를 중단합니다.

  8. depthInformationframeview가 주어졌을 때 WebGL depth information instance를 생성한 결과로 둡니다.

  9. depthInformation을 반환합니다.

XRFrame frameXRView view가 주어졌을 때 WebGL 깊이 정보 인스턴스를 생성하기 위해 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. resultXRWebGLDepthInformation의 새 인스턴스로 둔다.

  2. time을 다음과 같이 초기화한다.

    XRSessionmatchDepthViewtrue로 설정된 상태에서 생성된 경우:
    timeframe시간으로 둔다.
    그 밖의 경우
    timedevice가 깊이 정보를 캡처한 시간으로 둔다.
  3. sessionframesession으로 둔다.

  4. devicesessionXR 장치로 둔다.

  5. depthActivefalse이면 null을 반환하고 이 단계를 중단한다.

  6. nativeDepthInformation을 지정된 view에 대해 time 시점에 유효한 깊이 정보를 device네이티브 깊이 감지에 질의하여 얻은 네이티브 깊이 정보로 두며, 이때 sessiondepthType, depthUsage, 및 depthDataFormat을 고려한다.

  7. nativeDepthInformationnull이면 null을 반환하고 이 단계를 중단한다.

  8. nativeDepthBuffernativeDepthInformation네이티브 깊이 버퍼로 둔다.

  9. nativeDepthBuffer가 깊이 데이터에 대한 접근을 차단하기 위한 사용자 에이전트의 기준을 충족하면, null을 반환하고 이 단계를 중단한다.

  10. nativeDepthBuffer가 깊이 버퍼에서 사용할 수 있는 정보의 양을 제한하기 위한 사용자 에이전트의 기준을 충족하면, 그에 따라 nativeDepthBuffer를 조정한다.

  11. resultwidthnativeDepthBuffer의 너비로 초기화한다.

  12. resultheightnativeDepthBuffer의 높이로 초기화한다.

  13. resultnormDepthBufferFromNormViewnativeDepthInformation깊이 좌표 변환 행렬을 기반으로 하는 새로운 XRRigidTransform으로 초기화한다.

  14. resultrawValueToMetersnativeDepthInformation에서 제공한 배율로 초기화한다.

  15. resulttexturenativeDepthBuffer를 포함하는 불투명 텍스처로 초기화한다.

  16. resultviewview로 초기화한다.

  17. resulttransformview참조 공간에서 time 시점의 센서 포즈로 초기화한다.

  18. resulttextureType을 다음과 같이 초기화한다.

    resulttexturetexture-array의 textureType으로 생성된 경우:
    resulttextureType을 "texture-array"로 초기화한다.
    그 밖의 경우
    resulttextureType을 "texture"로 초기화한다.
  19. resultimageIndex를 다음과 같이 초기화한다.

    textureTypetexture인 경우
    resultimageIndexnull로 초기화한다.
    그렇지 않고 vieweye"right"인 경우
    resultimageIndex1로 초기화한다.
    그 밖의 경우
    resultimageIndex0으로 초기화한다.
  20. result를 반환한다.

다음 코드는 XRFrameRequestCallback 내에서 깊이 데이터를 얻는 방법을 보여준다. 이 예제에서는 깊이 감지가 활성화되고, 사용 방식은 "gpu-optimized"로, 데이터 형식은 "luminance-alpha"로 설정된 세션이라고 가정한다.
const session = ...;          // 깊이 감지가 활성화된 상태로 생성된 세션.
const referenceSpace = ...;   // 세션에서 생성된 참조 공간.
const glBinding = ...;        // 세션에서 생성된 XRWebGLBinding.

function requestAnimationFrameCallback(t, frame) {
  session.requestAnimationFrame(requestAnimationFrameCallback);

  const pose = frame.getViewerPose(referenceSpace);
  if (pose) {
    for (const view of pose.views) {
      const depthInformation = glBinding.getDepthInformation(view);
      if (depthInformation) {
        useWebGLDepthInformation(view, depthInformation);
      }
    }
  }
}

XRWebGLDepthInformation을 얻으면 이를 사용하여 뷰 평면에서 사용자의 환경까지의 거리를 알아낼 수 있다(자세한 내용은 § 4 결과 해석 절을 참조). 아래 코드는 데이터를 셰이더로 전송하는 방법을 보여준다.

const gl = ...;             // 사용할 GL 컨텍스트.
const shaderProgram = ...;  // 링크된 WebGLProgram.
const programInfo = {
  uniformLocations: {
    depthTexture: gl.getUniformLocation(shaderProgram, 'uDepthTexture'),
    uvTransform: gl.getUniformLocation(shaderProgram, 'uUvTransform'),
    rawValueToMeters: gl.getUniformLocation(shaderProgram, 'uRawValueToMeters'),
  }
};

function useWebGLDepthInformation(view, depthInformation) {
  // ...

  gl.bindTexture(gl.TEXTURE_2D, depthInformation.texture);
  gl.activeTexture(gl.TEXTURE0);
  gl.uniform1i(programInfo.uniformLocations.depthTexture, 0);

  gl.uniformMatrix4fv(
    programInfo.uniformLocations.uvTransform, false,
    depthInformation.normDepthBufferFromNormView.matrix);

  gl.uniform1f(
    programInfo.uniformLocations.rawValueToMeters,
    depthInformation.rawValueToMeters);

  // ...
}

깊이 버퍼를 사용하는 프래그먼트 셰이더의 예는 다음과 같다.

precision mediump float;

uniform sampler2D uDepthTexture;
uniform mat4 uUvTransform;
uniform float uRawValueToMeters;

varying vec2 vTexCoord;

float DepthGetMeters(in sampler2D depth_texture, in vec2 depth_uv) {
  // 깊이는 텍스처의 luminance 및 alpha 컴포넌트에 패킹된다.
  // 텍스처는 밀리미터를 저장하는 정규화 형식이다.
  vec2 packedDepth = texture2D(depth_texture, depth_uv).ra;
  return dot(packedDepth, vec2(255.0, 256.0 * 255.0)) * uRawValueToMeters;
}

void main(void) {
  vec2 texCoord = (uUvTransform * vec4(vTexCoord.xy, 0, 1)).xy;

  float depthInMeters = DepthGetMeters(uDepthTexture, texCoord);

  gl_FragColor = ...;
}

3.4. XRGPUDepthInformation

WebGPU 호환 세션의 경우, GPU 최적화 깊이 정보는 XRGPUBinding을 통해 XRGPUDepthInformation으로 노출되어야 하며, XRWebGLBinding을 통해 XRWebGLDepthInformation으로 노출되어서는 안 된다.

XRGPUDepthInformation에는 연관된 음이 아닌 정수 배열 레이어 인덱스가 있으며, 이는 연관된 의 깊이 정보를 포함하는 해당 texture의 배열 레이어를 식별한다.

[Exposed=Window]
interface XRGPUDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute GPUTexture texture;

  GPUTextureViewDescriptor getViewDescriptor();
};

texture 속성은 XRGPUBinding장치로 생성된 GPUTexture로 깊이 버퍼 정보를 포함한다. 각 텍셀은 센서의 근거리 평면에서 사용자의 환경까지의 거리에 지정되지 않은 단위로 대응한다. 값에 rawValueToMeters를 곱하여 지정되지 않은 단위에서 미터로 변환할 수 있다. normDepthBufferFromNormView정규화된 뷰 좌표에서 깊이 버퍼의 좌표계로 변환하는 데 사용할 수 있다. 이 속성에 접근할 때는 XRDepthInformation깊이 버퍼에 접근을 시도하는 알고리즘을 반드시 실행해야 한다.

반환된 텍스처에는 다음 속성이 있다.

texture에서 destroy()를 호출하면 해당 GPUTexture를 통한 접근을 반드시 종료해야 하지만, 이를 지원하는 네이티브 깊이 버퍼를 파괴하거나 변경해서는 안 된다.

getViewDescriptor() 메서드는 이 객체의 깊이 정보를 포함하는 texture 부분의 2차원 뷰를 생성하도록 구성된 GPUTextureViewDescriptor를 반환한다.

XRGPUDepthInformation depthInformation에서 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다.

  1. depthInformation을 사용하여 깊이 버퍼에 접근을 시도하는 알고리즘을 실행한다.

  2. descriptor를 새로운 GPUTextureViewDescriptor로 둔다.

  3. descriptordimension"2d"로 설정한다.

  4. descriptorbaseMipLevel을 `0`으로 설정한다.

  5. descriptormipLevelCount를 `1`로 설정한다.

  6. descriptorbaseArrayLayerdepthInformation배열 레이어 인덱스로 설정한다.

  7. descriptorarrayLayerCount를 `1`로 설정한다.

  8. descriptor를 반환한다.

XRFrame에는 연관된 WebGPU 깊이 텍스처 목록이 있으며, 처음에는 빈 목록이다.

XR 애니메이션 프레임 알고리즘은 다음과 같이 확장된다. XRFrameactive 불리언 값을 false로 설정하기 직전에 사용자 에이전트는 다음 단계를 반드시 실행해야 한다.

  1. XRFrameWebGPU 깊이 텍스처 목록의 각 texture에 대해:

    1. texture를 지원하는 네이티브 깊이 버퍼가 수정되거나 재사용되기 전에, texture에 접근하면서 이 XRFrame을 처리하는 동안 제출된 모든 WebGPU 작업이 완료되었는지 확인하거나, 동등한 GPU 측 종속성을 사용하여 해당 작업을 네이티브 깊이 감지 구현과 동기화한다.

    2. 기반 네이티브 깊이 버퍼를 파괴하지 않고 texture에서 destroy()를 호출한다.

  2. XRFrameWebGPU 깊이 텍스처 목록을 빈 목록으로 설정한다.

참고: 작성자는 XRGPUDepthInformation을 얻은 XRFrameRequestCallback 중에 texture를 사용하는 모든 작업을 인코딩하고 제출해야 한다. XRGPUDepthInformation이나 그 텍스처를 유지해도 텍스처의 수명이 연장되지는 않는다.

partial interface XRGPUBinding {
  XRGPUDepthInformation? getDepthInformation(XRView view);
};

getDepthInformation(view) 메서드는 XRGPUBinding에서 호출될 때 애플리케이션이 프레임에 관련된 WebGPU 깊이 정보를 얻기 원한다는 것을 나타낸다.

getDepthInformation(view)XRGPUBinding binding에서 XRView view와 함께 호출되면, 사용자 에이전트는 다음 단계를 실행하여 WebGPU 깊이 정보를 얻어야 한다.

  1. sessionbinding세션으로 둔다.

  2. devicebinding장치로 둔다.

  3. frameview프레임으로 둔다.

  4. sessionframesession과 일치하지 않으면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  5. depth-sensing 기능 설명자가 sessionXR 장치session 모드에 대한 활성화된 기능 목록포함되어 있지 않으면, NotSupportedError발생시키고 이 단계를 중단한다.

  6. sessiondepthUsage"gpu-optimized"가 아니면, InvalidStateError를 발생시키고 이 단계를 중단한다.

  7. device파괴된 경우, InvalidStateError를 발생시키고 이 단계를 중단한다.

  8. frameactive 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  9. frameanimationFrame 불리언 값이 false이면 InvalidStateError를 발생시키고 이 단계를 중단한다.

  10. depthInformationbinding, frameview가 주어졌을 때 WebGPU 깊이 정보 인스턴스를 생성한 결과로 둔다.

  11. depthInformation을 반환한다.

XRGPUBinding binding, XRFrame frameXRView view가 주어졌을 때 WebGPU 깊이 정보 인스턴스를 생성하기 위해 사용자 에이전트는 다음 단계를 반드시 실행해야 한다.

  1. result를 새로운 XRGPUDepthInformation 인스턴스로 둔다.

  2. sessionframesession으로 둔다.

  3. xrDevicesessionXR 장치로 둔다.

  4. gpuDevicebinding장치로 둔다.

  5. time을 다음과 같이 초기화한다.

    sessionmatchDepthViewtrue로 설정된 상태에서 생성된 경우:
    timeframe시간으로 둔다.
    그 밖의 경우:
    timexrDevice가 깊이 정보를 캡처한 시간으로 둔다.
  6. depthActivefalse이면 null을 반환하고 이 단계를 중단한다.

  7. nativeDepthInformation을 지정된 view에 대해 time 시점에 유효한 깊이 정보를 xrDevice네이티브 깊이 감지에 질의하여 얻은 네이티브 깊이 정보로 두며, 이때 sessiondepthType, depthUsage, 및 depthDataFormat을 고려한다.

  8. nativeDepthInformationnull이면 null을 반환하고 이 단계를 중단한다.

  9. nativeDepthBuffernativeDepthInformation네이티브 깊이 버퍼로 둔다.

  10. nativeDepthBuffer가 깊이 데이터에 대한 접근을 차단하기 위한 사용자 에이전트의 기준을 충족하면, null을 반환하고 이 단계를 중단한다.

  11. nativeDepthBuffer가 깊이 버퍼에서 사용할 수 있는 정보의 양을 제한하기 위한 사용자 에이전트의 기준을 충족하면, 그에 따라 nativeDepthBuffer를 조정한다.

  12. resultwidthnativeDepthBuffer의 너비로 초기화한다.

  13. resultheightnativeDepthBuffer의 높이로 초기화한다.

  14. resultnormDepthBufferFromNormViewnativeDepthInformation깊이 좌표 변환 행렬을 기반으로 하는 새로운 XRRigidTransform으로 초기화한다.

  15. resultrawValueToMetersnativeDepthInformation에서 제공한 배율로 초기화한다.

  16. format§ 2.2 의도된 깊이 유형, 데이터 사용 및 데이터 형식 표에서 sessiondepthDataFormat에 대응하는 GPUTextureFormat으로 둔다.

  17. arrayLayerCountnativeDepthBuffer의 배열 레이어 수로 두며, nativeDepthBuffer가 레이어형이 아니면 `1`로 둔다.

  18. arrayLayerCount가 `1`이면 arrayLayerIndex를 `0`으로 두고, 그렇지 않으면 viewindex로 둔다.

  19. arrayLayerIndexarrayLayerCount보다 작은지 단언한다.

  20. descriptor를 다음 멤버를 가진 새로운 GPUTextureDescriptor로 둔다.

  21. resulttexturedescriptor를 사용해 gpuDevice.createTexture()를 호출한 결과로 초기화하되, GPUTexture의 기반 저장소가 nativeDepthBuffer를 가리키도록 한다.

  22. result배열 레이어 인덱스arrayLayerIndex로 초기화한다.

  23. resulttextureframeWebGPU 깊이 텍스처 목록추가한다.

  24. resultview로 초기화한다.

  25. resulttransformview참조 공간에서 time 시점의 센서 포즈로 초기화한다.

  26. result를 반환한다.

다음 코드는 "gpu-optimized" 사용 및 "unsigned-short" 데이터 형식으로 구성된 WebGPU 호환 세션에서 깊이 데이터를 얻는 방법을 보여준다.
const adapter = await navigator.gpu.requestAdapter({ xrCompatible: true });
const device = await adapter.requestDevice();
const session = await navigator.xr.requestSession("immersive-ar", {
  requiredFeatures: ["depth-sensing", "webgpu"],
  depthSensing: {
    usagePreference: ["gpu-optimized"],
    dataFormatPreference: ["unsigned-short"],
  },
});
const referenceSpace = await session.requestReferenceSpace("local");
const gpuBinding = new XRGPUBinding(session, device);
const projectionLayer = gpuBinding.createProjectionLayer({
  colorFormat: gpuBinding.getPreferredColorFormat(),
});
session.updateRenderState({ layers: [projectionLayer] });

function requestAnimationFrameCallback(time, frame) {
  session.requestAnimationFrame(requestAnimationFrameCallback);

  const pose = frame.getViewerPose(referenceSpace);
  if (!pose) return;

  for (const view of pose.views) {
    const depthInformation = gpuBinding.getDepthInformation(view);
    if (!depthInformation) continue;

    const depthTextureView = depthInformation.texture.createView(
      depthInformation.getViewDescriptor());

    // 이 콜백 중에 제출되는 WebGPU 작업에서 depthTextureView를 사용한다.
  }
}

session.requestAnimationFrame(requestAnimationFrameCallback);

4. 결과 해석

주어진 픽셀에 유효하지 않은 깊이 데이터가 있는 것으로 판단되거나 그 밖의 이유로 깊이 데이터를 확인할 수 없는 경우, 사용자 에이전트는 반드시 깊이 값 0을 반환해야 한다.

data, texture, 및 texture에 저장된 값은 카메라 평면에서 실제 세계의 기하 구조(XR 시스템이 이해한 바에 따른)까지의 거리를 나타낸다. 아래 예제에서 점 a = (x, y)의 깊이 값은 점 A에서 카메라 평면까지의 거리에 대응한다. 구체적으로, 깊이 값은 aA 벡터의 길이를 나타내지 않는다.

Depth API 데이터 설명

위 이미지는 다음 코드에 대응한다.

// depthInfo는 XRCPUDepthInformation 유형이다:
const depthInMeters = depthInfo.getDepthInMeters(x, y);

5. Native device 개념

5.1. Native depth sensing

깊이 감지 명세에서는 깊이 감지 API가 구현되는 기반 네이티브 장치가 장치의 네이티브 깊이 감지 기능을 질의할 수 있는 방법을 제공한다고 가정한다. 장치가 네이티브 깊이 정보를 얻는 방법을 노출하는 경우, 해당 장치는 장치의 네이티브 깊이 감지 기능 질의를 지원한다고 한다. 네이티브 깊이 정보의 깊이 좌표 변환 행렬정규화된 뷰 좌표에서 정규화된 깊이 버퍼 좌표로 좌표계를 변환하며, 변환된 3D 벡터의 z 좌표에는 영향을 주지 않아야 한다.

장치는 두 가지 방식으로 깊이 감지 유형을 지원할 수 있다. 장치가 최소한의 후처리만 거쳐 추정된 깊이 값을 단순히 반환하는 경우, "raw" 깊이 유형을 지원한다고 한다. 장치 또는 런타임이 이 데이터의 노이즈를 "평활화"하기 위해 추가 처리를 적용할 수 있는 경우(예: 동일한 깊이 값을 갖는 더 큰 영역으로 처리), "smooth" 깊이 유형을 지원한다고 한다.

참고: "Raw" 깊이 데이터에는 종종 신뢰도 값이 함께 제공된다. UA는 그러한 데이터를 페이지에 반환할 때 신뢰도 값이 낮은 깊이 데이터를 유효하지 않은 깊이 데이터로 처리하도록 선택할 수 있다.

장치는 두 가지 방식으로 깊이 감지 사용 방식을 지원할 수 있다. 장치가 주로 CPU에서 접근 가능한 메모리를 통해 깊이 데이터를 반환할 수 있는 경우, "cpu-optimized" 사용 방식을 지원한다고 한다. 장치가 주로 GPU에서 접근 가능한 메모리를 통해 깊이 데이터를 반환할 수 있는 경우, "gpu-optimized" 사용 방식을 지원한다고 한다.

참고: 사용자 에이전트는 두 사용 모드를 모두 지원하도록 선택할 수 있다(예: 장치가 CPU 및 GPU에서 접근 가능한 데이터를 모두 제공할 수 있거나, CPU 및 GPU에서 접근 가능한 데이터 간 전송을 수동으로 수행하는 경우).

장치는 주어진 깊이 감지 사용 방식과 유형에 대해 다음 방식으로 깊이 감지 데이터 형식을 지원할 수 있다. 주어진 깊이 감지 사용 방식과 유형에서 장치가 16비트 부호 없는 정수를 포함하는 버퍼로 깊이 데이터를 반환할 수 있는 경우, "luminance-alpha""unsigned-short" 데이터 형식을 지원한다고 한다. 주어진 깊이 감지 사용 방식과 유형에서 장치가 32비트 부동 소수점 값을 포함하는 버퍼로 깊이 데이터를 반환할 수 있는 경우, "float32" 데이터 형식을 지원한다고 한다.

깊이 감지 구성은 하나의 XRDepthType, 하나의 XRDepthUsage, 및 하나의 XRDepthDataFormat의 조합으로 나타낸다.

장치는 지정된 구성에 대해 깊이 감지 유형을 지원하고, 깊이 감지 사용 방식을 지원하며, 깊이 감지 데이터 형식을 지원하는 경우 깊이 감지 구성을 지원한다고 한다.

참고: 깊이 감지 API 지원은 AR을 지원할 수 있는 것으로 분류된 하드웨어에만 국한되지 않지만, 이러한 장치에서 이 기능이 더 일반적일 것으로 예상된다. 적절한 센서를 포함하거나 다른 기술을 사용하여 깊이 버퍼를 제공하는 VR 장치도 깊이 감지 API를 구현하는 데 필요한 데이터를 제공할 수 있어야 한다.

depthTypeRequest, usagePreference, 및 dataFormatPreference 각각에 대해, 장치는 해당 배열이 비어 있는 경우 반드시 사용해야 하는 선호 네이티브 깊이 감지 기능을 반드시 가져야 한다. 유형, 사용 방식 및 형식은 서로 의존할 수 있지만, 장치에서 가장 효율적인 것을 반영하는 것이 좋다.

장치는 깊이 감지 기능이 현재 활성 상태로 실행 중인지를 나타내는 불리언인 깊이 감지 활성 상태를 가진다고 할 수 있다. 이 상태는 반드시 true로 시작해야 한다. 이 상태가 false일 때 사용자 에이전트는 이 기능이 활성화되어 있음으로 인한 성능 영향을 완화하기 위한 조치를 취하는 것이 좋다.

6. 개인정보 보호 및 보안 고려사항

Depth sensing API는 depth buffer format으로 사용자의 환경에 대한 추가 정보를 웹사이트에 제공합니다. 충분히 높은 resolution과 충분히 높은 precision을 가진 depth buffer가 주어지면, 웹사이트는 사용자가 편안하게 느끼는 것보다 더 자세한 정보를 잠재적으로 학습할 수 있습니다. 사용되는 underlying technology에 따라, depth data는 camera image 및 IMU sensors에 기반하여 생성될 수 있습니다.

사용자에 대한 privacy risk를 완화하기 위해, 사용자 에이전트는 session에서 depth sensing API를 활성화하기 전에 user consent를 구해야 합니다. 또한 depth sensing technologies 및 hardware가 개선됨에 따라, 사용자 에이전트는 API를 통해 노출되는 information 양을 제한하거나, 그러한 제한을 도입하는 것이 불가능한 경우 API에서 반환되는 data에 대한 access를 block하는 것을 고려해야 합니다. Information 양을 제한하기 위해, 사용자 에이전트는 예를 들어 resulting depth buffer의 resolution을 줄이거나, depth buffer에 있는 값의 precision을 줄일 수 있습니다(예: quantization을 통해). 이러한 방식으로 data 양을 제한하기로 결정한 사용자 에이전트는 여전히 이 명세를 구현하는 것으로 간주됩니다.

사용자 에이전트가 장치의 cameras가 제공하는 정보와 동등해질 만큼 충분히 자세한 depth buffer를 제공할 수 있는 경우, 먼저 camera access를 얻는 데 필요한 동등한 user consent를 얻어야 합니다.

변경 사항

2021년 8월 31일 최초 공개 작업 초안 이후 변경 사항

7. 감사의 글

다음 개인들은 WebXR Depth Sensing 명세의 설계에 기여했습니다:

적합성

문서 규약

적합성 요구사항은 설명적 주장과 RFC 2119 용어의 조합으로 표현됩니다. 이 문서의 규범적 부분에서 핵심 단어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”은 RFC 2119에 설명된 대로 해석해야 합니다. 하지만 가독성을 위해, 이 명세에서 이러한 단어들이 모두 대문자로 나타나지는 않습니다.

이 명세의 모든 텍스트는 명시적으로 비규범으로 표시된 섹션, 예제 및 노트를 제외하고 규범적입니다. [RFC2119]

이 명세의 예제는 “for example”이라는 단어로 소개되거나 class="example"을 사용하여 규범 텍스트와 구분됩니다. 예를 들면 다음과 같습니다:

이는 정보 제공용 예제의 예입니다.

정보 제공용 노트는 “Note”라는 단어로 시작하며 class="note"를 사용하여 규범 텍스트와 구분됩니다. 예를 들면 다음과 같습니다:

Note, 이는 정보 제공용 노트입니다.

적합한 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구사항 (예: "strip any leading space characters" 또는 "return false and abort these steps")은 알고리즘을 소개할 때 사용된 핵심 단어 ("must", "should", "may" 등)의 의미로 해석해야 합니다.

알고리즘 또는 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동등하다면 어떤 방식으로든 구현될 수 있습니다. 특히 이 명세에서 정의된 알고리즘은 이해하기 쉽게 작성된 것이며 성능을 목적으로 한 것은 아닙니다. 구현자는 최적화하는 것이 권장됩니다.

색인

이 명세에서 정의하는 용어

참조로 정의되는 용어

참고 문헌

규범적 참고 문헌

[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. 요구사항 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. 1997년 3월. 현행 최선의 관행. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBGL-2]
Kelsey Gilbert. WebGL 2.0 명세. URL: https://www.khronos.org/registry/webgl/specs/latest/2.0/
[WEBGPU]
Kai Ninomiya; Brandon Jones; Jim Blandy. WebGPU. 2026년 8월 12일. CRD. URL: https://www.w3.org/TR/webgpu/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 장치 API. 2026년 6월 9일. CRD. URL: https://www.w3.org/TR/webxr/
[WEBXRLAYERS-1]
Rik Cabanier. WebXR 레이어 API 레벨 1. 2026년 8월 11일. WD. URL: https://www.w3.org/TR/webxrlayers-1/

정보성 참고 문헌

[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Augmented Reality Module - Level 1. 2025년 4월 25일. CRD. URL: https://www.w3.org/TR/webxr-ar-module-1/

IDL 색인

enum XRDepthType {
  "raw",
  "smooth",
};

enum XRDepthUsage {
  "cpu-optimized",
  "gpu-optimized",
};

enum XRDepthDataFormat {
  "luminance-alpha",
  "float32",
  "unsigned-short",
};

dictionary XRDepthStateInit {
  required sequence<XRDepthUsage> usagePreference;
  required sequence<XRDepthDataFormat> dataFormatPreference;
  sequence<XRDepthType> depthTypeRequest;
  boolean matchDepthView = true;
};

partial dictionary XRSessionInit {
  XRDepthStateInit depthSensing;
};

partial interface XRSession {
  readonly attribute XRDepthUsage depthUsage;
  readonly attribute XRDepthDataFormat depthDataFormat;
  readonly attribute XRDepthType? depthType;
  readonly attribute boolean? depthActive;

  undefined pauseDepthSensing();
  undefined resumeDepthSensing();
};

[SecureContext, Exposed=Window]
interface XRDepthInformation {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;

  [SameObject] readonly attribute XRRigidTransform normDepthBufferFromNormView;
  readonly attribute float rawValueToMeters;
};

XRDepthInformation includes XRViewGeometry;

[Exposed=Window]
interface XRCPUDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute ArrayBuffer data;

  float getDepthInMeters(float x, float y);
};

partial interface XRFrame {
  XRCPUDepthInformation? getDepthInformation(XRView view);
};

[Exposed=Window]
interface XRWebGLDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute WebGLTexture texture;

  readonly attribute XRTextureType textureType;
  readonly attribute unsigned long? imageIndex;
};

partial interface XRWebGLBinding {
  XRWebGLDepthInformation? getDepthInformation(XRView view);
};

[Exposed=Window]
interface XRGPUDepthInformation : XRDepthInformation {
  [SameObject] readonly attribute GPUTexture texture;

  GPUTextureViewDescriptor getViewDescriptor();
};

partial interface XRGPUBinding {
  XRGPUDepthInformation? getDepthInformation(XRView view);
};

MDN

XRCPUDepthInformation/data

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRCPUDepthInformation/getDepthInMeters

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRCPUDepthInformation

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRDepthInformation/height

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRDepthInformation/normDepthBufferFromNormView

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRDepthInformation/rawValueToMeters

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRDepthInformation/width

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRDepthInformation

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/getDepthInformation

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/depthDataFormat

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/depthUsage

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRWebGLBinding/getDepthInformation

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRWebGLDepthInformation/texture

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRWebGLDepthInformation

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?