„Tiefe“ in der AR Foundation Android-App verwenden

Die Depth API hilft der Kamera eines Geräts, die Größe und Form der realen Objekte in einer Szene zu erkennen. Dabei wird mithilfe der Kamera Tiefenbilder oder Tiefenkarten erstellt. So erhält deine App AR-realistische Erlebnisse. Mithilfe der Informationen eines Tiefenbildes können Sie virtuelle Objekte vor oder hinter realen Objekten exakt anzeigen lassen. So entstehen immersive und realistische User Experiences.

Tiefeninformationen werden aus Bewegung berechnet und können mit Informationen von einem Hardware-Tiefensensor wie einem Flugzeitsensor (ToF) kombiniert werden, sofern verfügbar. Geräte benötigen zur Unterstützung der Depth API keinen ToF-Sensor.

Vorbereitung

Machen Sie sich mit den grundlegenden AR-Konzepten vertraut. und Konfigurieren einer ARCore-Sitzung beschrieben, bevor du fortfährst.

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

Wenn Ihre App Depth API-Unterstützung benötigt: Entweder, weil ein wesentlicher Bestandteil des AR-Erlebnisses auf Tiefe beruht, oder weil Es gibt kein anmutiges Fallback für die Teile der App, die Tiefe nutzen. den Vertrieb Ihrer App im Google Play Store auf Geräte, die die Depth API unterstützen.

App zu Depth Required machen

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

Depth ist standardmäßig auf Required festgelegt.

App zu Depth Optional machen

  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 „Tiefe“ optional festzulegen.

Tiefe aktivieren

Um Ressourcen zu sparen, wird die Depth API in ARCore nicht standardmäßig aktiviert. Zu nehmen Vorteil der Tiefe auf unterstützten Geräten haben, müssen Sie die Methode AROcclusionManager Komponente zum Spielobjekt AR Camera mit Camera und ARCameraBackground-Komponente Weitere Informationen finden Sie unter Automatische Verdeckung finden Sie in der Unity-Dokumentation.

Prüfen Sie in einer neuen ARCore-Sitzung, ob eine unterstützt das Gerät des Nutzers wie folgt Depth und die 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.
}

Tiefenaufnahmen aufnehmen

Holen Sie sich das neueste Umgebungstiefen-Image aus dem 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.
    }
}

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

Tiefenwerte

Angegebener Punkt A in der beobachteten realen Geometrie und ein 2D-Punkt a denselben Punkt im Tiefenbild darstellt, wird der Wert, der durch das Die API in a entspricht der Länge von CA, die auf die Hauptachse projiziert wird. Dies kann auch als Z-Koordinate von A relativ zur Kamera bezeichnet werden. Ursprung C. Wenn Sie mit der Depth API arbeiten, sollten Sie wissen, Die Tiefenwerte entsprechen nicht der Länge des Strahls CA selbst, sondern der Projektion. davon.

Virtuelle Objekte ausblenden und Tiefendaten visualisieren

Dann lesen Sie den Blogpost von Unity. finden Sie einen allgemeinen Überblick über tiefe Daten und wie diese zur Verdeckung virtuelle Bilder. Außerdem hat Unity ARFoundation-Beispiele das Verdecken virtueller Bilder und das Visualisieren von Tiefendaten demonstrieren.

Sie können Verdeckungen mit 2-Pass-Rendering oder pro Objekt mit Vorwärtsdurchlauf rendern. Die Effizienz der einzelnen Ansätze hängt von der Komplexität der Szene und weiteren anwendungsspezifischen Aspekten ab.

Vorwärtsdurchlauf-Rendering pro Objekt

Beim Vorwärtsdurchlauf-Rendering wird pro Objekt 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-Überblendung, um eine Verdeckung auf dem Gerät des Nutzers zu simulieren.

Rendering mit zwei Durchgängen

Beim Rendering mit zwei Durchgängen rendert der erste Durchlauf den gesamten virtuellen Inhalt in einem Zwischenpuffer. Beim zweiten Pass wird die virtuelle Szene basierend auf dem Unterschied zwischen der realen und der virtuellen Szenentiefe mit dem Hintergrund verschmelzen lassen. Dieser Ansatz erfordert keine zusätzliche objektspezifische Shader-Arbeit und liefert im Allgemeinen einheitlichere Ergebnisse als die Vorwärtspass-Methode.

Entfernung aus einem Tiefenbild extrahieren

Wenn Sie die Depth API zu anderen Zwecken als zum Verdecken 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

  • Ermöglichen Sie eine genauere Erkennung mit der Raw Depth API.
  • Im ARCore Depth Lab werden verschiedene Möglichkeiten für den Zugriff auf detaillierte Daten vorgestellt.