ใช้ความลึกในแอป AR Foundation สำหรับ Android

Depth API ช่วยให้กล้องของอุปกรณ์ทำความเข้าใจขนาดและรูปร่างของวัตถุจริงในฉาก ซึ่งจะใช้กล้องเพื่อสร้างรูปภาพที่มีความลึกหรือแผนที่ที่มีความลึก ซึ่งจะช่วยเพิ่มความสมจริงของ AR ลงในแอป คุณสามารถใช้ข้อมูลที่ได้จากรูปภาพที่มีความลึกเพื่อทำให้วัตถุเสมือนจริงปรากฏด้านหน้าหรือด้านหลังวัตถุในโลกจริงอย่างแม่นยำ ซึ่งช่วยให้ผู้ใช้ได้รับประสบการณ์ที่สมจริงและสมจริง

ข้อมูลความลึกจะคำนวณจากการเคลื่อนไหวและอาจรวมกับข้อมูลจากเซ็นเซอร์วัดความลึกของฮาร์ดแวร์ เช่น เซ็นเซอร์เวลาการบิน (ToF) (หากมี) อุปกรณ์ไม่ต้องใช้เซ็นเซอร์ ToF เพื่อรองรับ Depth API

ข้อกำหนดเบื้องต้น

ตรวจสอบว่าคุณเข้าใจแนวคิด AR พื้นฐาน และวิธีกำหนดค่าเซสชัน ARCore ก่อนดำเนินการต่อ

กำหนดค่าแอปให้เป็น Depth Required หรือ Depth Optional (Android เท่านั้น)

หากแอปต้องใช้การรองรับ Depth API ไม่ว่าจะเพราะส่วนหลักของประสบการณ์ AR ต้องอาศัยความลึก หรือเพราะไม่มีส่วนสำรองที่สวยงามสำหรับส่วนต่างๆ ของแอปที่ใช้ความลึก คุณอาจเลือกที่จะจำกัดการเผยแพร่แอปใน Google Play Store ให้เผยแพร่เฉพาะอุปกรณ์ที่รองรับ 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 เพื่อกำหนดให้แอปเป็นแบบความลึกที่ไม่บังคับ

เปิดใช้ความลึก

ARCore จะไม่เปิดใช้ Depth API โดยค่าเริ่มต้นเพื่อประหยัดทรัพยากร เพื่อให้ได้ประโยชน์ด้านความลึกในอุปกรณ์ที่รองรับ คุณต้องเพิ่มคอมโพเนนต์ AROcclusionManager ลงในออบเจ็กต์เกมกล้อง AR ด้วยตนเองโดยใช้คอมโพเนนต์ Camera และ ARCameraBackground ดูข้อมูลเพิ่มเติมได้ที่การบังอัตโนมัติ ในเอกสารประกอบสำหรับ 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 เพื่อความยืดหยุ่นที่มากขึ้นได้ ดูตัวอย่างวิธีได้ในตัวอย่าง ARFoundation ของ Unity

ทำความเข้าใจค่าความลึก

เมื่อกำหนดให้จุด A ในเรขาคณิตที่สังเกตได้และจุด 2 มิติ a ที่แทนจุดเดียวกันในภาพความลึก ค่าที่ได้จาก Depth API ที่ a จะเท่ากับความยาวของ CA ที่ฉายภาพลงบนแกนหลัก หรือเรียกอีกอย่างว่าพิกัด z ของ A ที่สัมพันธ์กับต้นทางกล้อง C เมื่อใช้ Depth API คุณต้องเข้าใจว่าค่าความลึกไม่ใช่ความยาวของแสง CA แต่เป็นการฉายภาพของแสง

ซ่อนวัตถุเสมือนจริงและแสดงภาพข้อมูลความลึก

ไปที่บล็อกโพสต์ของ Unity เพื่อดูภาพรวมระดับสูงของข้อมูลความลึกและวิธีใช้ข้อมูลดังกล่าวเพื่อประกอบรูปภาพเสมือน นอกจากนี้ ตัวอย่าง ARFoundation ของ Unity ยังแสดงให้เห็นถึงการปิดบังภาพเสมือนและการแสดงภาพข้อมูลเชิงลึกอีกด้วย

คุณสามารถแสดงผลการบังโดยใช้การแสดงผลแบบ 2-Pass หรือการแสดงผลต่อออบเจ็กต์แบบ Forward-Pass ประสิทธิภาพของแต่ละวิธีขึ้นอยู่กับความซับซ้อนของฉากและข้อควรพิจารณาอื่นๆ ของแอปโดยเฉพาะ

การแสดงผลต่อออบเจ็กต์, Forward-Pass

การแสดงผลแบบ Forward-Pass ต่อวัตถุจะเป็นตัวกำหนดการบดบังของแต่ละพิกเซลของวัตถุในตัวให้เฉดสีวัสดุ หากมองไม่เห็นพิกเซล ภาพมักจะถูกตัดออกด้วยการผสมอัลฟ่า ดังนั้นจึงจำลองการบดบังบนอุปกรณ์ของผู้ใช้

การแสดงภาพแบบ 2-Pass

เมื่อมีการแสดงผลแบบ 2-Pass คำสั่งแรกจะแสดงเนื้อหาเสมือนทั้งหมดลงในบัฟเฟอร์ตัวกลาง ด่านที่ 2 จะผสานฉากเสมือนจริงเข้ากับพื้นหลังตามความแตกต่างระหว่างความลึกในโลกจริงกับความลึกของฉากเสมือนจริง วิธีนี้ไม่ต้องใช้ตัวปรับเฉดสีเฉพาะวัตถุเพิ่มเติม และโดยทั่วไปจะให้ผลลัพธ์ที่มีลักษณะแบบเดียวกันมากกว่าวิธี Forward-Pass

ดึงระยะห่างจากรูปภาพที่มีความลึก

หากต้องการใช้ 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 ซึ่งสาธิตวิธีต่างๆ ในการเข้าถึงข้อมูลเชิงลึก