La API de Depth ayuda a la cámara de un dispositivo a comprender el tamaño y la forma de los objetos reales en una escena. Usa la cámara para crear imágenes de profundidad o mapas de profundidad, lo que agrega una capa de realismo de RA a tus apps. Puedes usar la información que proporciona una imagen de profundidad para hacer que los objetos virtuales aparezcan con precisión delante o detrás de objetos del mundo real, lo que permite experiencias del usuario inmersivas y realistas.
La información de profundidad se calcula a partir del movimiento y se puede combinar con la información de un sensor de profundidad de hardware, como un sensor de tiempo de vuelo (ToF), si está disponible. Un dispositivo no necesita un sensor ToF para admitir la API de Depth.
Requisitos previos
Asegúrate de comprender los conceptos fundamentales de la RA y cómo configurar una sesión de ARCore antes de continuar.
Configura tu app para que sea Depth Required o Depth Optional (solo para Android)
Si tu app requiere compatibilidad con la API de Depth, ya sea porque una parte fundamental de la experiencia de RA depende de la profundidad o porque no hay un resguardo elegante para las partes de la app que usan profundidad, puedes restringir la distribución de tu app en Google Play Store a dispositivos que admitan la API de Depth.
Crea tu app Depth Required
Navega a Edit > Project Settings > XR Plug-in Management > ARCore.
Depth se establece en Required de forma predeterminada.
Crea tu app Depth Optional
Navega a Edit > Project Settings > XR Plug-in Management > ARCore.
En el menú desplegable Depth, selecciona Optional para establecer una app como opcional para la profundidad.
Habilita la profundidad
Para ahorrar recursos, ARCore no habilita la API de Depth de forma predeterminada. Para aprovechar la profundidad en dispositivos compatibles, debes agregar manualmente el componente AROcclusionManager
al objeto de juego Cámara de RA con los componentes Camera
y ARCameraBackground
. Consulta Oclusión automática en la documentación de Unity para obtener más información.
En una nueva sesión de ARCore, verifica si el dispositivo de un usuario admite la profundidad y la API de Depth de la siguiente manera:
// 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.
}
Cómo adquirir imágenes de profundidad
Obtén la imagen de profundidad del entorno más reciente 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.
}
}
Puedes convertir la imagen sin procesar de la CPU en una RawImage
para obtener mayor flexibilidad. Puedes encontrar un ejemplo de cómo hacerlo en los ejemplos de ARFoundation de Unity.
Comprende los valores de profundidad
Dado el punto A
en la geometría observada del mundo real y un punto 2D a
que representa el mismo punto en la imagen de profundidad, el valor que proporciona la API de Depth en a
es igual a la longitud de CA
proyectada en el eje principal.
También se puede denominar la coordenada z de A
en relación con el origen de la cámara C
. Cuando se trabaja con la API de Depth, es importante comprender que los valores de profundidad no son la longitud del rayo CA
en sí, sino su proyección.
Oculta objetos virtuales y visualiza datos de profundidad
Consulta la entrada de blog de Unity para obtener una descripción general de alto nivel de los datos de profundidad y cómo se pueden usar para ocluir imágenes virtuales. Además, los ejemplos de ARFoundation de Unity muestran la oclusión de imágenes virtuales y la visualización de datos de profundidad.
Puedes renderizar la oclusión con renderización de dos pases o renderización de paso directo por objeto. La eficiencia de cada enfoque depende de la complejidad de la escena y de otras consideraciones específicas de la app.
Renderización de paso directo por objeto
La renderización de paso directo por objeto determina la oclusión de cada píxel del objeto en su sombreador de material. Si los píxeles no son visibles, se recortan, generalmente, mediante una combinación alfa, con lo que se simula la oclusión en el dispositivo del usuario.
Renderización de dos pases
Con la renderización de dos pases, el primer pase renderiza todo el contenido virtual en un búfer intermedio. El segundo pase combina la escena virtual con el fondo en función de la diferencia entre la profundidad del mundo real y la profundidad de la escena virtual. Este enfoque no requiere trabajo adicional de sombreador específico del objeto y, por lo general, produce resultados más uniformes que el método de pase hacia delante.
Cómo extraer la distancia de una imagen de profundidad
Si quieres usar la API de Depth con otros fines que no sean ocultar objetos virtuales ni visualizar datos de profundidad, extrae información de la imagen de profundidad.
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;
}
¿Qué sigue?
- Habilita sensores más precisos con la API de Raw Depth.
- Consulta el ARCore Depth Lab, que muestra diferentes formas de acceder a los datos de profundidad.