深度
ARDKの深度推定は、現実世界の各ピクセルを示す深度マップを生成し、デバイスのカメラから画面上の各ピクセルまでの実際の距離(メートル単位)を推定する機能です。 この機能には、以下のようなさまざまな使用例があります(ただし、これらに限定されません):
- オクルージョン用のzbufferに深度値を書き込む。
- 深度バッファから3次元位置をフェッチして、オブジェクトをワールドに配置する。
- メッシングシステムの一部としてメッシュを構築する。
- 被写界深度などの視覚効果を利用して、近くの被写体に焦点を合わせる。
これは深度カメラを使って、近くから遠くへ伝わる「パルス」を作り出す例である:
ARオクルージョンマネージャー
ARDK 3.0はUnityのAR Foundation Occlusion Subsystemと統合されています(新しいタ ブで開きます)。 XR設定でLightshipが有効になっていると、Lightshipの高度な深度を活用したサブシステムを実装することができます。 開発者としては、標準の AROcclusionManager (opens in new tab)をシーンに配置するだけです。
AROcclusionManager
のインターフェイスはAR Foundationと同じですが、オプションでできることは異なります:
- 環境深度モード: Lightshipの環境深度モードでは、次の改良されたニューラルネットワークアーキテクチャから選択できます。
- Medium: 当社独自の多重深度アーキテクチャを使用して深度を推定します。
- Best: 改良された多重深度のちらつき防止モデルを使用して深度を推定します。このアーキテクチャでは、前の時間ステップの深度マップを考慮します。
- Fastest: 小型だが、精度が低い可能性があるモデルを使用して深度を推定します。
- Temporal Smoothing(時間的スムージング): Lightshipではサポート対象外です。
- 人間のセグメンテーション:ライトシップには、人間を含む、より大きなアイテムのセグメンテーションのための独立した機能があります(セマンティック機能のページを参照)。 上記のオプションはLightshipでは使用しないため、 Disabled(無効) のままにしておきます。
- オクルージョン優先モード: 通常、環境オクルージョンと人間オクルージョンを切り替える場合に使用するモードです。 Lightshipでは、このモードを No Occlusion(オクルージョンなし) に切り替え、オクルージョンをオフにする場合のみ使用します。
深度をテクスチャとして利用する
AROcclusionManager
コンポーネントをシーンに配置すると、 MonoBehaviour
内で最新の深度マップをGPUテクスチャとして利用できます。
を使って
public class AccessDepthMap : MonoBehaviour
{
public AROcclusionManager _occlusionManager;
using ...
void Update()
{
if (!_occlusionManager.subsystem.running)
{
return;
}
...
var depthTexture = _occlusionManager.environmentDepthTexture;
...
}
...
}
Lightshipの深度推定が使用するニューラルネットワークのため、ここでオクルージョンマネージャから表面化される深度テクスチャ
は、反時計回りに90度回転され、固定アスペクト比を持ちます。 入力画像の例(左)と、対応する深度テクスチャ(右)。
Display Depth as a Shader(深度をシェーダーとして表示する) の入門ガイドページでは、画像を時計回りに90度回転させ、表示行列を使 用して出力される深度画像を適切なアスペクト比に変換するシェーダーの一例を紹介しています。
CPU上で深度マップをサンプリングする
AROcclusionManager
コンポーネントをシーンに配置すると、 MonoBehaviour
内で最新の深度マップをサンプリングできます。 このスニペットでは、CPU上で深度マップを取得し、画面のほぼ中央の深度を見つける方法を示しています。
を使って
public class SampleDepthMap : MonoBehaviour
{
public AROcclusionManager _occlusionManager;
private Matrix4x4 m_DisplayMatrix;
XRCpuImage? depthimage;
void Update()
{
if (!_occlusionManager.subsystem.running)
{
return;
}
if (_occlusionManager.TryAcquireEnvironmentDepthCpuImage(out
var image))
{
depthimage?.Dispose();
depthimage = image;
}
else
{
return;
}
var uvCenter = new Vector2(0.5, 0.5); // 画面の中心
var depthCenter = depthimage.Value.Sample<float>(uv, m_DisplayMatrix);
}
}
}
ここでも、depthImage
はLightshipからの生出力(反時計回りに90度回転、アスペクト比固定)である。 深度を使って地点をワールド座標に変換する の入門ガイドページでは、CPU上で深度マップを取得し、カメラの表示行列を使用してサンプリングする方法を紹介しています。
詳細を見る
深度の使い方については、深度に関する次の入門ガイドページをご覧ください。
デプス関連のサンプルもご覧ください: