本文へスキップ
バージョン: 3.0

深度情報を取得して表示する

この入門ガイドでは、深度バッファにアクセスする方法と使用例をご紹介します。 この例では、シェーダーで深度情報を取得し、カラーフィルターとして画面上に表示します。

この入門ガイドでは、以下の内容について説明します。

  1. 深度バッファにアクセスし、シェーダーを使って画面に表示する。
  2. 回転やアスペクト比を設定できるように、カメラからディスプレイのtransformを取得する。
  3. 生の深度テクスチャと行列をシェーダーに渡す。
  4. ディスプレイ行列を使用して、深度テクスチャ上の適切なサンプリングポイントを算出する。
  5. 深度情報の使用例として、テクスチャを数学的にカラースケールに変換する。

前提条件

ARDKがインストールされたUnityプロジェクトと、セットアップされた基本的なARシーンが必要です。 詳細については、 ARDK 3のインストール および ARシーンの設定を参照してください。

Raw Imageの追加

Raw Imageを追加して深度情報を表示するには、次のように行います。

  1. AR シーン下の HierarchyRaw Image を追加します:
    1. メインシーン下の Hierarchy で右クリックし、 UI にマウスオーバーし、 Raw Imageを選択します。
  2. 画像変換ツールを使って、 Raw Image を中央に配置し、後で見えるように画面全体に引き伸ばします。

マテリアルとシェーダーを追加します。

マテリアルとシェーダーを作成するには、次のように行います。

  1. Assets(アセット)ウィンドウで右クリックし、 Create(作成) の上にカーソルを合わせ、 Material(マテリアル) を選択します。 DepthMaterial という名前を付けます。
  2. この作業を繰り返しますが、 Shader(シェーダー) にカーソルを合わせ、 Standard Surface Shader を選択します。 DisplayDepth.
  3. シェーダーをマテリアルにドラッグして、それらを接続します。
  4. DisplayDepth Shader Code のコードを DisplayDepth シェーダに追加します。
ここをクリックしてDisplayDepthのコードを表示します。

DisplayDepth Shader Code

Shader "Unlit/DisplayDepth"
{
プロパティ
{
_MainTex ("_MainTex", 2D) = "white" {}
_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
{
float2 uv : TEXCOORD0;
float2 texcoord :TEXCOORD1;
float4 vertex : SV_POSITION;

};

float4x4 _DisplayMat;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v. vertex.vertex);
o.uv = v.uv;

#if !UNITY_UV_STARTS_AT_TOP
o.uv.y = 1-o.uv.y;
#endif

//画像を正しい回転とアスペクトに調整する必要があります。
o.texcoord = mul(float3(o.uv, 1.0f), _DisplayMat).xy;
return o;
}

sampler2D _MainTex;
sampler2D _DepthTex;

fixed4 frag (v2f i) : SV_Target
{
float depth = tex2D(_DepthTex, i.texcoord).r;

const float MAX_VIEW_DISP = 4.0f;
const float scaledDisparity = 1.0f / depth;
const float normDisparity = scaledDisparity / MAX_VIEW_DISP;

return float4(normDisparity,normDisparity,normDisparity,0.8);
}
ENDCG
}
}
}

深度データを取得するスクリプトを作成する

  1. Assets(アセット) ウィンドウで C#スクリプト ファイルを作成します。
  2. Depth_HowTo という名前を付けます。
  3. ファイルエディターで Depth_HowTo を開き、 深度スクリプトのコード のコードを追加します。

深度スクリプトのコード

using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class Depth_HowTo :MonoBehaviour
{
public ARCameraManager _cameraManager;

public AROcclusionManager _occlusionManager;

public RawImage _rawImage;

public Material _material;

private Matrix4x4 _displayMat = Matrix4x4.identity;

void OnEnable()
{
_cameraManager.frameReceived += OnCameraFrameUpdate;
}

private void OnDisable()
{
_cameraManager.frameReceived -= OnCameraFrameUpdate;
}

void Update()
{
if (!_occlusionManager.subsystem.running)
{
return;
}

//raw imageに素材を追加します。
_rawImage.material = _material;

//シェーダーに変数を設定する
//注意:深度テクスチャの更新はUpdate()関数内で行う必要があります
_rawImage.material.SetTexture("_DepthTex", _occlusionManager.EnvironmentDepthTexture)EnvironmentDepthTexture);
_rawImage.material.SetMatrix("_DisplayMat",_displayMat);
}

private void OnCameraFrameUpdate(ARCameraFrameEventArgs args)
{
if (!_occlusionManager.subsystem.running)
{
return;
}

// ディスプレイ・マトリックスを取得
_displayMat = args.displayMatrix? Matrix4x4.identity;

#if UNITY_ANDROID && !UNITY_EDITOR
_displayMat = _displayMat.transpose;
#endif
} }.
}

すべてを組み合わせる

テスト用にすべての部品を接続して試すには、次の手順を行います。

  1. Empty GameObject を作成します。
  2. Depth_HowTo スクリプトを Empty GameObject にドラッグします。
  3. Inspector
    1. メインカメラを Camera Manager のスクリプトにドラッグします。
    2. メインカメラを Occlusion Manager のスクリプトにドラッグします。
    3. マテリアルを Material のスクリプトにドラッグします。
    4. Raw Imageを Raw Image のスクリプトに渡します。
  4. Build Settings(ビルド設定) を開き、シーンをデバイスにビルドして試してみましょう。

出力

深度ディスプレイの操作
シェーダーに加える変更によっては、サンプルシーンの表示が異なる場合があります。