パススルーを実装する 健康と安全に関するおすすめ: パススルーAPIを使って複合現実エクスペリエンスを構築する際、ユーザーにとって快適かつ安全なエクスペリエンスをサポートしているかどうか、開発者が自分のコンテンツを評価することを強くおすすめします。詳しくは、
インサイトSDKについてのヒントとコツ のガイドをご覧ください。
パススルー機能は、物理世界の3Dビジュアリゼーションを、リアルタイムで快適に知覚できるようにMeta Questヘッドセットに提供します。パススルーAPIにより、バーチャルエクスペリエンスにパススルー表示を統合することができます。その機能は、OpenXRの拡張機能であるXR_FB_passthroughとXR_FB_triangle_meshによって提供されます。
パススルーは、専用サービスにより別個のレイヤーにレンダリングされ、XRコンポジターに直接送られます。ユーザーの物理環境の画像や動画に、アプリからアクセスすることはできません。その代わりに、アプリから特殊なプレースホルダーレイヤーが送信されます。このレイヤーが、XRコンポジターにより実際のパススルー表示に置き換わります。パススルーをカスタマイズする手段は、複合レイヤーやスタイリングなどいくつかあります。
複合レイヤー では、パススルーレイヤーの配置をXRコンポジタースタック内での仮想コンテンツとの相対関係(オーバーレイやアンダーレイ)で指定し、仮想コンテンツとどうブレンドするかを指定できます。パススルーを画面上のどこに表示するかは、アルファマスキングを使って指定できます。現在のところ、パススルーの奥行きに基づいてブレンドを指定する手段はありません。スタイリング では、パススルーフィードに色を付け、エッジレンダリングなどの視覚的効果を適用できます。サーフェス投影パススルー では、パススルー画像の投影先ジオメトリを定義します。このアプローチでは、アプリでユーザーの環境のさまざまな部分を認識している場合に、パススルーの表示の安定性が高くなります。XRセッション は、OpenXR仕様で定義されている、OpenXRセッションオブジェクト(ハンドルで表現される)です。パススルーオブジェクトはXrSessionインスタンスをスコープとしているため、ほとんどの作成(create)呼び出しにはセッションの指定が必要になります。詳しくは、
インスタンスとセッションの作成 をご覧ください。
パススルー機能 は、パススルー機能を有効にして、その機能の動作に必要なデータを提供します。
パススルーレイヤー は、コンテンツのレンダリング機能を提供します。それらはシステムによって生成され、アプリに代わってシステムコンポジターに送信されます。アプリでは、コンテンツをどこにどうレンダリングするかを指定できます。どこに というのは、合成スタックの中の位置に対応します(アプリの投影レイヤーの上か下かなど)。どう というのは、タイプ(投影か再構成か)とスタイル(色、輪郭)に対応します。
メッシュとジオメトリインスタンス を利用すると、(自動環境深度再構成ではなく)パススルー画像の投影先のジオメトリをアプリで指定することができます。パススルーがアクティブになると、パススルーはサーフェス投影パススルーの対象として選ばれているジオメトリ上にのみ表示されます。パススルーは、それらのジオメトリのテクスチャーのように動作します。このアプローチでは、アプリでユーザーの環境のさまざまな部分を認識している場合に、パススルーの表示の安定性が高くなります。
ヘッドセットがインターネットに接続されていること、最新バージョンがインストールされていることを確認します。ヘッドセットの[Settings (設定)] > [System (システム)] > [Software Update (ソフトウェアの更新)] で、最新バージョンであるかどうかを確認し、必要に応じて更新します。 アプリでは64ビットのビルドを使う必要があります。32ビットのアプリはサポートされていません。 Meta QuestとQuest 2の一般的なOpenXRプロジェクトの設定方法について詳しくは、モバイルSDKの利用を開始する とMeta QuestおよびQuest 2向けのOpenXRサポート をご覧ください。 AndroidManifest.xmlファイルに、次のように指定してパススルー機能のフラグを追加します。<uses-feature android:name="com.oculus.feature.PASSTHROUGH" android:required="true" /> 注 : マニフェストファイルの中でこの機能フラグがセットされていないと、パススルーOpenXR拡張機能は有効になりません。
パススルーAPIを実装するには、OpenXRインスタンス作成時に、XR_FB_passthroughとXR_FB_triangle_mesh(サーフェス投影パススルー専用)拡張機能が必須拡張機能として宣言されていることが必要です。
std::vector<const char*> requiredExtensionNames{
XR_FB_PASSTHROUGH_EXTENSION_NAME,
XR_FB_TRIANGLE_MESH_EXTENSION_NAME // optional
};
XrInstanceCreateInfo instanceCreateInfo = {XR_TYPE_INSTANCE_CREATE_INFO};
instanceCreateInfo.createFlags = 0;
instanceCreateInfo.applicationInfo = appInfo;
instanceCreateInfo.enabledApiLayerCount = 0;
instanceCreateInfo.enabledApiLayerNames = NULL;
instanceCreateInfo.enabledExtensionCount = requiredExtensionNames.size();
instanceCreateInfo.enabledExtensionNames = requiredExtensionNames.data();
XrInstance instance;
XrResult result = xrCreateInstance(&instanceCreateInfo, &instance);
if (XR_FAILED(result)) {
LOG("Failed to create XR instance: %d.\n", initResult);
exit(1);
}
次に、通常の手順どおりXrSessionの作成に移ります。OpenXRのインスタンスとセッションの設定と管理のあらゆる面を網羅したサンプルについては、ネイティブ版のサンプルをご覧ください。
上記の前提条件のいずれかが満たされていない場合、インスタンスの作成は失敗します。XrInstanceを作成する前に、拡張機能が利用可能かどうかを確認することができます。そのためには、
xrEnumerateInstanceExtensionProperties を呼び出して、返される拡張機能のリストの中に
XR_FB_passthroughと
XR_FB_triangle_meshが存在していることを確認します。
システムがパススルーをサポートしていることを確認する static bool SystemSupportsPassthrough(XrInstance instance, XRFormFactor formFactor)
{
XrSystemPassthroughProperties2FB passthroughSystemProperties{XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB};
XrSystemProperties systemProperties{XR_TYPE_SYSTEM_PROPERTIES, &passthroughSystemProperties};
XrSystemGetInfo systemGetInfo{XR_TYPE_SYSTEM_GET_INFO};
systemGetInfo.formFactor = formFactor;
XrSystemId systemId = XR_NULL_SYSTEM_ID;
xrGetSystem(instance, &systemGetInfo, &systemId);
xrGetSystemProperties(instance, systemId, &systemProperties);
return (passthroughSystemProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_BIT_FB;
}
同様に、現在のデバイスでカラーパススルーがサポートされているかどうかについて、XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB機能フラグがtrueかどうかを調べます。
パススルー拡張機能で定義されている関数を使うには、関数ポインターを宣言して取得する必要があります。
PFN_xrCreatePassthroughFB pfnXrCreatePassthroughFBX = nullptr;
XrResult result = xrGetInstanceProcAddr(_instance, "xrCreatePassthroughFB", (PFN_xrVoidFunction*)(&pfnXrCreatePassthroughFBX));
if (XR_FAILED(result)) {
LOG("Failed to obtain the function pointer for xrCreatePassthroughFB.\n");
}
関数ポインターすべてのリストについては、OpenXRパススルーのサンプルをご覧ください。
パススルーレイヤーをアプリに追加するには、その前にアプリでパススルー機能を作成する必要があります。パススルー表示に必要になる基本的なシステムリソースや処理は、パススルー機能により管理されます。アプリで行うべきことは、すべてのセッションで1つのパススルー機能を作成することだけです。
// Create the feature
XrPassthroughFB passthroughFeature = XR_NULL_HANDLE;
XrPassthroughCreateInfoFB passthroughCreateInfo = {XR_TYPE_PASSTHROUGH_CREATE_INFO_FB};
passthroughCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
XrResult result = pfnXrCreatePassthroughFBX(GetSession(), &passthroughCreateInfo, &passthroughFeature);
if (XR_FAILED(result)) {
LOG("Failed to create the passthrough feature.\n");
}
XrPassthroughCreateInfoFBの中でXR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FBフラグを指定することにより、パススルー機能が作成後すぐに開始されます。つまり、パススルー表示に必要な環境再構成やその他のバックグラウンドタスクを、システムがただちに実行開始する場合があるということです。アプリ実行時にパススルーをすぐには表示しないなどの理由で、作成と開始を分離するのであれば、flagsをセットしないままにし、後で手動で機能を開始してください。それには次のようなコードを使います。
// Start the feature manually
XrResult result = pfnXrPassthroughStartFB(passthroughFeature);
if (XR_FAILED(result)) {
LOG("Failed to start a passthrough feature.\n");
}
システムでパススルー画像を生成するための準備はパススルー機能によって行いますが、アプリの中でパススルーが表示されるようにするには、アプリで1つ以上のパススルーレイヤーを作成し、開始する必要があります。パススルーレイヤーには次の2つの目的があります。
パススルーをアプリの他のレイヤーとどう合成するかを指定する。例えば、メイン投影レイヤーなどです。 パススルーの外観と動作を別個にカスタマイズする。 アプリでは、複数のパススルーレイヤーを作成して開始することができます。しかし、同時に作成できるパススルーレイヤーは3つまでです。
// Create and run passthrough layer
XrPassthroughLayerFB passthroughLayer = XR_NULL_HANDLE;
XrPassthroughLayerCreateInfoFB layerCreateInfo = {XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB};
layerCreateInfo.passthrough = passthroughFeature;
layerCreateInfo.purpose = XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB;
layerCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
XrResult result = pfnXrCreatePassthroughLayerFBX(Session, &layerCreateInfo, &passthroughLayer);
if (XR_FAILED(result)) {
LOG("Failed to create and start a passthrough layer");
}
パススルー機能と同じようにパススルーレイヤーについても、XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FBフラグを省くことにより停止状態で作成しておいて、後でxrPassthroughLayerResumeFBを使って開始することができます。
purposeフィールドは、パススルーレイヤーのタイプを指定します。ほとんどの場合は、
XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FBが適切な選択となります。その他の選択肢の説明については、
サーフェス投影パススルー を参照してください。
アプリから送信する他のレイヤーとパススルーレイヤーをどういう順序でブレンドするかをXRコンポジターに対して指示するには、各パススルーレイヤーのxrEndFrame呼び出しに、タイプXrCompositionLayerPassthroughFBのコンポジターレイヤーを含める必要があります。
アプリに1つの投影レイヤーと1つのパススルーレイヤーするという単純なシナリオでは、これにより、パススルーレイヤーをアプリケーションの投影レイヤーの上または下のどちらに表示するかをアプリで選択できるようになります。レイヤー数が3つ以上になる複雑なシナリオの場合、任意の順序で合成することが可能です。
プロキシレイヤーが送信されていないパススルーレイヤーは、コンポジターによって破棄される場合があります。ただし、プロキシレイヤーを送信しないことでパススルーレイヤーを非表示にすることはできません。アプリでは、
xrPassthroughLayerPauseFB でシステムリソースを保存し、パススルーが非アクティブであることをシステムに通知する必要があります。プロキシレイヤーは、常に実行中のパススルーレイヤーに対して送信を行い、一時停止中のパススルーレイヤーに対しては送信を行いません。
以下のスニペットは、パススルーレイヤーがアプリの投影レイヤーのオーバーレイとして合成される単純なシナリオを示しています。
XrCompositionLayerPassthroughFB passthroughCompLayer = {XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB};
passthroughCompLayer.layerHandle = passthroughLayer;
passthroughCompLayer.flags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
passthroughCompLayer.space = XR_NULL_HANDLE;
const kLayerCount = 2;
const XrCompositionLayerBaseHeader* layers[kLayerCount] = {
(const XrCompositionLayerBaseHeader*) applicationCompLayer,
(const XrCompositionLayerBaseHeader*) passthroughCompLayer
};
XrFrameEndInfo endFrameInfo = {XR_TYPE_FRAME_END_INFO};
endFrameInfo.displayTime = predictedDisplayTime;
endFrameInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
endFrameInfo.layerCount = kLayerCount;
endFrameInfo.layers = layers;
xrEndFrame(session, &endFrameInfo);
構造コンテンツの次の点に注意してください。
パススルー合成レイヤーに画像データが含まれないためXrCompositionLayerPassthroughFB::spaceは無関係なので、XR_NULL_HANDLEに設定する必要があります。 パススルー合成レイヤーに関係するレイヤーフラグは、XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BITだけです。それ以外のレイヤーフラグは無視されます。
スタイルまたはサーフェス投影パススルーが使われている場合、システム生成のパススルーレイヤーに不透明でないアルファ値が含まれる可能性があります。XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BITがセットされていない場合、それらのアルファ値は無視されます。アプリでアルファ値を無視することが特に必要でない限り、このフラグをセットすることをおすすめします。 Meta Quest OpenXRの実装では、パススルーを使う場合であっても、XrFrameEndInfo::environmentBlendModeがXR_ENVIRONMENT_BLEND_MODE_OPAQUEに設定されている必要があります。パススルーを背景として表示するには、アプリの投影レイヤーより前にパススルーレイヤーを送信します。つまり、XrCompositionLayerBaseHeader配列の中でapplicationCompLayerとpassthroughCompLayerの挿入順序を変更します。 次の2つの拡張機能は、XrCompositionLayerPassthroughFBインスタンスの次のチェーンの中でサポートされます。合成時にパススルーレイヤーによって、それらの拡張機能のプロパティが考慮されます。
XR_FB_composition_layer_alpha_blend: パススルーレイヤーのブレンド係数を指定します。例えば、加算的ブレンドを実現したり、パススルーレイヤーを別のレイヤーのアルファチャネルでマスキングしたりすることが可能です(「複合現実の合成とマスキング」を参照)。XR_KHR_composition_layer_color_scale_bias: 合成時のパススルーレイヤーの色とアルファ値に変更を加えます。 アプリの中で、ユーザーの選択に基づいてVRやパススルー背景を表示したいと思う可能性があります。Metaのシステムはすでにホーム環境でユーザーにこの選択肢を提供しているため、ユーザーのホーム環境設定をアプリに流用できます。より一般的な言い方をすれば、ユーザーの個人設定に基づいて、システムはMRとVRのどちらをデフォルト値としてアプリに推奨するかを決めます。この推奨事項は、拡張機能
XR_META_passthrough_preferences によって利用可能になります。
xrGetPassthroughPreferences を呼び出します。フラグXR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_METAが設定されている場合、アプリでパススルーを表示することがシステムから推奨されます。これは現在、ユーザーがホーム環境でバックグラウンドとしてパススルーを選択した場合に該当します。