AR Foundation Android 앱에서 Depth 사용

Depth API는 기기의 카메라가 장면의 실제 물체의 크기와 모양을 파악하는 데 도움이 됩니다. 카메라를 사용하여 깊이 이미지 또는 깊이 맵을 만들어 앱에 AR 현실감을 더합니다. 깊이 이미지에서 제공하는 정보를 사용하여 가상 객체가 실제 객체 앞이나 뒤에 정확하게 표시되도록 하면 몰입도 높은 현실적인 사용자 경험을 제공할 수 있습니다.

깊이 정보는 움직임에서 계산되며, 비행시간(ToF) 센서와 같은 하드웨어 깊이 센서의 정보와 결합할 수 있습니다(가능한 경우). 기기가 Depth API를 지원하기 위해 ToF 센서가 필요하지는 않습니다.

기본 요건

계속하기 전에 기본 AR 개념ARCore 세션을 구성하는 방법을 이해해야 합니다.

앱을 Depth Required 또는 Depth Optional로 구성합니다 (Android만 해당).

AR 환경의 핵심 부분이 깊이에 의존하거나 깊이를 사용하는 앱 부분에 적절한 대체 옵션이 없기 때문에 앱에 Depth API 지원이 필요한 경우 Google Play 스토어에서 앱 배포를 Depth API를 지원하는 기기로 제한할 수 있습니다.

앱 만들기 Depth Required

Edit > Project Settings > XR Plug-in Management > ARCore로 이동합니다.

Depth는 기본적으로 Required로 설정됩니다.

앱 만들기 Depth Optional

  1. Edit > Project Settings > XR Plug-in Management > ARCore로 이동합니다.

  2. Depth 드롭다운 메뉴에서 Optional를 선택하여 앱을 Depth(깊이) 선택사항으로 설정합니다.

깊이 사용 설정

리소스를 절약하기 위해 ARCore는 기본적으로 Depth API를 사용 설정하지 않습니다. 지원되는 기기에서 깊이를 활용하려면 CameraARCameraBackground 구성요소를 사용하여 AR 카메라 게임 객체에 AROcclusionManager 구성요소를 수동으로 추가해야 합니다. 자세한 내용은 Unity 문서의 자동 폐쇄를 참고하세요.

새 ARCore 세션에서 다음과 같이 사용자의 기기가 깊이와 Depth API를 지원하는지 확인합니다.

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

깊이 이미지 획득

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

원시 CPU 이미지를 RawImage로 변환하면 유연성을 높일 수 있습니다. 이를 수행하는 방법의 예는 Unity의 ARFoundation 샘플을 참고하세요.

깊이 값 이해

관찰된 실제 도형의 점 A와 깊이 이미지에서 동일한 점을 나타내는 2D 점 a가 주어질 때 a에서 Depth API에 의해 제공되는 값은 주축에 투영된 CA의 길이와 같습니다. 이를 카메라 원점 C을 기준으로 A의 z 좌표라고도 합니다. Depth API를 사용할 때는 깊이 값이 광선 CA 자체의 길이가 아니라 투영이라는 점을 이해하는 것이 중요합니다.

가상 물체 가림 및 깊이 데이터 시각화

깊이 데이터에 대한 대략적인 개요와 이를 사용하여 가상 이미지를 가리는 방법은 Unity의 블로그 게시물을 참고하세요. 또한 Unity의 ARFoundation 샘플에서는 가려진 가상 이미지와 깊이 데이터 시각화를 보여줍니다.

2패스 렌더링 또는 객체별 전방 패스 렌더링을 사용하여 가림을 렌더링할 수 있습니다. 각 접근 방식의 효율성은 장면의 복잡성과 기타 앱별 고려사항에 따라 다릅니다.

객체별 전방 패스 렌더링

객체별 포워드 패스 렌더링은 재료 셰이더에서 객체의 각 픽셀의 가림을 결정합니다. 픽셀이 표시되지 않으면 일반적으로 알파 블렌딩을 통해 잘리므로 사용자 기기에서 가림 현상을 시뮬레이션합니다.

2패스 렌더링

2패스 렌더링을 사용하면 첫 번째 패스가 모든 가상 콘텐츠를 중간 버퍼로 렌더링합니다. 두 번째 패스는 실제 깊이와 가상 장면 깊이의 차이를 기반으로 가상 장면을 배경에 블렌딩합니다. 이 접근 방식은 추가적인 객체별 셰이더 작업이 필요하지 않으며 일반적으로 전방 패스 메서드보다 더 균일한 결과를 생성합니다.

깊이 이미지에서 거리 추출

가상 객체를 가리거나 깊이 데이터를 시각화하는 것 이외의 목적으로 Depth API를 사용하려면 깊이 이미지에서 정보를 추출하세요.

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

다음 단계

  • Raw Depth API를 사용하여 더 정확한 감지를 사용 설정합니다.
  • 깊이 데이터에 액세스하는 다양한 방법을 보여주는 ARCore Depth Lab을 확인하세요.