Depth API 可協助裝置的相機瞭解場景中真實物體的大小和形狀。這項功能會使用相機拍攝深度圖片或深度地圖,為應用程式增添 AR 寫實感。您可以運用深度圖片提供的資訊,讓虛擬物件準確出現在現實世界中或物件後方,帶來身歷其境且逼真的使用者體驗。
深度資訊是根據動作計算得出,可能會與硬體深度感應器的資訊結合,例如飛行時間 (ToF) 感應器 (如有)。裝置不需要 ToF 感應器即可支援 Depth API。
必要條件
請務必瞭解基本 AR 概念 以及如何在繼續操作前設定 ARCore 工作階段。
將應用程式設為 Depth Required 或 Depth Optional (僅限 Android)
如果您的應用程式需要 Depth API 支援, 是 AR 體驗的核心環節需要深度 但應用程式上其他運用深度的部分 都沒有良好的遞補機制 您可以選擇限定在 Google Play 商店中發行應用程式 支援 Depth API 的裝置。
讓應用程式Depth Required
前往 Edit > Project Settings > XR Plug-in Management > ARCore。
Depth 目前預設為 Required。
讓應用程式Depth Optional
前往 Edit > Project Settings > XR Plug-in Management > ARCore。
從「Depth」下拉式選單中選取「Optional」 視需要將應用程式設為「深度」
啟用深度
為了儲存資源,ARCore 預設不會啟用 Depth API。參加
引進支援裝置時,必須手動將
AROcclusionManager
敬上
元件新增至 AR 相機遊戲物件中的 Camera
和
ARCameraBackground
元件。詳情請見
自動遮蔽
請參閱 Unity 說明文件
在新的 ARCore 工作階段中, 使用者的裝置支援深度和 Depth API,如下所示:
// Reference to AROcclusionManager that should be added to the AR Camera
// game object that contains the Camera and ARCameraBackground components.
var occlusionManager = …
// Check whether the user's device supports the Depth API.
if (occlusionManager.descriptor?.supportsEnvironmentDepthImage)
{
// If depth mode is available on the user's device, perform
// the steps you want here.
}
取得深度圖片
取得最新的環境深度映像檔:
AROcclusionManager
。
// Reference to AROcclusionManager that should be added to the AR Camera
// game object that contains the Camera and ARCameraBackground components.
var occlusionManager = …
if (occlusionManager.TryAcquireEnvironmentDepthCpuImage(out XRCpuImage image))
{
using (image)
{
// Use the texture.
}
}
您可以將原始 CPU 映像檔轉換為 RawImage
以獲得更大的彈性一個
範例請見 Unity 的 ARFoundation 範例。
瞭解深度值
觀察到的實際幾何圖形和 2D 點 a
上的已知點 A
代表深度圖片中的相同點,也就是深度圖片提供的值
a
處的 API 等於投影到主要軸的 CA
長度。
這也稱為相機相對於 A
的 z 座標
來源:C
。使用 Depth API 時,請務必瞭解
深度值不是灰色 CA
本身的長度,而是 投影
我們很快就會深入探討
所以目前先概略介紹
忽略虛擬物件,並以圖表呈現深度資料
查看 Unity 的網誌文章 ,以便概略瞭解深度資料,以及如何使用這些資料遮蔽資料 虛擬映像檔此外,Unity 的 ARFoundation 範例 會呈現遮蓋的虛擬影像,以及以視覺化方式呈現深度資料。
您可以使用兩道算繪或個別物件的正向傳遞算繪,算繪遮蔽情形。每個方法的效率都取決於場景的複雜程度,以及其他應用程式特有的考量因素。
每個物件的正向傳遞轉譯
個別物件的正向循環算繪會決定該物件在其 Material 著色器中每個像素的遮蔽情形。如果像素看不見,就會遭到裁剪 (通常是透過 Alpha 混合),進而模擬使用者裝置上的遮蔽情形。
雙通道算繪
透過雙傳遞算繪,第一個傳遞會將所有虛擬內容算繪到中介緩衝區。第二張票證根據實際深度與虛擬場景深度之間的差異,將虛擬場景融入背景。這種方法不需要其他物件專屬的著色器工作,而且通常會產生比轉寄傳遞方法更加統一的結果。
擷取深度圖片的距離
如要將 Depth API 用於遮蔽虛擬物件或以視覺化方式呈現深度資料,請擷取深度圖片中的資訊,
Texture2D _depthTexture;
short[] _depthArray;
void UpdateEnvironmentDepthImage()
{
if (_occlusionManager &&
_occlusionManager.TryAcquireEnvironmentDepthCpuImage(out XRCpuImage image))
{
using (image)
{
UpdateRawImage(ref _depthTexture, image, TextureFormat.R16);
_depthWidth = image.width;
_depthHeight = image.height;
}
}
var byteBuffer = _depthTexture.GetRawTextureData();
Buffer.BlockCopy(byteBuffer, 0, _depthArray, 0, byteBuffer.Length);
}
// Obtain the depth value in meters at a normalized screen point.
public static float GetDepthFromUV(Vector2 uv, short[] depthArray)
{
int depthX = (int)(uv.x * (DepthWidth - 1));
int depthY = (int)(uv.y * (DepthHeight - 1));
return GetDepthFromXY(depthX, depthY, depthArray);
}
// Obtain the depth value in meters at the specified x, y location.
public static float GetDepthFromXY(int x, int y, short[] depthArray)
{
if (!Initialized)
{
return InvalidDepthValue;
}
if (x >= DepthWidth || x < 0 || y >= DepthHeight || y < 0)
{
return InvalidDepthValue;
}
var depthIndex = (y * DepthWidth) + x;
var depthInShort = depthArray[depthIndex];
var depthInMeters = depthInShort * MillimeterToMeter;
return depthInMeters;
}
後續步驟
- 使用 Raw Depth API 啟用更準確的感應功能。
- 歡迎查看 ARCore Depth Lab,瞭解存取深度資料的各種方式。