Menggunakan Depth di aplikasi Android AR Foundation

Depth API membantu kamera perangkat memahami ukuran dan bentuk objek nyata dalam adegan. Fitur ini menggunakan kamera untuk membuat gambar kedalaman, atau peta kedalaman, sehingga menambahkan lapisan realisme AR ke aplikasi Anda. Anda dapat menggunakan informasi yang diberikan oleh gambar kedalaman untuk membuat objek virtual secara akurat muncul di depan atau di belakang objek dunia nyata, yang memungkinkan pengalaman pengguna yang imersif dan realistis.

Informasi kedalaman dihitung dari gerakan dan dapat digabungkan dengan informasi dari sensor kedalaman hardware, seperti sensor waktu terbang (ToF), jika tersedia. Perangkat tidak memerlukan sensor ToF untuk mendukung Depth API.

Prasyarat

Pastikan Anda memahami konsep AR dasar dan cara mengonfigurasi sesi ARCore sebelum melanjutkan.

Konfigurasi aplikasi Anda menjadi Depth Required atau Depth Optional (khusus Android)

Jika aplikasi Anda memerlukan dukungan Depth API, baik karena bagian inti dari pengalaman AR bergantung pada kedalaman, atau karena tidak ada penggantian halus untuk bagian aplikasi yang menggunakan kedalaman, Anda dapat memilih untuk membatasi distribusi aplikasi di Google Play Store ke perangkat yang mendukung Depth API.

Jadikan aplikasi Anda Depth Required

Buka Edit > Project Settings > XR Plug-in Management > ARCore

Depth ditetapkan ke Required secara default.

Jadikan aplikasi Anda Depth Optional

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

  2. Dari menu drop-down Depth, pilih Optional untuk menyetel aplikasi ke Depth opsional.

Aktifkan Kedalaman

Untuk menghemat resource, ARCore tidak mengaktifkan Depth API secara default. Untuk memanfaatkan kedalaman pada perangkat yang didukung, Anda harus menambahkan komponen AROcclusionManager secara manual ke objek game Kamera AR dengan komponen Camera dan ARCameraBackground. Lihat Oklusi otomatis di dokumentasi Unity untuk mengetahui informasi selengkapnya.

Dalam sesi ARCore baru, periksa apakah perangkat pengguna mendukung kedalaman dan Depth API, sebagai berikut:

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

Mendapatkan gambar kedalaman

Mendapatkan gambar kedalaman lingkungan terbaru dari 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.
    }
}

Anda dapat mengonversi image CPU mentah menjadi RawImage untuk fleksibilitas yang lebih besar. Contoh caranya dapat ditemukan di contoh ARFoundation Unity.

Memahami nilai kedalaman

Titik A yang ditentukan pada geometri dunia nyata yang diamati dan titik 2D a mewakili titik yang sama pada gambar kedalaman, nilai yang diberikan oleh Depth API pada a sama dengan panjang CA yang diproyeksikan ke sumbu utama. Ini juga dapat disebut sebagai koordinat z A relatif terhadap C asal kamera. Saat menggunakan Depth API, pahami bahwa nilai kedalaman bukanlah panjang CA sinar itu sendiri, tetapi proyeksi sinarnya.

Menutup objek virtual dan memvisualisasikan data kedalaman

Lihat postingan blog Unity untuk ringkasan umum tentang data kedalaman dan cara data tersebut dapat digunakan untuk menutupi gambar virtual. Selain itu, contoh ARFoundation Unity menunjukkan pemblokiran gambar virtual dan visualisasi data kedalaman.

Anda dapat merender oklusi menggunakan rendering dua jalur atau rendering maju per objek. Efisiensi setiap pendekatan bergantung pada kompleksitas adegan dan pertimbangan khusus aplikasi lainnya.

Rendering maju per objek

Rendering maju per objek menentukan oklusi setiap piksel objek dalam shader materialnya. Jika piksel tidak terlihat, piksel akan dipotong, biasanya melalui pencampuran alfa, sehingga menyimulasikan oklusi pada perangkat pengguna.

Rendering dua tahap

Dengan rendering dua-pass, pass pertama merender semua konten virtual ke buffer perantara. Tahap kedua memadukan adegan virtual dengan latar belakang berdasarkan perbedaan antara kedalaman dunia nyata dengan kedalaman adegan virtual. Pendekatan ini tidak memerlukan pekerjaan shader khusus objek tambahan dan umumnya menghasilkan hasil yang tampak lebih seragam daripada metode forward-pass.

Mengekstrak jarak dari gambar kedalaman

Agar dapat menggunakan Depth API untuk tujuan selain menutupi objek virtual atau memvisualisasikan data kedalaman, ekstrak informasi dari gambar kedalaman.

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

Langkah selanjutnya

  • Aktifkan deteksi yang lebih akurat dengan Raw Depth API.
  • Lihat ARCore Depth Lab, yang menunjukkan berbagai cara untuk mengakses data kedalaman.