Utilizzare la profondità nell'app per Android AR Foundation

L'API Depth aiuta la fotocamera di un dispositivo a comprendere le dimensioni e la forma degli oggetti reali in una scena. Utilizza la fotocamera per creare immagini di profondità o mappe di profondità, aggiungendo così un livello di realismo AR alle tue app. Puoi utilizzare le informazioni fornite da un'immagine di profondità per fare in modo che gli oggetti virtuali appaiano accuratamente davanti o dietro oggetti del mondo reale, consentendo un'esperienza utente immersiva e realistica.

Le informazioni sulla profondità vengono calcolate in base al movimento e possono essere combinate con quelle provenienti da un sensore di profondità hardware, ad esempio un sensore del tempo di volo (ToF), se disponibile. Un dispositivo non ha bisogno di un sensore ToF per supportare l'API Depth.

Prerequisiti

Assicurati di comprendere i concetti fondamentali della realtà aumentata e su come configurare una sessione ARCore prima di procedere.

Configura l'app in modo che sia Depth Required o Depth Optional (solo Android)

Se la tua app richiede il supporto dell'API Depth, o perché una parte fondamentale dell'esperienza AR si basa sulla profondità o perché non esiste un alternativo trucco per le parti dell'app che usano la profondità, puoi scegli di limitare la distribuzione della tua app nel Google Play Store a dispositivi che supportano l'API Depth.

Rendi la tua app Depth Required

Vai a Edit > Project Settings > XR Plug-in Management > ARCore.

Depth è impostato su Required per impostazione predefinita.

Rendi la tua app Depth Optional

  1. Vai a Edit > Project Settings > XR Plug-in Management > ARCore.

  2. Dal menu a discesa Depth, seleziona Optional per impostare l'opzione "Profondità" facoltativa.

Attiva profondità

Per risparmiare risorse, ARCore non abilita l'API Depth per impostazione predefinita. Per la profondità sui dispositivi supportati, devi aggiungere manualmente il valore AROcclusionManager all'oggetto di gioco AR Camera con Camera e ARCameraBackground. Consulta Copertura automatica nella documentazione di Unity.

In una nuova sessione ARCore, verifica se è presente il dispositivo dell'utente supporta depth e l'API Depth, come segue:

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

Acquisisci immagini di profondità

Recupera l'ultima immagine di profondità dell'ambiente dal 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.
    }
}

Puoi convertire l'immagine CPU non elaborata in un file RawImage per una maggiore flessibilità. Un consulta gli esempi di ARFoundation di Unity.

Informazioni sui valori di profondità

Dato il punto A sulla geometria reale osservata e un punto 2D a che rappresenta lo stesso punto nell'immagine di profondità, il valore specificato dal valore L'API in a è uguale alla lunghezza di CA prevista sull'asse principale. È anche indicata come la coordinata z di A rispetto alla fotocamera origine C. Quando lavori con l'API Depth, è importante capire che i valori di profondità non sono la lunghezza del raggio CA stesso, ma la proiezione da questa parte.

Occlude oggetti virtuali e visualizza dati di profondità

Leggi il post del blog di Unity per una panoramica di alto livello dei dati di profondità e di come possono essere utilizzati per nascondere immagini virtuali. Inoltre, i modelli Esempi di ARFoundation dimostrare l'occlusione di immagini virtuali e la visualizzazione di dati di profondità.

Puoi visualizzare la copertura utilizzando il rendering a due passaggi o il rendering in avanti per oggetto. L'efficienza di ciascun approccio dipende dalla complessità della scena e da altre considerazioni specifiche dell'app.

Rendering con progresso in avanti per oggetto

Il rendering in avanti per singolo oggetto determina l'occlusione di ogni pixel dell'oggetto nel suo tonalità di materiale. Se i pixel non sono visibili, vengono ritagliati, in genere tramite una combinazione alfa, simulando così l'occlusione sul dispositivo dell'utente.

Rendering a due passaggi

Con il rendering a due passaggi, il primo passaggio esegue il rendering di tutti i contenuti virtuali in un buffer intermedio. Il secondo passaggio unisce la scena virtuale con lo sfondo in base alla differenza tra la profondità del mondo reale e quella della scena virtuale. Questo approccio non richiede alcun lavoro aggiuntivo sullo screenr specifico per gli oggetti e generalmente produce risultati più uniformi rispetto al metodo del progresso in avanti.

Estrai la distanza da un'immagine di profondità

Per utilizzare l'API Depth per scopi diversi dall'occultamento di oggetti virtuali o dalla visualizzazione di dati di profondità, estrai informazioni dall'immagine di profondità.

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

Passaggi successivi

  • Abilita un rilevamento più preciso con l'API Raw Depth.
  • Dai un'occhiata al ARCore Depth Lab, che illustra diversi modi per accedere a dati di profondità.