اذهب إلى المحتوى

مقدمة إلى WebGL - التنقل في الفضاء وتشغيل الأضواء


عبد اللطيف ايمش

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

main.png

ملاحظة: هذا الدرس يكمل من حيث انتهى الدرس السابق، لذا عليك أن تفهمه وتحصل على شِفرته قبل الاستمرار بقراءة هذا الدرس.

التنقل في الفضاء ثلاثي الأبعاد

أتوقع أنَّك تعرف محاور الإحداثيات من دراستك الثانوية: يُرسَم المحور x أفقيًا، والمحور y شاقوليًا (عموديّا). وبضبط الوحدات التي تُمثلها تلك المحاور، فسنتمكن من تحديد مكان أيّ عنصرٍ في الجزء الموجب من الفضاء ثنائي الأبعاد. أما إذا أردنا تضمين الأماكن السالبة فعلينا تمديد المحاور إلى اليسار وإلى الأسفل:

01-2D-space.png

نقطة تقاطع المحورين هي النقطة 0, 0 وتسمى «المبدأ» (Origin).
أما لتحديد المواقع في فضاء ثلاثي الأبعاد، فعلينا إضافة محور ثالث عمودي على المحورين السابقين ويتجه بعيدًا عن المشاهد. نستطيع تخيّل المحور z أيضًا بإمالة المنظور قليلًا كما في الرسم التوضيحي الآتي:

02-3D-space.png

لاحظ أنَّ الجزء السالب من المحور z يتجه مبتعدًا عنّا، أما الجزء الموجب فهو أقرب.

يمكن الآن تحديد مكان أيّة نقطة في الفضاء بتقاطع ثلاثة قيم x وy وz.

ملاحظة: لاحظ عدم أهمية ما الذي تمثِّله تلك الأرقام، فقد تكون بوحدة المليمتر أو القدم أو السنوات الضوئية! المهم هو كيف تتفاعل تلك الأرقام مع بعضها: فالقيمة 2x هي ضعف المسافة x.

تتواجد الكاميرات التي أنشأناها في الدرس السابق في مبدأ الإحداثيات افتراضيًا، لكننا نريد وضعها بعيدًا عن المنتصف:

camera.position.set(1380, 0, 0);

المتغير scene يحتوي على الكائنات التي سنُنشِئها، والذي يُمكن تهيئته بالسطر الآتي:

scene = new THREE.Scene();

يوضع المشهد تلقائيًا في مبدأ الإحداثيات (‎0, 0, 0) وسنضع فيه أيضًا العنصر الرئيسي الذي سنُنشِئه (كوكب المريخ). لذا نريد أن نوجِّه الكاميرا إلى تلك النقطة:

camera.lookAt(scene.position);

ملاحظة: يمكن وضع الكاميرا – في هذا المثال– على المحور z أيضًا لكن يجب أن تبعد بنفس القيمة (1380)، ويمكن أيضًا وضعها في الجزء السالب من المحور x أوz؛ وذلك لأنَّ الكاميرا ستكون موجهةً نحو المبدأ دومًا.

لنشغِّل الأضواء

المشهد الذي أنشأناه هو فضاءٌ مظلمٌ لا متناهٍ، مما يعني أنَّ أي كائن سيوضع فيه سيكون غيرَ مرئي، لعدم وجود مصدر للضوء. لنضف واحدًا:

light = new THREE.PointLight(0xFFFFFF, 2, 5000);
light.position.set(2000, 2000, 1500);
scene.add(light);

ملاحظة: لاحظ أنَّك لن ترى شيئًا في هذه المرحلة، ليس لأنَّ مصدر الضوء يكون مخفيًّا افتراضيًا، وإنما لأننا لم نعرض المشهد بعد.

تتوافر ستة أنواع من الأضواء في إطار عمل threeJS:

  • ضوء نقطي (PointLight): وهو الضوء الذي يكون له موضعٌ معيّن، ويُشعّ الضوء في كل الاتجاهات بقدر متساوٍ، مما يجعل هذا النوع من الإضاءة مثاليًا لمحاكاة الضوء الآتي من النجوم أو المصابيح.
  • ضوء ذو اتجاه (DirectionalLight): وهو الضوء الذي له اتجاهٌ معيّن، لكنه ليس حزمةً ضوئيةً (Beam، على النقيض من «بقعة الضوء» Spotlight أدناه)، وهو مفيدٌ لمحاكاة طريقة رؤية أشعة الشمس من سطح الأرض.
  • بقعة ضوء (SpotLight): الضوء الذي يُشير إلى اتجاهٍ معيّن يشبه حزمةً ضوئيةً واسعةً مَثَلُهُ كَمَثَلِ الأضواء المسرحية.
  • الضوء الآتي من منطقة مضيئة مستطيلة (RectAreaLight) وهو مفيدٌ لمحاكاة الضوء المار عبر النافذة أو من لوحٍ من الفلورسنت.
  • الإضاءة المحيطية (AmbientLight): هذا ضوءٌ عامٌ كالذي تراه آتيًا من جميع الاتجاهات. تخيل ليلةً غيرَ مقمرةٍ فيها ضوء محيطي. للإضاءة المحيطية القدرة على إضفاء لونٍ معيّن على المشهد: فكلما كان الضوء المحيطي فاتحًا كلما ظهر المشهد بلونٍ باهت.
  • الإضاءة نصف الكروية (HemisphereLight): يدعى هذا النوع من الإضاءة في برامج التصميم ثلاثي الأبعاد بالمصطلح «Skylight». وهي تحاكي الضوء القادم من الأعلى (السماء) إلى الأسفل (أيّ نوع من الانعكاس أو الضوء من الأرض). يمكنك تخيّل هذا النوع من الإضاءة كما لو أنَّ الإضاءة المحيطية مقسومة إلى نصفين.

سأشرح أنواع الإضاءة السابقة تفصيليًا في مقالاتٍ قادمة، لكن علينا أن نركِّز الآن على الضوء النقطي والذي يأخذ ثلاثة وسائط: اللون (عبر قيمة بالنظام الست عشري، يسبقها ‎0x)، والشدة (Intensity)، والنقطة التي سيبدأ الضوء بالانتشار منها.

Quote

في الحياة الواقعية، يتَّبِع الضوءُ قانونَ التربيعِ العكسي (Inverse-square law) الذي ينص على أنَّ شدة الضوء تتناسب عكسيًا مع مربع المسافة من المصدر. وهذا يحدث فوريًا ومباشرةً بعد خروج الفوتون (photon) من المصدر الضوئي. أما في النمذجة ثلاثية الأبعاد، فستجد أنَّ هذا القانون سيُسبِّب مشاكل: فمن السهل إنشاء مصدر ضوئي تظن أنَّه قويٌ كفايةً لتجد أنَّ شدته قد قلَّت بسرعة. ولهذا السبب يشيع ضبط مسافةٍ لبدء تناقص شدة الضوء في الرسومات ثلاثية الأبعاد منها: حيث يكون الضوء بكامل شدته من المصدر إلى تلك النقطة، ثم تبدأ شدته بالتناقص تدريجيًا بدءًا من تلك النقطة.

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

نموذج أولي بسيط

يؤسفني أن نخوض في كل المعلومات السابقة دون أن تتاح لنا فرصةٌ لرؤية أيّة أشكال في صفحتنا، لذا أنشأتُ نسخةً مبسطةً من الناتج وعرضتها لك. الشيفرة الآتية تضم جميع التعليمات البرمجية التي كتبناها منذ بداية هذه السلسلة وحتى هذه المرحلة (دون الشفرة المسؤولة عن تضمين إطار threeJS):

let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000),
light = new THREE.PointLight(0xFFFFFF, 2, 5000),
scene = new THREE.Scene();
light.position.set(2000, 2000, 1500);
camera.position.set(1500, 0, 0);
camera.lookAt(scene.position);
scene.add(light);

let marsGeo = new THREE.SphereGeometry (500, 32, 32),
marsMaterial = new THREE.MeshPhongMaterial( { color: 0xff6600 } ),
marsMesh = new THREE.Mesh(marsGeo, marsMaterial);
scene.add(marsMesh);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight)       
marsloc.appendChild(renderer.domElement);
renderer.render(scene, camera);

بوضع الشيفرة السابقة في صفحة الويب التي أنشأناها في الدرس السابق، فسترى النتيجة الآتية؛ لكن ما يزال علينا إضافة الكثير من الأمور إليها، وشرحها بالتفصيل، وهذا ما سنفعله في الدرس القادم.

ترجمة –وبتصرّف– للمقال A WebGL Tour of the Solar System: Mars, Part Two لصاحبه Dudley Storey.


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...