TL;DR

  • OpenXR은 XR 하드웨어별 SDK 파편화를 줄이기 위해 Khronos가 만든 벤더 중립 표준이다.
  • 앱은 OpenXR API 하나에 맞추고, 실제 기기 차이는 Loader·Runtime·Extension 계층이 흡수한다.
  • Unity, Unreal, Godot, WebXR 연계까지 포함해 XR 플랫폼 이식성과 유지보수성을 크게 높여준다.

1. 개념

OpenXR은 VR·AR·MR을 포괄하는 XR 애플리케이션이 특정 벤더 SDK에 종속되지 않도록, Khronos가 정의한 크로스플랫폼 런타임 표준 API다. 애플리케이션은 단일 OpenXR 인터페이스를 기준으로 세션, 입력, 공간, 프레임 제출을 처리하고, 실제 디바이스별 차이는 런타임과 확장 계층이 담당한다.

2. 배경

초기 XR 생태계는 Oculus SDK, OpenVR, WMR, 모바일 전용 SDK처럼 플랫폼별 API가 갈라져 있었다. 이 구조에서는 같은 앱을 여러 기기에 내보내려면 입력, 렌더링, 세션 관리 코드를 중복 구현해야 했고, 벤더 락인과 유지보수 비용이 빠르게 커졌다. OpenXR은 이 파편화를 줄이고 공통 기반을 만들기 위해 등장했다.

3. 이유

OpenXR을 이해해야 XR 프로젝트에서 런타임 호환성, 입력 추상화, 공간 좌표계, 프레임 타이밍, 엔진 통합 문제를 정확히 다룰 수 있다. 특히 Meta, SteamVR, Pico, HoloLens, Android XR 같은 서로 다른 런타임을 하나의 코드 경로로 묶을 때 OpenXR이 사실상 기준점이 된다.

4. 특징

  • Loader, API Layer, Runtime으로 분리된 벤더 중립 아키텍처
  • XrInstance, XrSession, XrSpace, XrAction, XrSwapchain 중심 객체 모델
  • predictedDisplayTime 기반 프레임 루프와 표준 세션 상태 머신
  • Action System과 Interaction Profile을 통한 입력 추상화
  • Unity OpenXR Plugin, Unreal OpenXR, Godot OpenXR, WebXR 연계까지 이어지는 폭넓은 생태계

5. 상세 내용

OpenXR 크로스플랫폼 XR 표준 완전가이드

작성일: 2026-04-29 카테고리: XR / Graphics / Khronos / Game Dev 포함 내용: Khronos Group, OpenXR Loader, API Layers, Runtime, XrInstance, XrSession, XrSpace, XrAction, XrSwapchain, Reference Spaces (VIEW/LOCAL/STAGE/LOCAL_FLOOR/UNBOUNDED), Composition Layers, xrWaitFrame, xrBeginFrame, xrEndFrame, xrPollEvent, Session State Machine, Predicted Display Time, Late Latching, Foveated Rendering, Application SpaceWarp, Multiview, Action System, Interaction Profile, Suggested Bindings, Graphics Binding (Vulkan/D3D11/D3D12/OpenGL/OpenGL ES), Project Treble 비교, Monado, Meta Quest Horizon OS, SteamVR, WMR/HoloLens 2, Pico, Varjo, HTC Vive, Magic Leap 2, Lynx, Snap Spectacles, Apple visionOS 부재, OpenVR/Oculus SDK 마이그레이션, Unity OpenXR Plugin, XR Interaction Toolkit, Meta XR SDK, Unreal Meta XR Plugin, Godot 4 OpenXR, BabylonJS/Three.js WebXR, StereoKit, Bevy XR, Android XR (Google), CTS, OpenXR 1.1, Privacy Sandbox, Snapdragon Spaces


1. OpenXR이란?

핵심 개념

┌─────────────────────────────────────────────────────────────────┐
│                  OpenXR 한 줄 정의                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "Khronos가 관리하는 royalty-free 개방 표준 — VR/AR/MR(통칭 XR)  │
│   하드웨어와 소프트웨어를 분리하는 크로스플랫폼 C API"            │
│                                                                  │
│  ┌──────────────────────────────────────────────────────┐       │
│  │  App                                                  │       │
│  │   │  단일 OpenXR API                                  │       │
│  │   ▼                                                   │       │
│  │  Loader (Khronos 제공, 앱에 번들)                     │       │
│  │   ├── API Layers (validation/dump/...)                │       │
│  │   └── Runtime (Meta/SteamVR/Monado/MSFT/Pico/...)    │       │
│  │                                                        │       │
│  │  Write once, run on any conformant runtime            │       │
│  └──────────────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────────────┘

XR / VR / AR / MR 관계

약어 풀 이름 의미
VR Virtual Reality 물리 세계 차단, 디지털 세계 몰입
AR Augmented Reality 물리 세계 위에 디지털 오버레이
MR Mixed Reality 물리/디지털 실시간 상호작용, 공간 앵커
XR eXtended Reality VR/AR/MR 전체를 포괄하는 우산 용어

왜 “OpenXR”이지 “OpenVR”이 아닌가?

  1. OpenVR은 이미 Valve의 등록상표: 2016년부터 SteamVR용으로 Valve가 사용 중
  2. 범위 차이: OpenXR은 VR뿐 아니라 AR, MR, 미래의 어떤 형태도 포괄
  3. 컨소시엄 중립성: 다양한 회원사(Oculus VR, Microsoft MR, Magic Leap AR)의 이해를 모두 아우름

Khronos Group의 어원

Χρόνος (Chrónos) — 그리스 신화의 “측정 가능한 선형 시간”의 신. 그리스인들은 시간을 χρόνος(연대기적 시간)와 καιρός(결정적 순간)로 구분했다. Khronos Group은 전자를 택했는데, 이는 “실시간(real-time) 컴퓨팅과 그래픽 처리”를 다루는 조직 성격에 정확히 부합한다 — 시간이 곧 프레임, 렌더링, 지연(latency)의 언어이기 때문이다.

2000년 설립. 비영리 개방 컨소시엄. 주요 표준: OpenGL(이관 1992), OpenGL ES(2003), WebGL(2011), OpenCL(2009), Vulkan(2016), SPIR-V(2015), glTF(2015), OpenXR(2019).


2. 등장 배경 (Pre-OpenXR Fragmentation)

2.1 2013~2017 파편화 시대

┌─────────────────────────────────────────────────────────────────┐
│              "왜 또 다른 표준이 필요했는가"                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  앱이 동시 지원해야 했던 SDK들:                                   │
│                                                                  │
│  Oculus PC SDK (LibOVR)        — Rift, Rift S용                  │
│  Oculus Mobile SDK (VrApi)     — Gear VR, Quest용                │
│  OVRPlugin (Unity)             — 위 둘을 Unity에서 통합          │
│  OpenVR / SteamVR (Valve)      — Vive, Index, WMR (SteamVR 종속)│
│  Windows Mixed Reality API     — HoloLens, WMR HMD              │
│  Google VR SDK (Daydream)      — Android Daydream (2019 종료)    │
│  Vive Wave SDK (HTC)           — Vive Focus 시리즈               │
│  PSVR SDK (Sony)               — PSVR 콘솔 전용                  │
│  OSVR (Razer)                  — 2015 시도, 실패                 │
│                                                                  │
│  → 개발사는 N배 구현 비용                                        │
│  → 하드웨어 벤더가 자사 런타임에 개발자 가두기 경쟁              │
│  → 콘텐츠 부족 → 사용자 부족 → 개발자 외면 악순환                │
└─────────────────────────────────────────────────────────────────┘

2.2 OpenVR의 한계

Valve의 OpenVR은 다수 HMD를 지원했지만 SteamVR 런타임이 항상 중간에 존재해야 했다. “Open”이라는 이름과 달리 Valve가 런타임 계층을 통제했다.

2.3 OSVR 실패의 교훈

Razer + Sensics가 2015년 시작한 OSVR(Open Source Virtual Reality)은 “VR의 Android”를 표방했지만 콘텐츠 부재, 하드웨어 정밀도 부족, 소프트웨어 미성숙으로 실패. Razer는 OSVR을 포기하고 Khronos OpenXR 창립 회원으로 합류했다 — 중립적 대형 컨소시엄 없이 오픈 표준 성공이 어렵다는 교훈.


3. 역사적 기원 (Historical Origins)

연도 사건
2016 초 Khronos 회원 면대면 회의에서 XR API 파편화 해결 탐색 그룹 형성
2016.03~04 Oculus Rift CV1 / HTC Vive 출시 — 두 PC VR 플랫폼이 완전히 다른 SDK
2017.02.27 (GDC 2017) Khronos가 OpenXR Working Group 공식 설립 발표. AMD, Intel, ARM, NVIDIA, Epic Games, Unity, Oculus/Facebook, Microsoft, Sony, Qualcomm, HTC 등
2019.03.18 OpenXR 0.90 Provisional Specification 공개
2019.07.29 (SIGGRAPH 2019) OpenXR 1.0 공식 비준 + 공개 릴리스. Monado(Linux), WMR, Oculus Rift 즉시 구현체 제공
2020.06 Valve, SteamVR OpenXR Developer Preview 공개. CTS 95% 통과
2020.11 Microsoft, OpenXR 1.0 Conformant 인증 (HoloLens 2 + WMR)
2021.02 Valve SteamVR, OpenXR 1.0 Conformant 등재
2021.07.23 Meta “All In on OpenXR” 공식 선언. Oculus 독자 API 단계적 종료 발표
2022.08.31 Oculus Mobile SDK(VrApi) + Oculus PC API 완전 지원 종료(Unsupported)
2022 PICO (ByteDance), OpenXR 1.0 Conformant Runtime 제공
2024.04.15 OpenXR 1.1 릴리스 — Local Floor, Palm Pose, Quad Views 등 5개 Extension을 Core로 승격. 연간 정기 릴리스 사이클 선언
2024.02 Apple Vision Pro 출시 — OpenXR 미지원. RealityKit + CompositorServices 독자 스택
2024.07 Varjo XR-4 시리즈 OpenXR 1.0 Conformant
2024.12.12 Google이 Android XR 발표 — OpenXR 1.1 기반. Samsung Galaxy XR (Project Moohan) 첫 출시 기기
2024.11 Pico 4 Ultra OpenXR 1.1 Conformant
2025~ OpenXR이 사실상 업계 표준화. Apple만 미참여

SIGGRAPH 2019 발언:

  • Brent Insko (Intel, OpenXR WG 의장): “Now is the time for software developers to start putting OpenXR to work.”
  • Don Box (Microsoft Technical Fellow): “The mobile era was defined by closed ecosystems. With mixed reality, the next wave must be open.

4. 용어 사전 (Terminology Dictionary)

용어 풀 이름 의미
OpenXR “Open eXtended Reality”. XR 우산 표준.
Khronos Group 그리스어 Chrónos(시간)에서 유래. 2000년 설립 비영리 개방 컨소시엄
CTS Conformance Test Suite 런타임이 사양을 올바르게 구현했는지 검증하는 자동/수동 테스트
Loader OpenXR Loader 앱과 함께 배포되는 벤더 중립 라이브러리. Active Runtime 탐색·로드
Runtime OpenXR Runtime 벤더(Meta/Valve/MSFT 등) 제공 구현. 트래킹, 컴포지터, 렌즈 왜곡 보정 등
API Layer 앱과 런타임 사이 선택적 미들웨어. validation, debug, profiling
XrInstance 런타임 최상위 핸들. xrCreateInstance로 생성
XrSession 그래픽스 바인딩된 렌더링 세션. 상태 머신 동반
XrSpace 3D 좌표계. Reference Space 또는 Action Space
XrAction / XrActionSet 의미적 입력 단위. 하드웨어 추상화
XrSwapchain 런타임 관리 텍스처 배열
Reference Space VIEW / LOCAL / STAGE / LOCAL_FLOOR / UNBOUNDED 좌표계 종류
Composition Layer Projection / Quad / Cylinder / Equirect / Cube xrEndFrame에 제출하는 렌더링 단위
Interaction Profile 컨트롤러 표준 경로 (/interaction_profiles/oculus/touch_controller 등)
Suggested Binding 앱이 제안하는 Action↔하드웨어 매핑. 런타임이 사용자 리바인딩 가능
Graphics Binding xrCreateSession 시 GPU 디바이스 선언. Vulkan/D3D11/D3D12/GL/GLES
predictedDisplayTime xrWaitFrame이 반환하는 미래 프레임 표시 시각. 헤드 포즈 예측에 사용
Late Latching GPU 큐 직전에 최신 포즈로 재투영 (motion-to-photon ↓)
ATW / ASW Asynchronous Time Warp / SpaceWarp 컴포지터가 누락 프레임을 보간
Foveated Rendering FFR / ETFR 시야 중심부만 고해상도 렌더링
Multiview 두 눈 동시 렌더링 (single pass stereo)
Monado Collabora 주도 오픈소스 OpenXR 런타임. Android XR/Pico/CloudXR/Snapdragon Spaces 기반
WebXR W3C JavaScript API. 브라우저가 내부적으로 OpenXR을 호출 (Chromium)

5. 3계층 아키텍처

5.1 전체 구조

┌──────────────────────────────────────────────────┐
│            Application (앱 / 게임 엔진)            │
└──────────┬───────────────────────────────────────┘
           │ OpenXR C API
           ▼
┌──────────────────────────────────────────────────┐
│       OpenXR Loader (Khronos)                    │
│  - 앱과 함께 배포 (또는 시스템 설치)                │
│  - Trampoline functions: 앱 → 첫 레이어 라우팅      │
│  - Per-instance dispatch table                   │
└──────────┬───────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────┐
│       API Layer Chain (선택적, 0개 이상)          │
│  XR_APILAYER_LUNARG_core_validation              │
│  XR_APILAYER_LUNARG_api_dump                     │
│  XR_APILAYER_LUNARG_best_practices               │
└──────────┬───────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────┐
│       Runtime Terminator (마지막 레이어)           │
└──────────┬───────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────┐
│   XR Runtime (벤더별)                             │
│   Meta Quest / SteamVR / Monado / WMR /          │
│   Pico / Varjo / Magic Leap / Android XR / ...   │
└──────────┬───────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────┐
│        Hardware Driver / OS / HMD                │
└──────────────────────────────────────────────────┘

5.2 Active Runtime 선택 메커니즘

Windows

HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1
  ActiveRuntime = "C:\...\oculus_openxr_64.json"
HKLM\...\AvailableRuntimes
  oculus_openxr.json = 0
  steamxr.json       = 0

Linux (XDG)

$XDG_CONFIG_HOME/openxr/1/active_runtime.json
/etc/xdg/openxr/1/active_runtime.json    ← 배포판 기본

Android

<!-- AndroidManifest.xml: 런타임 패키지 발견을 위한 Intent Category -->
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD"/>

ContentProvider 조회: org.khronos.openxr.runtime_broker(사용자 설치) → org.khronos.openxr.system_runtime_broker(시스템). 폴백: /vendor/etc/openxr/1/active_runtime.json.

환경변수 오버라이드 (전 플랫폼)

export XR_RUNTIME_JSON=/path/to/runtime/manifest.json

5.3 Runtime Manifest 예시

{
  "file_format_version": "1.0.0",
  "runtime": {
    "name": "Monado",
    "library_path": "/usr/lib/libopenxr_monado.so",
    "functions": {
      "xrCreateInstance": "monado_xrCreateInstance"
    },
    "instance_extensions": [
      {"name": "XR_KHR_vulkan_enable2", "extension_version": 2}
    ]
  }
}

5.4 API Layer Manifest

{
  "file_format_version": "1.0.0",
  "api_layer": {
    "name": "XR_APILAYER_LUNARG_core_validation",
    "library_path": "./XrApiLayer_core_validation.so",
    "api_version": "1.0",
    "implementation_version": "1",
    "enable_environment": "XR_ENABLE_CORE_VALIDATION",
    "disable_environment": "XR_DISABLE_CORE_VALIDATION"
  }
}

활성화:

export XR_ENABLE_API_LAYERS=XR_APILAYER_LUNARG_core_validation:XR_APILAYER_LUNARG_api_dump

6. 객체 모델 (Object Handles)

XrInstance                           ← 런타임 연결
└── XrSession                        ← 그래픽스 바인딩 세션
    ├── XrSwapchain[]                ← 그래픽스 API 텍스처 배열
    ├── XrSpace[]                    ← 좌표계
    │   ├── Reference Space (VIEW/LOCAL/STAGE/LOCAL_FLOOR/UNBOUNDED)
    │   └── Action Space (컨트롤러 포즈 등)
    ├── XrActionSet[]
    │   └── XrAction[] (boolean/float/vector2f/pose/vibration)
    └── XrSpatialAnchor[]            ← 확장

6.1 XrInstance 생성

XrApplicationInfo appInfo = {
    .applicationName    = "MyXRApp",
    .applicationVersion = 1,
    .engineName         = "MyEngine",
    .engineVersion      = 1,
    .apiVersion         = XR_CURRENT_API_VERSION
};
const char* extensions[] = {
    "XR_KHR_vulkan_enable2",
    "XR_EXT_hand_tracking",
};
XrInstanceCreateInfo ci = {
    .type                  = XR_TYPE_INSTANCE_CREATE_INFO,
    .applicationInfo       = appInfo,
    .enabledExtensionCount = 2,
    .enabledExtensionNames = extensions
};
XrInstance instance;
xrCreateInstance(&ci, &instance);

XrSystemGetInfo sysInfo = {
    .type       = XR_TYPE_SYSTEM_GET_INFO,
    .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
};
XrSystemId systemId;
xrGetSystem(instance, &sysInfo, &systemId);

6.2 XrSession 생성 (Graphics Binding 필수)

XrGraphicsBindingVulkan2KHR vkBinding = {
    .type             = XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR,
    .instance         = vkInstance,
    .physicalDevice   = vkPhysicalDevice,
    .device           = vkDevice,
    .queueFamilyIndex = graphicsQueueFamily,
    .queueIndex       = 0
};
XrSessionCreateInfo sessionCI = {
    .type     = XR_TYPE_SESSION_CREATE_INFO,
    .next     = &vkBinding,
    .systemId = systemId
};
XrSession session;
xrCreateSession(instance, &sessionCI, &session);

런타임 권장 GPU 디바이스 획득:

PFN_xrGetVulkanGraphicsDevice2KHR xrGetVulkanGraphicsDevice2KHR;
xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsDevice2KHR",
    (PFN_xrVoidFunction*)&xrGetVulkanGraphicsDevice2KHR);

XrVulkanGraphicsDeviceGetInfoKHR info = {
    .type           = XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR,
    .systemId       = systemId,
    .vulkanInstance = vkInstance
};
VkPhysicalDevice physDevice;
xrGetVulkanGraphicsDevice2KHR(instance, &info, &physDevice);

6.3 Graphics Binding 종류

API 바인딩 구조체 Extension
Vulkan XrGraphicsBindingVulkan2KHR XR_KHR_vulkan_enable2
OpenGL (Win32) XrGraphicsBindingOpenGLWin32KHR XR_KHR_opengl_enable
OpenGL ES (Android) XrGraphicsBindingOpenGLESAndroidKHR XR_KHR_opengl_es_enable
Direct3D 11 XrGraphicsBindingD3D11KHR XR_KHR_D3D11_enable
Direct3D 12 XrGraphicsBindingD3D12KHR XR_KHR_D3D12_enable
Metal XrGraphicsBindingMetalKHR (Apple 미참여로 Khronos 공식 미존재)

7. Session State Machine (가장 중요)

                  xrCreateSession()
                        │
                        ▼
                  ┌──────────────┐
                  │   UNKNOWN    │
                  └──────┬───────┘
                         │ runtime ready
                         ▼
              ┌──→  ┌─────────┐  ←─ xrEndSession 완료
              │     │  IDLE   │
              │     └────┬────┘
              │          │ 런타임이 RUNTIME_READY 알림
              │          ▼
              │     ┌─────────┐
              │     │  READY  │ ★ xrBeginSession() 호출 시점
              │     └────┬────┘
              │          │ xrBeginSession()
              │          ▼
              │     ┌────────────────┐
              │     │ SYNCHRONIZED   │
              │     └────┬───────────┘
              │          │ 가시화
              │          ▼
              │     ┌─────────┐
              │     │ VISIBLE │
              │     └────┬────┘
              │          │ 포커스 획득
              │          ▼
              │     ┌─────────┐
              │     │ FOCUSED │
              │     └────┬────┘
              │          │ 런타임이 종료 요청
              │          ▼
              │     ┌──────────┐
              └─────│ STOPPING │ ★ 즉시 xrEndSession() 호출
                    └──┬───────┘
                       │ 손실 / 재시작
                       ▼
                  ┌────────────────┐    ┌─────────┐
                  │ LOSS_PENDING   │ →  │ EXITING │ → 종료
                  └────────────────┘    └─────────┘

7.1 상태별 의미

상태 앱이 해야 할 일
IDLE CPU/GPU 최소화. 이벤트 폴링 계속
READY 즉시 xrBeginSession() 호출
SYNCHRONIZED 프레임 루프 실행. shouldRender=false면 렌더 생략 가능
VISIBLE 렌더링 + 레이어 제출. 입력 처리 X
FOCUSED 정상 게임 루프: 렌더 + xrSyncActions + 입력
STOPPING 즉시 xrEndSession() 호출. 프레임 루프 중단
LOSS_PENDING xrDestroySession() 후 선택적 재생성
EXITING 프로세스 종료 또는 비-XR UI 전환

8. Frame Loop

8.1 왜 Predicted Display Time이 핵심인가

머리 움직임 → 센서(~1ms) → CPU 게임루프(~3-5ms) → GPU 렌더(~8-10ms)
            → 컴포지터 합성(~2ms) → 디스플레이 스캔아웃(~1ms) → 포톤
                                                                  │
                                              motion-to-photon ←──┘

90Hz = 11.1ms 예산. 20ms 초과 시 멀미. 따라서 현재 헤드 포즈가 아닌 디스플레이 시점의 예측 포즈로 렌더해야 한다.

8.2 표준 프레임 루프

while (running) {
    PollEvents(instance, session, &running, &quit);

    XrFrameState fs = {.type = XR_TYPE_FRAME_STATE};
    xrWaitFrame(session, NULL, &fs);

    xrBeginFrame(session, NULL);

    XrCompositionLayerBaseHeader *layers[2] = {0};
    uint32_t layerCount = 0;

    if (fs.shouldRender) {
        XrViewLocateInfo vli = {
            .type                  = XR_TYPE_VIEW_LOCATE_INFO,
            .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
            .displayTime           = fs.predictedDisplayTime,
            .space                 = appSpace
        };
        XrView views[2];
        XrViewState vs = {.type = XR_TYPE_VIEW_STATE};
        uint32_t vc = 2;
        xrLocateViews(session, &vli, &vs, vc, &vc, views);
    }

    XrFrameEndInfo fei = {
        .type                 = XR_TYPE_FRAME_END_INFO,
        .displayTime          = fs.predictedDisplayTime,
        .environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE,
        .layerCount           = layerCount,
        .layers               = layers
    };
    xrEndFrame(session, &fei);
}

핵심 규칙:

  1. xrWaitFrame이 반환한 predictedDisplayTimexrLocateViews, xrEndFrame에 동일하게 사용
  2. xrLocateViews로 받은 pose를 그대로 XrCompositionLayerProjectionView.pose에 전달
  3. XrCompositionLayerProjection.space는 반드시 world-locked (LOCAL/STAGE 등). VIEW를 사용하면 ATW가 망가짐

9. Reference Spaces

VIEW         원점: 헤드(좌우 눈 중점), 헤드와 함께 이동
LOCAL        원점: 앱 시작 시 헤드 위치
STAGE        원점: 물리적 바닥 중앙
LOCAL_FLOOR  LOCAL + 추정 바닥 높이
UNBOUNDED    대규모 AR/MR 공간

좌표계: Right-handed, +Y up, -Z forward. 쿼터니언은 (x, y, z, w) 순서.


10. Action System

OpenXR Action System은 앱이 의미적 액션(grab, teleport)을 정의하고, 런타임이 하드웨어 매핑을 관리하는 구조다. 이 덕분에 입력 장치가 달라져도 앱 코드는 같은 의미 단위로 유지된다.

XrActionSetCreateInfo asci = {
    .type = XR_TYPE_ACTION_SET_CREATE_INFO,
    .priority = 0
};
strcpy(asci.actionSetName, "gameplay");
strcpy(asci.localizedActionSetName, "Gameplay");
XrActionSet gameplay;
xrCreateActionSet(instance, &asci, &gameplay);

11. Extension 메커니즘

접두사 의미
XR_KHR_* Khronos 비준
XR_EXT_* 멀티벤더 합의
XR_FB_* / XR_META_* Meta
XR_MSFT_* Microsoft
XR_VALVE_* Valve
XR_HTC_* HTC
XR_BD_* ByteDance
XR_ML_* Magic Leap
XR_VARJO_* Varjo
XR_ANDROID_* Android XR

12. OpenXR 런타임 생태계

벤더 기기 / 런타임 OS OpenXR 버전
Meta Quest 1/2/3/3S/Pro Android 1.1
Valve SteamVR Windows / Linux 1.0
Microsoft HoloLens 2 + WMR Windows 1.0
ByteDance Pico 4 / 4 Ultra Android 1.1
Google Galaxy XR / Android XR Android XR 1.1
Varjo XR-3 / XR-4 / Aero Windows 1.0
Collabora Monado Linux / Android 1.0

Apple Vision Pro는 여전히 OpenXR 미지원이다.


13. 게임 엔진 통합

13.1 Unity

[Unity App C#]
    ↓
[XR Interaction Toolkit]
    ↓
[Unity OpenXR Plugin]
   또는
[Meta OpenXR]
    ↓
[Runtime: Meta / SteamVR / Pico / ...]

13.2 Unreal / Godot / WebXR

  • Unreal은 Epic OpenXR Plugin이 기본 경로다.
  • Godot 4는 OpenXR 코어를 내장한다.
  • Chromium 기반 WebXR는 내부적으로 OpenXR 런타임을 호출할 수 있다.

14. WebXR vs OpenXR

항목 WebXR OpenXR
표준 기관 W3C Khronos
언어 JavaScript C/C++
환경 브라우저 Native / 게임 엔진
배포 URL 설치형
기능 범위 서브셋 풀 사양

15. 대안 비교

항목 OpenVR OpenXR
표준 주체 Valve 단독 Khronos 컨소시엄
대상 VR 전용 VR + AR + MR
런타임 SteamVR 종속 로더 + 다중 런타임
현황 유지보수 모드 활성 표준

16. 상황별 최적 선택

시나리오 권장
PC + Quest + Pico 크로스플랫폼 OpenXR
Quest 전용 + Meta 생태계 OpenXR + Meta XR SDK
iOS / visionOS ARKit + RealityKit
Web 배포 XR WebXR
Linux 오픈소스 XR Monado + OpenXR
Android XR OpenXR

17. 성능 최적화 베스트 프랙티스

  • predictedDisplayTime을 프레임 전반에 일관되게 사용
  • 멀티뷰와 단일 패스 스테레오를 적극 활용
  • UI는 Quad Layer 등 별도 레이어로 분리
  • Vulkan + Foveated Rendering + SpaceWarp 조합을 우선 검토

18. 함정 / 안티패턴

  • xrWaitFrame 결과와 다른 시각으로 xrLocateViews 호출
  • xrBeginFrame / xrEndFrame 짝 무결성 깨짐
  • xrPollEvent 생략으로 세션 상태 변화 미처리
  • xrSyncActions 없이 액션 상태 조회
  • Swapchain Acquire/Wait/Release 순서 위반
  • Projection Layer space에 VIEW 사용

19. 마이그레이션 패턴

  • OpenVR → OpenXR: 세션, 프레임 루프, 입력 시스템을 OpenXR 구조로 전환
  • Oculus SDK → OpenXR: Unity OpenXR Plugin + Meta OpenXR 또는 엔진 공식 플러그인 경로 사용
  • 벤더 확장 사용 시 KHR/Core 우선, 벤더별 폴백 적용

20. 검증 & 디버깅

export XR_ENABLE_API_LAYERS=XR_APILAYER_LUNARG_core_validation:XR_APILAYER_LUNARG_api_dump
export XR_LOADER_DEBUG=all

RenderDoc, PIX, Meta ODT, SteamVR Performance Tool 같은 툴이 실무 디버깅에 많이 쓰인다.


21. 빅테크 전략

  • Meta: 독자 API를 사실상 정리하고 OpenXR 중심으로 이동
  • Microsoft: HoloLens/WMR에 OpenXR을 적극 도입
  • Google: Android XR를 OpenXR 1.1 기반으로 시작
  • Valve: OpenVR에서 OpenXR로 점진 전환
  • Apple: visionOS 독자 스택 유지

22. 엔터프라이즈 / 방위산업

OpenXR은 벤더 락인을 줄이고 장비 교체 비용을 낮출 수 있어 산업 훈련, 시뮬레이터, 방위 분야에서 특히 중요하다.


23. 경험적 조언

  1. Extension은 기능 플래그처럼 다뤄라.
  2. predictedDisplayTime은 절대 대충 쓰면 안 된다.
  3. 런타임별 공통분모와 벤더 특화 기능을 분리 설계하라.
  4. OpenXR은 이식성의 코어이고, 생태계 기능은 벤더 SDK가 보완한다.

24. 참고 자료