シェーダーとして深度情報にアクセスして表示する
通常、ARアプリケーションでカメラフレームを扱う際には、カメラに合わせた変換マトリックス(表示マトリックス)を使用して、アスペクト比がアプリケーションのビューポートに一致するようにする必要があります。 深度画像とAR背景画像のアスペクト比が一致している場合、AR Foundationでは表示マトリックスを AROcclusionManager.environmentDepth
に適用し、適切な解像度の深度マップテクスチャを出力することができます。 Lightshipでは、 LightshipOcclusionExtension
でこれらのプロパティを分離することで、 DepthTexture(テクスチャ自体)
と DepthTransform(表示マトリックス)
の両方を使用できます。 このように変換マトリックスを個別に保存することで、デバイスから深度情報が取得できなかったカメラフレームに対しても、補正が可能なワーピングデータを追加することができます。
この入門ガイドでは、以下の内容について説明します。
- フルスクリーン画像を表示するためのUIとシェーダーリソースを設定する。
- 深度テクスチャにアクセスする。
- テクスチャを画面に合わせる画像変換マトリックスを取得する。
- 深度テクスチャとその画像変換マトリックスをレンダリングリソースに適用する。
- メトリック深度を色スケールに数値変換する(深度情報の活用例)。
前提条件
ARDKがインストールされたUnityプロジェクトと、セットアップされた基本的なARシーンが必要です。 詳しくは、Lightship ARDKのセットアップと 基本的なARシーンのセットアップを参照してください。 また、Niantic はUnityエディターでテストできるように、 プレイバックを設定する ことも推奨しています。
ARオクルージョンマネージャーを追加する
ARFoundationでは、 AR Occlusion Manager のMonoBehaviourを使用することで、深度バッファにアクセスできます。 プロジェクトに AR Occlusion Manager を追加するには、次の手順を行います。
- メインカメラ の
GameObject
にAROcclusionManager
を追加します。- Hierarchyで、
XROrigin
と Camera Offsetを展開し、 Main Camera オブジェクトを選択します。 次に、 Inspectorで、 Add Component をクリックし、AROcclusionManager
を追加します。
- Hierarchyで、

Lightship Occlusion Extensionの追加
拡張機能を追加するには、以下の手順を行います。
LightshipOcclusionExtension
をメインカメラGameObject
に追加します:- Hierarchy で、
XROrigin
を展開し、 Main Camera を選択します。 次に、 インスペクタ で、 コンポーネントの追加 をクリックし、Lightship Occlusion Extension
を追加します。
- Hierarchy で、
AR Foundation Occlusion Managerを使用して深度テクスチャにアクセスする
AR Foundationから深度テクスチャを取得するには、次の手順を行います。
- Project ウィンドウで Assets フォルダを開き、その中で右クリックして Create メニューを開き、 C# Script を選択します。
Depth_HowTo
という名前を付けます。 Depth_HowTo.cs
をファイルエディターで開き、以下のスニペットからコードを追加して保存します。- Hierarchy で Main Camera を選択します。 Assets フォルダから
Depth_HowTo.cs
を Inspector の下部にドラッグし、コンポーネントとして追加します。 **Occlusion Manager **の横の丸をクリックし、Main Cameraを選択します。

深度の入門ガイド コードを表示するにはクリックしてください。
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using Niantic.Lightship.AR.Utilities;
public class Depth_HowTo :MonoBehaviour
{
public AROcclusionManager _occlusionManager;
void Update()
{
if (!_occlusionManager.subsystem.running)
{
return;
}.
// AR Foundationから深度テクスチャを取得する
// 背景画像と同じアスペクト比である必要がある
var depthTexture = _occlusionManager.environmentDepthTexture;
// カメラの表示行列のレイアウトはプラットフォームによって異なるため保証できない
// そのため、代わりにCameraMathライブラリを使用して自分で計算する
var displayMatrix = CameraMath.CalculateDisplayMatrix
(
depthTexture.width,
depthTexture.height,
Screen.width,
Screen.height,
XRDisplayContext.GetScreenOrientation()
);
// テクスチャで何かする
// ...
}
}
Lightship Occlusion Extensionを使用して深度テクスチャにアクセスする
Lightshipから深度テクスチャを取得するには、次の手順を行います。
Depth_HowTo.cs
を再度開き、コードを以下のスニペットに置き換えます。- スクリプトの準備ができたら、 Hierarchy から Main Camera を選択し、 Inspector でそれをコンポーネントとして追加します。 Occlusion Extension フィールドの横にある丸をクリックし、 Main Camera を選択します。

深度の入門ガイド コードを表示するにはクリックしてください。
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using Niantic.Lightship.AR.Utilities;
using Niantic.Lightship.AR.Occlusion;
public class Depth_HowTo :MonoBehaviour
{
public AROcclusionManager _occlusionManager;
public LightshipOcclusionExtension _occlusionExtension;
void Update()
{
if (!_occlusionManager.subsystem.running)
{
return;
} // 深度テクスチャを取得します。
//
var depthTexture = _occlusionExtension.DepthTexture;
var displayMatrix = _occlusionExtension.DepthTransform;
// テクスチャで何かする
// ...
}
}
Raw Imageを追加して深度バッファを表示する
リアルタイムの深度データにアクセスできるようになったので、それをカスタムUI要素に反映して画面上に 表示します。 この例では、Raw Imageを作成し、深度バッファを変換してカメラ出力の上にオーバーレイ表示するマテリアルをアタッチします。
リアルタイムの深度表示を設定するには、次の手順を行います。
- Hierarchy で右クリックし、 UI メニューを開いて Raw Image を選択します。 新しいRaw Imageに
DepthImage
という名前を付けます。 - 画像変換ツールを使って Raw Image を画面中央に配置し、後で見やすいように画面全体を覆うように広げます(例は下の画像を参照)。
- すべてのパラメーター(左、上、Z、右、下)を0に設定します。

マテリアルとシェーダーを追加する
マテリアルとシェーダーを作成するには、次のように行います。
- Project ウィンドウで Assets フォルダを開き、その中で右クリックします。 Create メニューを開き、 Material を選択します。 新しいマテリアルに
DepthMaterial
という名前を付けます。 - この作業を繰り返しますが、Shaderメニュー開き、Unlit Shaderを選択します。 新しいシェーダーに
DisplayDepth
という名前 を付けます。 - シェーダーをマテリアルにドラッグして、それらを接続します。
- シェーダーをダブルクリックして開き、次のセクションの
DisplayDepth
シェーダーコードに貼り付けます。
DisplayDepthシェーダーのコード
深度表示は、vert/fragセクションを使用する標準的なフルスクリーンシェーダーです。 このシェーダーのvertセクションでは、ディスプレイ変換行列を使ってUV座標に乗算し、テクスチャをサンプリングします。 この操作により、深度を画面に合わせるための変換が行われます。
クリックしてDepthDisplayシェーダーを表示
Shader "Unlit/DisplayDepth"
{
Properties
{
_DepthTex ("_DepthTex", 2D) = "green" {}
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float3 texcoord : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// 深度テクスチャのサンプラー
sampler2D _DepthTex;
// スクリーン空間から深度テクスチャ空間への変換
float4x4 _DepthTransform;
inline float ConvertDistanceToDepth(float d)
{
// 近クリップ平面よりも小さい距離をクリップし、その距離から深度値を計算します
return (d < _ProjectionParams.y) ? 0.0f : ((1.0f / _ZBufferParams.z) * ((1.0f / d) - _ZBufferParams.w));
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// 画像変換をUV座標に適用
o.texcoord = mul(_DepthTransform, float4(v.uv, 1.0f, 1.0f)).xyz;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// 深度画像変換にはリプロジェクション(ワー ピング)が含まれている可能性があるため、
// 同次座標から直交座標にUV座標を変換する必要があります
float2 depth_uv = float2(i.texcoord.x / i.texcoord.z, i.texcoord.y / i.texcoord.z);
// 深度値は赤チャンネルをサンプリングして取得
// テクスチャ内の値は、カメラからの距離を示すメトリックの視線深度(カメラからの距離)
float eyeDepth = tex2D(_DepthTex, depth_uv).r;
// 視線深度をZバッファ値に変換
// Zバッファ値は[0, 1]の範囲の非線形値
float depth = ConvertDistanceToDepth(eyeDepth);
// Z値を色として使用
#ifdef UNITY_REVERSED_Z
return fixed4(depth, depth, depth, 1.0f);
#else
return fixed4(1.0f - depth, 1.0f - depth, 1.0f - depth, 1.0f);
#endif
}
ENDCG
}
}
}