Utiliser la fonctionnalité Depth dans votre application Android AR Foundation

L'API Depth aide l'appareil photo d'un appareil à comprendre la taille et la forme des objets réels d'une scène. Elle utilise l'appareil photo pour créer des images de profondeur, ou cartes de profondeur, et ajoute ainsi un niveau de réalisme RA à vos applications. Vous pouvez utiliser les informations fournies par une représentation de profondeur pour faire apparaître des objets virtuels avec précision devant ou derrière des objets du monde réel, afin de proposer des expériences utilisateur immersives et réalistes.

Les informations de profondeur sont calculées à partir des mouvements et peuvent être combinées avec celles d'un capteur de profondeur matériel, tel qu'un capteur de temps de vol, le cas échéant. Un appareil n'a pas besoin de capteur ToF pour être compatible avec l'API Depth.

Conditions préalables

Assurez-vous de bien comprendre les concepts fondamentaux de la RA et de configurer une session ARCore avant de continuer.

Configurez votre application pour qu'elle soit Depth Required ou Depth Optional (Android uniquement).

Si votre application nécessite la compatibilité avec l'API Depth, soit parce qu'une partie essentielle de l'expérience de RA repose sur la profondeur, soit parce qu'il n'existe pas de solution de secours pour les parties de l'application qui utilisent la profondeur, vous pouvez choisir de limiter la distribution de votre application sur le Google Play Store aux appareils compatibles avec l'API Depth.

Définir votre application comme Depth Required

Accédez à Edit > Project Settings > XR Plug-in Management > ARCore.

Depth est défini par défaut sur Required.

Définir votre application comme Depth Optional

  1. Accédez à Edit > Project Settings > XR Plug-in Management > ARCore.

  2. Dans le menu déroulant Depth, sélectionnez Optional pour définir une application sur "Profondeur" (facultatif).

Activer la profondeur

Pour économiser des ressources, ARCore n'active pas l'API Depth par défaut. Pour profiter de la profondeur sur les appareils compatibles, vous devez ajouter manuellement le composant AROcclusionManager à l'objet de jeu Appareil photo RA avec les composants Camera et ARCameraBackground. Pour en savoir plus, consultez la section Occlusion automatique dans la documentation Unity.

Dans une nouvelle session ARCore, vérifiez si l'appareil d'un utilisateur est compatible avec l'API Depth et l'API Depth, comme suit:

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

Obtenir des représentations de profondeur

Obtenez la dernière image de profondeur d'environnement à partir de 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.
    }
}

Vous pouvez convertir l'image de processeur brute en RawImage pour plus de flexibilité. Pour savoir comment procéder, consultez les exemples ARFoundation d'Unity.

Comprendre les valeurs de profondeur

En se basant sur le point A sur la géométrie réelle observée et sur un point 2D a représentant le même point sur la représentation de profondeur, la valeur donnée par l'API Depth à a est égale à la longueur de CA projetée sur l'axe principal. Elle peut également être désignée par l'expression "coordonnée Z" de A par rapport à l'origine de la caméra (C). Lorsque vous utilisez l'API Depth, il est important de comprendre que les valeurs de profondeur ne correspondent pas à la longueur du rayon CA lui-même, mais à sa projection.

Occlure les objets virtuels et visualiser les données de profondeur

Consultez l'article de blog d'Unity pour une présentation générale des données de profondeur et de leur utilisation pour masquer des images virtuelles. De plus, les exemples ARFoundation d'Unity montrent comment masquer des images virtuelles et visualiser les données de profondeur.

Vous pouvez effectuer le rendu de l'occlusion à l'aide du rendu en deux passes ou par objet, avant l'affichage. L'efficacité de chaque approche dépend de la complexité de la scène et d'autres considérations propres à l'application.

Rendu par objet, transfert vers l'avant

Le rendu direct de l'objet détermine l'occlusion de chaque pixel de l'objet dans son nuanceur Material. Si les pixels ne sont pas visibles, ils sont rognés, généralement par le biais de la combinaison alpha, ce qui simule une occlusion sur l'appareil de l'utilisateur.

Rendu en deux passes

Avec le rendu en deux passages, la première passe affiche tout le contenu virtuel dans un tampon intermédiaire. La seconde passe mélange la scène virtuelle à l'arrière-plan en fonction de la différence entre la profondeur du monde réel et celle de la scène virtuelle. Cette approche ne nécessite aucun travail supplémentaire de nuanceur spécifique à l'objet et produit généralement des résultats plus uniformes que la méthode de transmission vers l'avant.

Extraire la distance d'une représentation de profondeur

Pour utiliser l'API Depth à d'autres fins que l'occlusion d'objets virtuels ou la visualisation de données de profondeur, extrayez des informations de la représentation de profondeur.

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

Et ensuite ?

  • Améliorez la précision de la détection avec l'API Raw Depth.
  • Rendez-vous sur l'atelier ARCore Depth Lab, qui présente différentes manières d'accéder aux données de profondeur.