„Tiefe“ in der AR Foundation Android-App verwenden

Mithilfe der Depth API kann die Kamera eines Geräts die Größe und Form der realen Objekte in einer Szene erkennen. Dabei werden mithilfe der Kamera Tiefenbilder bzw. Tiefenkarten erstellt und deine Apps um AR-Realismus ergänzt. Mithilfe der Informationen aus einem Tiefenbild können Sie virtuelle Objekte vor oder hinter realen Objekten genau darstellen lassen und so eine immersive und realistische User Experience schaffen.

Tiefeninformationen werden aus Bewegungen berechnet und können mit Daten von einem Hardware-Tiefensensor wie einem Flugzeitsensor (ToF) kombiniert werden, sofern verfügbar. Geräte benötigen keinen ToF-Sensor, um die Depth API zu unterstützen.

Voraussetzungen

Machen Sie sich mit den grundlegenden AR-Konzepten und zur Konfiguration einer ARCore-Sitzung vertraut, bevor Sie fortfahren.

Konfiguriere deine App als Depth Required oder Depth Optional (nur Android)

Wenn für Ihre App Unterstützung für die Depth API erforderlich ist, weil ein wesentlicher Bestandteil der AR-Erfahrung auf der Tiefe basiert oder es kein ordnungsgemäßes Fallback für die Teile der App gibt, die Tiefendaten verwenden, können Sie den Vertrieb Ihrer App im Google Play Store auf Geräte beschränken, die die Depth API unterstützen.

App „Depth Required“ einrichten

Rufen Sie Edit > Project Settings > XR Plug-in Management > ARCore auf.

Depth ist standardmäßig auf Required festgelegt.

App „Depth Optional“ einrichten

  1. Rufen Sie Edit > Project Settings > XR Plug-in Management > ARCore auf.

  2. Wählen Sie im Drop-down-Menü Depth die Option Optional aus, um für eine App die Option „Tiefe“ (optional) festzulegen.

Tiefe aktivieren

Die Depth API wird in ARCore nicht standardmäßig aktiviert, um Ressourcen zu sparen. Damit Sie die Tiefenwirkung auf unterstützten Geräten nutzen können, müssen Sie die Komponente AROcclusionManager manuell mit den Komponenten Camera und ARCameraBackground dem AR-Kamera-Spielobjekt hinzufügen. Weitere Informationen finden Sie in der Unity-Dokumentation unter Automatische Verdeckung.

So prüfen Sie in einer neuen ARCore-Sitzung, ob das Gerät eines Nutzers die Tiefenfunktion und die Depth API unterstützt:

// 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 neueste Image der Umgebungstiefe aus dem 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.
    }
}

Für mehr Flexibilität können Sie das CPU-Rohbild in ein RawImage konvertieren. Ein Beispiel dafür finden Sie in den ARFoundation-Beispielen von Unity.

Tiefenwerte verstehen

Bei einem Punkt A auf der beobachteten realen Geometrie und einem 2D-Punkt a, der denselben Punkt im Tiefenbild darstellt, entspricht der von der Tiefen-API bei a angegebene Wert der Länge von CA, die auf die Hauptachse projiziert wird. Dies kann auch als Z-Koordinate von A relativ zum Kameraursprung C bezeichnet werden. Wenn Sie mit der Depth API arbeiten, ist es wichtig zu verstehen, dass die Tiefenwerte nicht der Länge des CAstrahls selbst, sondern der Projektion des Strahls entsprechen.

Virtuelle Objekte verdecken und Tiefendaten visualisieren

Im Blogpost von Unity finden Sie einen allgemeinen Überblick über Tiefendaten und darüber, wie Sie damit virtuelle Bilder verdecken können. Außerdem zeigen die ARFoundation-Beispiele von Unity das Verdecken virtueller Bilder und die Visualisierung von Tiefendaten.

Sie können Verdeckungen mit Zwei-Durchlauf-Rendering oder Vorwärtsdurchlauf pro Objekt rendern. Die Effizienz der einzelnen Ansätze hängt von der Komplexität der Szene und anderen anwendungsspezifischen Überlegungen ab.

Rendering pro Objekt, Vorwärtsdurchlauf

Beim Vorwärtsdurchlauf-Rendering pro Objekt wird die Verdeckung jedes Pixels des Objekts in seinem Material-Shader bestimmt. Wenn die Pixel nicht sichtbar sind, werden sie abgeschnitten, in der Regel durch Alpha-Mischung, wodurch eine Verdeckung auf dem Gerät des Nutzers simuliert wird.

Rendering mit zwei Durchgängen

Beim Rendern mit zwei Durchgängen werden mit der ersten Übergabe alle virtuellen Inhalte in einem Zwischenpuffer gerendert. Beim zweiten Durchlauf wird die virtuelle Szene basierend auf dem Unterschied zwischen der tatsächlichen Tiefe und der virtuellen Szene mit dem Hintergrund verschmelzen. Dieser Ansatz erfordert keine zusätzliche objektspezifische Shader-Arbeit und erzeugt im Allgemeinen einheitlichere Ergebnisse als die Forward-Pass-Methode.

Entfernung aus einem Tiefenbild extrahieren

Wenn Sie die Depth API nicht zum Verdecken virtueller Objekte oder zur Visualisierung 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;
}

Nächste Schritte

  • Verwenden Sie die Raw Depth API, um eine genauere Erkennung zu ermöglichen.
  • Im ARCore Depth Lab werden verschiedene Möglichkeiten für den Zugriff auf Tiefendaten vorgestellt.