استخدام ميزة "العمق" في تطبيق AR Foundation المتوافق مع Android

تساعد واجهة برمجة التطبيقات Depth API كاميرا الجهاز في فهم حجم الأجسام الحقيقية وشكلها في المشهد. ويستخدم هذا الإطار الكاميرا لإنشاء صور أو خرائط ذات عمق، ما يضيف لمسة واقعية إلى تطبيقاتك. يمكنك استخدام المعلومات التي تقدّمها صورة العمق لعرض الأجسام الافتراضية بدقة أمام الأجسام الواقعية أو خلفها، ما يتيح للمستخدمين تجارب غامرة وواقعية.

يتم احتساب معلومات العمق من خلال الحركة، ويمكن دمجها مع معلومات من جهاز استشعار العمق، مثل جهاز استشعار مدة الطيران (ToF)، إذا كان متوفّرًا. لا يحتاج الجهاز إلى استشعار ToF لتتوافق مع Depth API.

المتطلبات الأساسية

احرص على فهم مفاهيم الواقع المعزّز الأساسية وكيفية ضبط جلسة ARCore قبل المتابعة.

ضبط تطبيقك ليكون Depth Required أو Depth Optional (على أجهزة Android فقط)

إذا كان تطبيقك يتطلّب توافق 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 لضبط تطبيق على "التفاصيل" اختيارية.

تفعيل ميزة "العمق"

لتوفير الموارد، لا تفعّل ARCore واجهة برمجة التطبيقات Depth API تلقائيًا. للاستفادة من عمق الصورة على الأجهزة المتوافقة، عليك إضافة عنصر AROcclusionManager يدويًا إلى عنصر اللعبة كاميرا الواقع المعزّز باستخدام العنصرَين 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.
    }
}

يمكنك تحويل صورة وحدة المعالجة المركزية الأوّلية إلى RawImage لتحقيق مرونة أكبر. يمكنك العثور على مثال على كيفية إجراء ذلك في عيّنات ARFoundation في Unity.

فهم قيم العمق

إذا كانت النقطة A في الأشكال الهندسية المرصودة في العالم الواقعي والنقطة a في المستوى ثنائي الأبعاد تمثلان النقطة نفسها في صورة العمق، تكون القيمة التي تقدّمها Depth API في a مساوية لطول CA الذي يتم إسقاطه على المحور الرئيسي. ويمكن أيضًا الإشارة إلى ذلك باسم الإحداثي z لنقطة A بالنسبة إلى نقطة C في اتجاه الكاميرا. عند استخدام Depth API، من المهم معرفة أنّ قيم العمق ليست طول الشعاع CA نفسه، بل إسقاطه.

حجب الأجسام الافتراضية وعرض بيانات العمق

اطّلِع على مقالة المدونة التي نشرتها Unity للحصول على نظرة عامة على بيانات العمق وكيفية استخدامها لإخفاء الصور الافتراضية. بالإضافة إلى ذلك، توضِّح عيّنات ARFoundation في Unity تداخل الصور الافتراضية وعرض بيانات العمق.

يمكنك عرض حجب الرؤية باستخدام العرض بمرور مرّتين أو العرض بمرور مرّة واحدة لكلّ عنصر. تعتمد كفاءة كل نهج على تعقيد المشهد والاعتبارات الأخرى الخاصة بالتطبيق.

التقديم المتقدّم لكل عنصر

يحدِّد التقديم المباشر لكل عنصر حجب كل بكسل من العنصر في برنامج تشويش المواد. إذا لم تكن وحدات البكسل مرئية، يتم اقتصاصها، عادةً من خلال دمج ألفا، ما يحاكي حجب العناصر على جهاز المستخدم.

المعالجة بمرور مرّتين

باستخدام وضع التقديم/الإظهار من تمريرةَين، تُعرِض المَرّة الأولى كل المحتوى الافتراضي في ذاكرة تخزين مؤقتة وسيطة. وفي الخطوة الثانية، يتم دمج المشهد الافتراضي في الخلفية استنادًا إلى الفرق بين عمق العالم الحقيقي وعمق المشهد الافتراضي. لا يتطلّب هذا النهج أيّ عمل إضافي على مخطّط الإضاءة الخاص بالجسم، وينتج بشكل عام نتائج تبدو أكثر اتساقًا من طريقة المرور إلى الأمام.

استخراج المسافة من صورة ذات عمق

لاستخدام 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 الذي يعرض طرقًا مختلفة للوصول إلى بيانات العمق.