Używanie głębi w aplikacji AR Foundation na Androida

Depth API pomaga aparatowi urządzenia rozpoznać rozmiar i kształt rzeczywistych obiektów w scenie. Używa aparatu do tworzenia zdjęć głębi, czyli map głębi, dzięki czemu Twoje aplikacje zyskują dodatkową warstwę realizmu AR. Na podstawie informacji uzyskanych dzięki obrazowi głębi możesz precyzyjnie wyświetlać wirtualne obiekty przed lub za rzeczywistymi obiektami, co zapewnia użytkownikom realistyczne i ciekawe wrażenia.

Informacje o głębi są obliczane na podstawie ruchu i mogą być łączone z informacjami ze sprzętowego czujnika głębokości, np. z czujnika czasu lotu (ToF), jeśli jest dostępny. Urządzenie nie potrzebuje czujnika ToF do obsługi interfejsu Depth API.

Wymagania wstępne

Upewnij się, że znasz podstawowe pojęcia związane z AR. i dowiedz się, jak skonfigurować sesję ARCore, zanim przejdziesz dalej.

Skonfiguruj aplikację jako Depth Required lub Depth Optional (tylko Android)

Jeśli Twoja aplikacja wymaga obsługi Depth API, że podstawowa część funkcji AR zależy od głębi lub dlatego, nie można zastosować płynnego wyglądu do tych części aplikacji, które wymagają głębi. ograniczyć rozpowszechnianie aplikacji w Sklepie Google Play do urządzeniach obsługujących Depth API.

Zmień wersję aplikacji na Depth Required

Wejdź na Edit > Project Settings > XR Plug-in Management > ARCore.

Depth ma domyślną wartość Required.

Zmień wersję aplikacji na Depth Optional

  1. Wejdź na Edit > Project Settings > XR Plug-in Management > ARCore.

  2. Z menu Depth wybierz Optional. aby ustawić w aplikacji opcję Głębia opcjonalna.

Włącz głębię

Aby oszczędzać zasoby, ARCore domyślnie nie włącza interfejsu Depth API. Do zrobienia na obsługiwanych urządzeniach wymaga głębi, musisz ręcznie dodać AROcclusionManager do obiektu gry Aparat AR za pomocą tagów Camera i Komponent ARCameraBackground. Zobacz Automatyczne przesłonięcie w dokumentacji Unity.

W nowej sesji ARCore sprawdź, czy urządzenie użytkownika obsługuje głębię kolorów i interfejs Depth API w następujący sposób:

// 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.
}

Uzyskiwanie zdjęć głębi

Pobierz najnowszy obraz głębi środowiska ze strony 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.
    }
}

Możesz przekonwertować nieprzetworzony obraz procesora na format RawImage , co zapewnia większą elastyczność. An jak to zrobić, znajdziesz w przykładach ARFoundation w witrynie Unity.

Poznawanie wartości głębokości

Podany punkt A na zaobserwowanej geometrii rzeczywistej i punkt 2D: a reprezentujący ten sam punkt na zdjęciu głębi. Wartość podana jako Głębia Interfejs API w miejscu a ma długość CA przewidywanej na oś podmiotu zabezpieczeń. Może też być nazywana współrzędną Z zmiennej A względem kamery. miejsce wylotu: C. Podczas pracy z Depth API należy pamiętać, że wartości głębi to nie długość promienia CA, ale odwzorowanie .

Blokuj wirtualne obiekty i wizualizuj dane o głębi

Przeczytaj posta na blogu Unity który zawiera ogólny przegląd szczegółowych danych i sposobów ich wykorzystywania wirtualnych obrazów. Dodatkowo Przykłady ARFoundation jak pomijać wirtualne obrazy i wizualizować dane głębi.

Możesz wyrenderować przesłanianie za pomocą renderowania dwuetapowego lub renderowania z przebiegiem do przodu dla poszczególnych obiektów. Skuteczność każdego podejścia zależy od złożoności sceny i innych czynników związanych z aplikacją.

Na obiekt, renderowanie do przodu

Renderowanie z przebiegiem do przodu określa przesłonięcie każdego piksela obiektu w trybie cieniowania materiału. Jeśli piksele nie są widoczne, są przycinane, zwykle przez mieszanie alfa, w celu symulowania przesłaniania na urządzeniu użytkownika.

Renderowanie dwuprzebiegowe

W przypadku renderowania dwuprzebiegowego pierwsze przejście renderuje całą zawartość wirtualną w buforze pośrednim. Drugi etap polega na połączeniu sceny wirtualnej z tłem na podstawie różnicy między głębią świata a głębią sceny wirtualnej. Ta metoda nie wymaga dodatkowej pracy z programem cieniowania dla konkretnego obiektu i zwykle daje bardziej jednolite wyniki niż metoda oparta na przebiegu do przodu.

Wyodrębnij odległość z obrazu głębi

Aby używać interfejsu Depth API do celów innych niż zakrywanie wirtualnych obiektów lub wizualizowanie danych głębi, wyodrębnij informacje z obrazu głębi.

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;
}

Co dalej?

  • Włącz dokładniejsze wykrywanie za pomocą interfejsu Raw Depth API.
  • Wypróbuj ARCore Depth Lab, aby dowiedzieć się, jak uzyskać dostęp do szczegółowych danych.