Utilizzare la profondità nell'app per Android AR Foundation

L'API Profondità 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 appaiono con precisione davanti o dietro a oggetti del mondo reale, offrendo esperienze utente coinvolgenti e realistiche.

Le informazioni sulla profondità vengono calcolate in base al movimento e potrebbero essere combinate con le informazioni fornite da un sensore di profondità hardware, come un sensore del tempo di volo (ToF), se disponibile. Un dispositivo non ha bisogno di un sensore ToF per supportare l'API Profondità.

Prerequisiti

Assicurati di aver compreso i concetti fondamentali di AR e di configurare una sessione ARCore prima di procedere.

Configura la tua app in modo che sia Depth Required o Depth Optional (solo Android)

Se la tua app richiede il supporto dell'API Profondità, perché una parte fondamentale dell'esperienza AR si basa sulla profondità o perché non esiste un fallback funzionale per le parti dell'app che utilizzano la profondità, puoi scegliere di limitare la distribuzione della tua app nel Google Play Store ai dispositivi che supportano l'API depth.

Imposta la tua app come Depth Required

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

Depth è impostato su Required per impostazione predefinita.

Imposta la tua app come Depth Optional

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

  2. Dal menu a discesa Depth, seleziona Optional per impostare un'app su Profondità facoltativa.

Attiva profondità

Per risparmiare risorse, ARCore non abilita l'API depth per impostazione predefinita. Per sfruttare la profondità sui dispositivi supportati, devi aggiungere manualmente il componente AROcclusionManager all'oggetto di gioco Fotocamera AR con i componenti Camera e ARCameraBackground. Per ulteriori informazioni, consulta Occlusione automatica nella documentazione di Unity.

In una nuova sessione ARCore, verifica se il dispositivo di un utente supporta l'API depth e depth, come indicato di seguito:

// 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à

Scarica l'immagine più recente sulla profondità di ambiente da 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 non elaborata della CPU in un file RawImage per una maggiore flessibilità. Un esempio di come eseguire questa operazione è disponibile negli esempi di ARFoundation di Unity.

Comprendere i valori di profondità

Dato il punto A sulla geometria del mondo reale osservata e un punto 2D a che rappresenta lo stesso punto nell'immagine in profondità, il valore fornito dall'API depth all'indirizzo a è uguale alla lunghezza di CA proiettata sull'asse principale. Può anche essere indicata come la coordinata z di A rispetto all'origine della fotocamera C. Quando si utilizza l'API Profondità, è importante comprendere che i valori di profondità non sono la lunghezza del raggio CA stesso, ma la sua proiezione.

Occultare oggetti virtuali e visualizzare dati di profondità

Leggi il post del blog di Unity per una panoramica generale sui dati approfonditi e su come possono essere utilizzati per occultare le immagini virtuali. Inoltre, gli esempi di ARFoundation di Unity mostrano le immagini virtuali che nascondono e vengono visualizzati i dati sulla profondità.

Puoi eseguire il rendering dell'occlusione utilizzando il rendering in due passaggi o il rendering per oggetto con passaggio in avanti. L'efficienza di ogni approccio dipende dalla complessità della scena e da altre considerazioni specifiche dell'app.

Rendering passa in avanti per oggetto

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

Rendering in due passaggi

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

Estrai la distanza da un'immagine in profondità

Per utilizzare l'API Profondità per scopi diversi dall'occultare gli oggetti virtuali o la visualizzazione dei dati sulla 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

  • Consenti un monitoraggio più preciso con l'API Raw depth.
  • Dai un'occhiata al ARCore Insights Lab, che illustra diversi modi per accedere ai dati sulla profondità.