1. قبل البدء
يتناول هذا الدرس التطبيقي مثالاً على إنشاء تطبيق ويب للواقع المعزّز. ويستخدم JavaScript لعرض نماذج ثلاثية الأبعاد تبدو وكأنّها موجودة في العالم الحقيقي.
يمكنك استخدام WebXR Device API الذي يجمع بين وظائف الواقع المعزّز والواقع الافتراضي. يمكنك التركيز على إضافات الواقع المعزّز إلى WebXR Device API لإنشاء تطبيق مزوَّد بميزة الواقع المعزَّز يعمل على الويب التفاعلي.

ما هو الواقع المعزّز؟
الواقع المعزّز هو مصطلح يُستخدم عادةً لوصف مزيج من الرسومات التي يتم إنشاؤها بواسطة الكمبيوتر مع العالم الحقيقي. في حالة الواقع المعزّز المستند إلى الهاتف، يعني ذلك وضع رسومات الكمبيوتر بشكل مقنع على خلاصة الكاميرا المباشرة. ولكي يظل هذا التأثير واقعيًا أثناء تحرّك الهاتف في العالم الحقيقي، يجب أن يفهم الجهاز المتوافق مع تكنولوجيا الواقع المعزّز العالم الذي يتحرّك فيه وأن يحدّد وضعيته (موضعه واتجاهه) في الفضاء الثلاثي الأبعاد. وقد يشمل ذلك رصد الأسطح وتقدير إضاءة البيئة.
أصبح الواقع المعزّز مستخدَمًا على نطاق واسع في التطبيقات بعد إطلاق ARCore من Google وARKit من Apple، سواء كان ذلك لإنشاء فلاتر صور السيلفي أو الألعاب المستندة إلى الواقع المعزّز.
ما ستنشئه
في هذا الدرس العملي، ستنشئ تطبيق ويب يضع نموذجًا في العالم الحقيقي باستخدام الواقع المعزّز. سيتم إجراء ما يلي في تطبيقك:
- استخدام أدوات الاستشعار في الجهاز المستهدَف لتحديد موقعه واتجاهه وتتبُّعهما في العالم
- عرض تصميم ثلاثي الأبعاد مدمج مع شاشة الكاميرا المباشرة
- تنفيذ اختبارات إصابة لتحديد موضع العناصر فوق الأسطح التي تم اكتشافها في العالم الحقيقي
أهداف الدورة التعليمية
- كيفية استخدام WebXR Device API
- كيفية ضبط مشهد واقع معزّز أساسي
- كيفية العثور على سطح باستخدام اختبارات إصابة الواقع المعزّز
- كيفية تحميل نموذج ثلاثي الأبعاد وعرضه بشكل متزامن مع خلاصة الكاميرا في العالم الحقيقي
- كيفية عرض الظلال استنادًا إلى التصميم الثلاثي الأبعاد
يركّز هذا الدرس التطبيقي حول الترميز على واجهات برمجة التطبيقات للواقع المعزّز. يتم تجاهل المفاهيم ومجموعات الرموز غير ذات الصلة وتقديمها لك في رمز المستودع المقابل.
المتطلبات
- محطة عمل لترميز واستضافة محتوى الويب الثابت
- جهاز Android متوافق مع ARCore يعمل بالإصدار Android 8.0 Oreo
- Google Chrome
- تثبيت خدمات Google Play للواقع المعزّز (يطلب منك Chrome تلقائيًا تثبيتها على الأجهزة المتوافقة)
- خادم ويب من اختيارك
- كابل USB لتوصيل جهاز الواقع المعزّز بمحطة العمل
- الرمز النموذجي
- محرِّر نصوص
- معرفة أساسية بلغات HTML وCSS وJavaScript وأدوات مطوّري برامج Chrome
انقر على تجربة على جهاز الواقع المعزّز لتجربة الخطوة الأولى من هذا الدرس التطبيقي حول الترميز. إذا ظهرت لك صفحة تتضمّن رسالة "لا يتضمّن المتصفّح ميزات الواقع المعزّز"، تأكَّد من تثبيت "خدمات Google Play للواقع المعزّز" على جهاز Android.
2. إعداد بيئة التطوير
تنزيل الرمز
- انقر على الرابط التالي لتنزيل كل الرموز البرمجية لهذا الدرس العملي على محطة العمل:
- فكّ ضغط ملف ZIP الذي تم تنزيله. سيؤدي ذلك إلى فك حزمة مجلد رئيسي (
ar-with-webxr-master)، يحتوي على أدلة تتضمّن عدة خطوات من هذا الدرس التطبيقي حول الترميز، بالإضافة إلى جميع الموارد التي تحتاج إليها.
يحتوي المجلّدان step-03 وstep-04 على الحالة النهائية المطلوبة للخطوتَين الثالثة والرابعة من هذا الدرس العملي، بالإضافة إلى نتيجة final. وهي متوفّرة للرجوع إليها.
يمكنك تنفيذ جميع أعمال الترميز في الدليل work.
تثبيت خادم الويب
- يمكنك استخدام خادم الويب الخاص بك. إذا لم يسبق لك إعداد خادم ويب، يوضّح هذا القسم كيفية إعداد Web Server for Chrome.
إذا لم يكن هذا التطبيق مثبَّتًا على محطة العمل بعد، يمكنك تثبيته من "سوق Chrome الإلكتروني".
- بعد تثبيت تطبيق "خادم الويب لمتصفّح Chrome"، انتقِل إلى
chrome://appsوانقر على رمز "خادم الويب":
![]()
يظهر مربّع الحوار التالي الذي يتيح لك ضبط إعدادات خادم الويب المحلي:

- انقر على اختيار مجلد واختَر مجلد
ar-with-webxr-master. يتيح لك ذلك عرض عملك قيد التنفيذ من خلال عنوان URL المميّز في مربّع حوار خادم الويب (في قسم عناوين URL لخادم الويب). - ضِمن الخيارات (يجب إعادة التشغيل)، ضَع علامة في مربّع الاختيار عرض index.html تلقائيًا.
- بدِّل خادم الويب إلى إيقاف، ثم أعِد التبديل إلى بدء.

- تأكَّد من ظهور عنوان URL واحد على الأقل لخادم الويب: http://127.0.0.1:8887، وهو عنوان URL التلقائي للمضيف المحلي.
إعداد قاعدة إعادة توجيه المنفذ
اضبط جهاز الواقع المعزّز كي يصل إلى المنفذ نفسه على محطة العمل عند الانتقال إلى localhost:8887 عليه.
- على محطة عمل التطوير، انتقِل إلى chrome://inspect وانقر على توجيه المنفذ...:

- استخدِم مربّع الحوار إعدادات إعادة توجيه المنفذ لإعادة توجيه المنفذ 8887 إلى localhost:8887.
- ضَع علامة في مربّع الاختيار تفعيل إعادة توجيه المنفذ:

التحقق من صحة الإعداد
اختبار الاتصال:
- وصِّل جهاز الواقع المعزّز بمحطة العمل باستخدام كابل USB.
- على جهاز الواقع المعزّز في Chrome، أدخِل http://localhost:8887 في شريط العناوين. يجب أن يعيد جهاز الواقع المعزّز توجيه هذا الطلب إلى خادم الويب الخاص بمحطة عمل التطوير. من المفترض أن يظهر دليل للملفات.
- على جهاز الواقع المعزّز، انقر على
step-03لتحميل ملفstep-03/index.htmlفي المتصفّح.
ستظهر لك صفحة تحتوي على زر بدء الواقع المعزّز. | ومع ذلك، إذا ظهرت لك صفحة الخطأ المتصفّح غير متوافق، من المحتمل أن يكون جهازك غير متوافق. |
|
|
من المفترض أن يعمل الاتصال بخادم الويب الآن مع جهاز الواقع المعزّز.
- انقر على بدء الواقع المعزّز. قد يُطلب منك تثبيت ARCore.

تظهر لك رسالة تطلب منك منح أذونات الكاميرا في المرة الأولى التي تشغّل فيها تطبيقًا يستخدم الواقع المعزّز.
← 
بعد أن يصبح كل شيء جاهزًا، من المفترض أن يظهر مشهد مكعبات فوق خلاصة الكاميرا. تتحسّن ميزة "فهم المشهد" كلما حلّلت الكاميرا المزيد من العالم، لذا يمكن أن يساعدك التنقّل في تثبيت العناصر.

3- ضبط WebXR
في هذه الخطوة، ستتعرّف على كيفية إعداد جلسة WebXR ومشهد واقع معزّز أساسي. يتم توفير صفحة HTML مع أنماط CSS وJavaScript لتفعيل وظائف الواقع المعزّز الأساسية. يؤدي ذلك إلى تسريع عملية الإعداد، ما يسمح لبرنامج التدريب العملي بالتركيز على ميزات الواقع المعزّز.
صفحة HTML
يمكنك إنشاء تجربة واقع معزّز في صفحة ويب تقليدية باستخدام تكنولوجيات الويب الحالية. في هذه التجربة، يمكنك استخدام لوحة عرض بملء الشاشة، لذا لا يجب أن يكون ملف HTML معقّدًا جدًا.
تتطلّب ميزات الواقع المعزّز إجراءً من المستخدم لبدء استخدامها، لذا تتوفّر بعض مكوّنات التصميم المتعدد الأبعاد لعرض زر بدء الواقع المعزّز ورسالة المتصفّح غير المتوافق.
يجب أن يظهر ملف index.html الموجود في دليل work على النحو التالي. هذه مجموعة فرعية من المحتوى الفعلي، لذا لا تنسخ هذا الرمز إلى ملفك.
<!-- Don't copy this code into your file! -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building an augmented reality application with the WebXR Device API</title>
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<!-- three.js -->
<script src="https://unpkg.com/three@0.123.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.123.0/examples/js/loaders/GLTFLoader.js"></script>
<script src="../shared/utils.js"></script>
<script src="app.js"></script>
</head>
<body>
<!-- Information about AR removed for brevity. -->
<!-- Starting an immersive WebXR session requires user interaction. Start the WebXR experience with a simple button. -->
<a onclick="activateXR()" class="mdc-button mdc-button--raised mdc-button--accent">
Start augmented reality
</a>
</body>
</html>
افتح رمز JavaScript الخاص بالمفتاح
نقطة البداية لتطبيقك هي app.js. يوفّر هذا الملف بعض الرموز الجاهزة لإعداد تجربة واقع معزّز.
يتضمّن دليل العمل أيضًا رمز التطبيق (app.js).
التحقّق من التوافق مع WebXR والواقع المعزّز
قبل أن يتمكّن المستخدم من العمل باستخدام الواقع المعزّز، تحقَّق من توفّر navigator.xr وميزات الواقع الممتد اللازمة. العنصر navigator.xr هو نقطة الدخول إلى WebXR Device API، لذا يجب أن يكون متوفّرًا إذا كان الجهاز متوافقًا. تحقَّق أيضًا من أنّ وضع الجلسة "immersive-ar" متوافق.
إذا كان كل شيء على ما يرام، سيؤدي النقر على الزر الدخول إلى الواقع المعزّز إلى محاولة إنشاء جلسة XR. بخلاف ذلك، يتم استدعاء onNoXRDevice() (في shared/utils.js) الذي يعرض رسالة تشير إلى عدم توفّر ميزة الواقع المعزّز.
هذا الرمز متوفّر حاليًا في app.js، لذا ليس عليك إجراء أي تغيير.
(async function() {
if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) {
document.getElementById("enter-ar").addEventListener("click", activateXR)
} else {
onNoXRDevice();
}
})();
طلب XRSession
عند النقر على الدخول إلى الواقع المعزّز، يستدعي الرمز activateXR(). سيؤدي ذلك إلى بدء تجربة الواقع المعزّز.
- ابحث عن الدالة
activateXR()فيapp.js. تم حذف بعض الرموز:
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = /* TODO */;
// Omitted for brevity
}
يمكن الوصول إلى WebXR من خلال XRSystem.requestSession(). استخدِم وضع immersive-ar للسماح بعرض المحتوى الذي تمّ عرضه في بيئة من العالم الحقيقي.
- ابدأ
this.xrSessionباستخدام الوضع"immersive-ar":
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = await navigator.xr.requestSession("immersive-ar");
// ...
}
إعداد XRReferenceSpace
يصف XRReferenceSpace نظام الإحداثيات المستخدَم للعناصر داخل العالم الافتراضي. يكون وضع 'local' هو الأنسب لتجربة الواقع المعزّز، مع مساحة مرجعية لها نقطة أصل بالقرب من المشاهد وتتبُّع ثابت.
ابدأ this.localReferenceSpace في onSessionStarted() باستخدام الرمز التالي:
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
تحديد تكرار صورة متحركة
- استخدِم
requestAnimationFrameفيXRSessionلبدء حلقة عرض، على غرارwindow.requestAnimationFrame.
في كل إطار، يتم استدعاء onXRFrame مع طابع زمني وXRFrame.
- أكمِل عملية تنفيذ
onXRFrame. عند رسم إطار، ضَع الطلب التالي في قائمة الانتظار من خلال إضافة ما يلي:
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
- أضِف رمزًا لإعداد بيئة الرسومات. أضِف ما يلي إلى أسفل
onXRFrame:
// Bind the graphics framebuffer to the baseLayer's framebuffer.
const framebuffer = this.xrSession.renderState.baseLayer.framebuffer;
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
this.renderer.setFramebuffer(framebuffer);
- لتحديد وضعية المشاهد، استخدِم
XRFrame.getViewerPose(). تصفXRViewerPoseموضع الجهاز واتجاهه في الفضاء. يحتوي أيضًا على مصفوفة منXRView، والتي تصف كل نقطة عرض يجب عرض المشهد منها بشكل صحيح على الجهاز الحالي. في حين أنّ الواقع الافتراضي المجسّم يتضمّن عرضَين (واحد لكل عين)، لا تتضمّن أجهزة الواقع المعزّز سوى عرض واحد.
يتم استخدام المعلومات الواردة فيpose.viewsبشكل شائع لإعداد مصفوفة العرض ومصفوفة العرض في الكاميرا الافتراضية. يؤثّر ذلك في طريقة عرض المشهد بتنسيق ثلاثي الأبعاد. بعد ضبط إعدادات الكاميرا، يمكن عرض المشهد. - أضِف ما يلي إلى أسفل
onXRFrame:
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(this.localReferenceSpace);
if (pose) {
// In mobile AR, we only have one view.
const view = pose.views[0];
const viewport = this.xrSession.renderState.baseLayer.getViewport(view);
this.renderer.setSize(viewport.width, viewport.height);
// Use the view's transform matrix and projection matrix to configure the THREE.camera.
this.camera.matrix.fromArray(view.transform.matrix);
this.camera.projectionMatrix.fromArray(view.projectionMatrix);
this.camera.updateMatrixWorld(true);
// Render the scene with THREE.WebGLRenderer.
this.renderer.render(this.scene, this.camera);
}
اختبارها
شغِّل التطبيق، ثم انتقِل إلى work/index.html على جهاز التطوير. من المفترض أن تظهر لك خلاصة الكاميرا مع مكعبات تطفو في الفضاء وتتغير زاوية نظرها أثناء تحريك جهازك. تتحسّن عملية التتبُّع كلما تحرّكت أكثر، لذا استكشِف الخيارات المناسبة لك ولجهازك.

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

طلب XRSession يتضمّن ميزات إضافية
لإجراء اختبارات إصابة، يجب توفُّر ميزات إضافية عند طلب XRSession.
- في
app.js، ابحث عنnavigator.xr.requestSession. - أضِف الميزتَين
"hit-test"و"dom-overlay"كـrequiredFeatures على النحو التالي:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"]
});
- ضبط تراكب DOM طبِّق العنصر
document.bodyفوق شاشة كاميرا الواقع المعزّز على النحو التالي:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"],
domOverlay: { root: document.body }
});
إضافة طلب حركة
يعمل ARCore بشكل أفضل عند توفّر فهم كافٍ للبيئة المحيطة. ويتم تحقيق ذلك من خلال عملية تُعرف باسم "الاستهداف وتحديد الموقع الجغرافي في الوقت نفسه" (SLAM)، حيث يتم استخدام نقاط مميزة مرئية لحساب التغيير في الموقع الجغرافي وخصائص البيئة.
استخدِم الرمز "dom-overlay" من الخطوة السابقة لعرض طلب حركة في أعلى بث الكاميرا.
أضِف <div> إلى index.html باستخدام المعرّف stabilization. تعرض <div> هذه صورة متحركة للمستخدمين تمثّل حالة الثبات وتطلب منهم التحرّك بأجهزتهم لتحسين عملية SLAM. يظهر هذا النص عندما يكون المستخدم في وضع الواقع المعزّز ويتم إخفاؤه عندما تعثر شبكة التصويب على سطح، ويتم التحكّم فيه من خلال فئات <body>.
<div id="stabilization"></div>
</body>
</html>
إضافة شبكة تصويب
استخدِم شبكة شعيرات متقاطعة للإشارة إلى الموقع الجغرافي الذي يشير إليه عرض الجهاز.
- في
app.js، استبدِل استدعاءDemoUtils.createCubeScene()فيsetupThreeJs()بـThree.Scene()فارغ.
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
}
- املأ المشهد الجديد بعنصر يمثّل نقطة التصادم. يتولّى الصف
Reticleالمتوفّر تحميل نموذج شبكة التصويب فيshared/utils.js. - أضِف
Reticleإلى المشهد فيsetupThreeJs():
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
this.reticle = new Reticle();
this.scene.add(this.reticle);
}
لإجراء اختبار مؤشر الماوس، عليك استخدام XRReferenceSpace جديد. تشير مساحة المرجع هذه إلى نظام إحداثيات جديد من منظور المشاهد لإنشاء شعاع متوافق مع اتجاه العرض. يتم استخدام نظام الإحداثيات هذا في XRSession.requestHitTestSource()، الذي يمكنه احتساب اختبارات النتائج.
- أضِف ما يلي إلى
onSessionStarted()فيapp.js:
async onSessionStarted() {
// ...
// Setup an XRReferenceSpace using the "local" coordinate system.
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
// Add these lines:
// Create another XRReferenceSpace that has the viewer as the origin.
this.viewerSpace = await this.xrSession.requestReferenceSpace("viewer");
// Perform hit testing using the viewer as origin.
this.hitTestSource = await this.xrSession.requestHitTestSource({ space: this.viewerSpace });
// ...
}
- باستخدام
hitTestSource، نفِّذ اختبار مؤشر الماوس كل إطار:- إذا لم تظهر أي نتائج لاختبار مؤشر الماوس، يعني ذلك أنّ ARCore لم يحصل على وقت كافٍ لفهم البيئة. في هذه الحالة، اطلب من المستخدم تحريك الجهاز باستخدام أداة التثبيت
<div>. - إذا ظهرت نتائج، حرِّك شبكة التصويب إلى ذلك الموقع الجغرافي.
- إذا لم تظهر أي نتائج لاختبار مؤشر الماوس، يعني ذلك أنّ ARCore لم يحصل على وقت كافٍ لفهم البيئة. في هذه الحالة، اطلب من المستخدم تحريك الجهاز باستخدام أداة التثبيت
- عدِّل
onXRFrameلتحريك شبكة التصويب:
onXRFrame = (time, frame) => {
// ... some code omitted ...
this.camera.updateMatrixWorld(true);
// Add the following:
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
if (!this.stabilized && hitTestResults.length > 0) {
this.stabilized = true;
document.body.classList.add("stabilized");
}
if (hitTestResults.length > 0) {
const hitPose = hitTestResults[0].getPose(this.localReferenceSpace);
// update the reticle position
this.reticle.visible = true;
this.reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
this.reticle.updateMatrixWorld(true);
}
// More code omitted.
}

إضافة سلوك عند النقر على الشاشة
يمكن أن يرسل XRSession أحداثًا استنادًا إلى تفاعل المستخدم من خلال الحدث select، الذي يمثّل الإجراء الأساسي. في WebXR على الأجهزة الجوّالة، يكون الإجراء الأساسي هو النقر على الشاشة.
- أضِف متتبِّع الأحداث
selectفي أسفلonSessionStarted:
this.xrSession.addEventListener("select", this.onSelect);
في هذا المثال، يؤدي النقر على الشاشة إلى وضع زهرة عباد الشمس في شبكة التصويب.
- أنشئ عملية تنفيذ للدالة
onSelectفي الفئةApp:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
}
}
اختبار التطبيق
لقد أنشأت شبكة شعيرات يمكنك توجيهها باستخدام جهازك من خلال اختبارات إصابة. عند النقر على الشاشة، يجب أن تتمكّن من وضع زهرة عباد الشمس في الموقع الذي تحدّده شبكة التصويب.
- عند تشغيل تطبيقك، من المفترض أن تتمكّن من رؤية شبكة خطوط متقاطعة تتتبّع سطح الأرضية. إذا لم يظهر لك أي شيء، جرِّب التنقّل ببطء باستخدام هاتفك.
- بعد ظهور شبكة التصويب، انقر عليها. يجب وضع زهرة عباد الشمس فوقها. قد تحتاج إلى التحرك قليلاً لكي تتمكّن منصة الواقع المعزّز الأساسية من رصد الأسطح في العالم الحقيقي بشكل أفضل. تؤدي الإضاءة المنخفضة والأسطح غير المميزة إلى انخفاض جودة فهم المشهد، وتزيد من احتمال عدم العثور على أي تطابق. إذا واجهت أي مشاكل، اطّلِع على الرمز
step-04/app.jsللاطّلاع على مثال عملي لهذه الخطوة.

5- إضافة ظلال
يتضمّن إنشاء مشهد واقعي عناصر مثل الإضاءة والظلال المناسبة على الكائنات الرقمية التي تضيف الواقعية والانغماس في المشهد.
تتم معالجة الإضاءة والظلال من خلال three.js. يمكنك تحديد الأضواء التي يجب أن تلقي ظلالاً، والمواد التي يجب أن تتلقّى هذه الظلال وتعرضها، والشبكات التي يمكنها إلقاء الظلال. يحتوي مشهد هذا التطبيق على ضوء يلقي بظل وسطح مستوٍ لعرض الظلال فقط.
- فعِّل الظلال على
three.jsWebGLRenderer. بعد إنشاء أداة العرض، اضبط القيم التالية علىshadowMap:
setupThreeJs() {
...
this.renderer = new THREE.WebGLRenderer(...);
...
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
...
}
يحتوي المشهد النموذجي الذي تم إنشاؤه في DemoUtils.createLitScene() على عنصر يُسمى shadowMesh، وهو عبارة عن سطح أفقي مستوٍ يعرض الظلال فقط. تبلغ قيمة الموضع Y لهذه المساحة في البداية 10,000 وحدة. بعد وضع زهرة عباد الشمس، حرِّك shadowMesh ليكون على الارتفاع نفسه الذي يظهر به السطح في العالم الحقيقي، وذلك لعرض ظل الزهرة فوق الأرض في العالم الحقيقي.
- في
onSelect، بعد إضافةcloneإلى المشهد، أضِف الرمز البرمجي لإعادة ضبط موضع مستوى الظل:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
const shadowMesh = this.scene.children.find(c => c.name === "shadowMesh");
shadowMesh.position.y = clone.position.y;
}
}
اختبارها
عند وضع زهرة عباد الشمس، من المفترض أن تتمكّن من رؤية ظلها. إذا واجهت أي مشاكل، اطّلِع على الرمز final/app.js للاطّلاع على مثال عملي لهذه الخطوة.

6. مراجع إضافية
تهانينا! لقد وصلت إلى نهاية هذا الدرس العملي حول الواقع المعزّز باستخدام WebXR.

