Die Depth API hilft der Kamera eines Geräts, die Größe und Form der realen Objekte in einer Szene zu ermitteln. Dabei werden mit der Kamera Tiefenbilder oder Tiefenkarten erstellt, um Ihren Apps einen realistischen AR-Look zu verleihen. Mithilfe der Informationen aus einem Tiefenbild können Sie virtuelle Objekte präzise vor oder hinter realen Objekten erscheinen lassen, was für ein immersives und realistisches Nutzererlebnis sorgt.
Die Tiefeninformationen werden anhand von Bewegungen berechnet und können mit Informationen von einem Hardware-Tiefensensor wie einem Time-of-Flight-Sensor (ToF-Sensor) kombiniert werden, sofern verfügbar. Ein Gerät benötigt keinen ToF-Sensor, um die Depth API zu unterstützen.
Vorbereitung
Machen Sie sich mit den grundlegenden AR-Konzepten und der Konfiguration einer ARCore-Sitzung vertraut, bevor Sie fortfahren.
App als Depth Required oder Depth Optional konfigurieren (nur Android)
Wenn für Ihre App die Depth API erforderlich ist, weil ein zentraler Teil der AR-Funktionen auf der Tiefenwahrnehmung basiert oder weil es keinen reibungslosen Fallback für die Teile der App gibt, die die Tiefenwahrnehmung nutzen, können Sie die Bereitstellung Ihrer App im Google Play Store auf Geräte beschränken, die die Depth API unterstützen.
App Depth Required
Rufen Sie Edit > Project Settings > XR Plug-in Management > ARCore auf.
Depth ist standardmäßig auf Required festgelegt.
App Depth Optional
Rufen Sie Edit > Project Settings > XR Plug-in Management > ARCore auf.
Wählen Sie im Drop-down-Menü Depth die Option Optional aus, um für eine App „Tiefe optional“ festzulegen.
Tiefe aktivieren
Aus Ressourcengründen wird die Depth API in ARCore standardmäßig nicht aktiviert. Wenn Sie die Tiefenschärfe auf unterstützten Geräten nutzen möchten, müssen Sie dem Spielobjekt AR-Kamera mit den Komponenten Camera
und ARCameraBackground
manuell die Komponente AROcclusionManager
hinzufügen. Weitere Informationen finden Sie in der Unity-Dokumentation unter Automatische Okklusion.
Prüfen Sie in einer neuen ARCore-Sitzung, ob das Gerät eines Nutzers die Tiefenerfassung und die Depth API unterstützt. Gehen Sie dazu so vor:
// 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.
}
Tiefenbilder aufnehmen
Rufen Sie das aktuelle Bild mit der Umgebungstiefe von der AROcclusionManager
ab.
// 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.
}
}
Sie können das Roh-CPU-Image in ein RawImage
konvertieren, um mehr Flexibilität zu erhalten. Ein Beispiel dazu finden Sie in den ARFoundation-Beispielen von Unity.
Tiefenwerte
Angenommen, es gibt den Punkt A
in der beobachteten realen Geometrie und den 2D-Punkt a
, der denselben Punkt im Tiefenbild darstellt. Der von der Depth API unter a
angegebene Wert entspricht der Länge von CA
, projiziert auf die Hauptachse.
Dies kann auch als die Z‑Koordinate von A
bezogen auf den Kameraursprung C
bezeichnet werden. Bei der Arbeit mit der Depth API ist es wichtig zu wissen, dass die Tiefenwerte nicht die Länge des Strahls CA
selbst, sondern seine Projektion sind.
Virtuelle Objekte verdecken und Tiefendaten visualisieren
Im Blogpost von Unity finden Sie eine allgemeine Übersicht über Tiefendaten und wie sie verwendet werden können, um virtuelle Bilder zu verdecken. Außerdem zeigen die ARFoundation-Beispiele von Unity, wie virtuelle Bilder verdeckt und Tiefendaten visualisiert werden.
Sie können Occlusion mit dem zweistufigen Rendering oder dem objektspezifischen Forward-Pass-Rendering rendern. Die Effizienz der einzelnen Ansätze hängt von der Komplexität der Szene und anderen app-spezifischen Aspekten ab.
Objektbasiertes Forward-Pass-Rendering
Beim objektbasierten Forward-Pass-Rendering wird die Okklusion jedes Pixels des Objekts in seinem Material-Shader bestimmt. Wenn die Pixel nicht sichtbar sind, werden sie normalerweise durch Alpha-Blending zugeschnitten, um eine Okklusion auf dem Gerät des Nutzers zu simulieren.
Zwei-Pass-Rendering
Beim Two-Pass-Rendering werden beim ersten Durchlauf alle virtuellen Inhalte in einen Zwischenpuffer gerendert. Beim zweiten Durchlauf wird die virtuelle Szene basierend auf der Differenz zwischen der Tiefe der realen Welt und der Tiefe der virtuellen Szene in den Hintergrund eingeblendet. Dieser Ansatz erfordert keine zusätzlichen objektspezifischen Shader-Arbeiten und führt im Allgemeinen zu einheitlicheren Ergebnissen als die Forward-Pass-Methode.
Entfernung aus einem Tiefenbild extrahieren
Wenn Sie die Depth API nicht nur zum Ausblenden virtueller Objekte oder zum Visualisieren von Tiefendaten verwenden möchten, extrahieren Sie Informationen aus dem Tiefenbild.
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;
}
Weiteres Vorgehen
- Mit der Raw Depth API können Sie eine genauere Erfassung ermöglichen.
- Im ARCore Depth Lab werden verschiedene Möglichkeiten zum Zugriff auf Tiefendaten veranschaulicht.