الإضاءة الأساسية في مكتبة OpenGL هي واحدة من أهم أدوات برمجة الألوان في المشهد ، حيث أنها تعيد النظر في جودة الرسومات ودقتها الأقرب إلى عالم حقيقي.[1]
بينما تتصف الإضاءة الأساسية في العالم الحقيقي بالتعقيد ، وذلك لاعتمادها على عوامل عديدة ، وبالتالي فإن لدينا قوى رئيسية في إدارة المصفوفات لكي يتم تقديم رسومات ذات جودة عالية. [1]
تمتلك الإضاءة في اوبن جل مجموعة من النماذج قادرة على توفير خصائص فريدة في عرض المشهد.
ولربما يستدعي البعض منها القيام بمعادلات فيزيائية حتى تعطي الأداء على النحو المطلوب.[1]
يمكن تقسيم الإضاءة الأساسية في OpenGL إلى مجموعة من الأنواع الواقعة تحت الاسم Phong lighting model.[1]
تساعد الإضاءة الأساسية في إخراج محرك رسومي قوي ، وذلك من خلال الأنواع والفوائد الكبيرة التي يحصل عليها المطور في عالم الفضاء الرسومي.[1]
على سبيل المثال ، يشير أول نوع من الأضواء السابقة إلى وجود إشعاع خافت ومتوهج من مكان بعيد.
وبالتالي فهو يظهر ألوان وأماكن بعض الأجسام في العرض مثل ضوء القمر ، وخاصة أثناء انعكاسه على الجبال والمباني أو أضواء أخرى قوية.[1]
بينما تشير الإضاءة المنتشرة على وجود كائن له وجه يعكس لونه نتيجة ضوء قوي منتشر ، وبالتالي يصبح أعلى حدة عندما يقترب الضوء شيئًا فشيئًا.[1]
يمثل النوع الأخير من الإضاءة بريق الضوء القادم من مركزه ، حيث تظهر إحداثيات مصدر الضوء على أنها انعكاس على بعض الأجسام التي تسمح بذلك.[1]
غالبًا ما تأتي الإضاءة الأساسية المحيطة من مصادر ضوء متعددة وليس من ضوء القمر أو الشمس فقط.
فهي تمثل أضواء المحيط في العالم الحقيقي مثل أضواء الشوارع والمنازل والمصانع.[1]
ما يميز الأضواء المحيطة بأنها من الممكن أن ترتد وتنتشر خارج مكانها مكونة بذلك انعكاسات ووهج في مناطق أخرى معتمة.[1]
بالتالي من الممكن أن تنعكس على أسطح بطريقة غير مباشرة و باتجاهات متعددة.[1]
تمثل خوارزمية global illumination أحد اشكالها في الإضاءة الرئيسية. وتتصف بمدى التعقيد الذي يحصل عند تطبيقها على نحو مطلوب.[1]
وتتبنى الإضاءة الأساسية معادلات معقدة في الإضاءة المحيطة ولأننا لا نريد تعقيد الأمور سوف نعمل على استخدام نموذج بسيط لكي تفلح عملية تمثيل الانعكاسات.
بالتالي سوف نعمل على نفس الكود الذي قمنا بإعداده من الدرس السابق مع اضافة بعض التعديلات على ملفات الظلال.
إضافة الإضاءة المحيطة سهلة وبسيطة فهي تأخذ قيمة الضوء مضروبة بمعامل الضوء كما في الكود التالي:
void main() { float ambientStrength = 0.3f; vec3 ambient = ambientStrength * light Color; vec3 result = ambient * object Color; color = vec4(result, 1.0f); }
قد لا تقدم معادلة الضوء المحيط نتائج جيدة على النماذج ، لكن إضاءة الانتشار سوف تعطي تأثير كبير على الكائنات.[1] على سبيل المثال فهي تعطي وضوح أكثر على النماذج الأقرب لأشعة الضوء المصدرية (Lamp shader).[1]
يتم استخدام علم الزوايا والمثلثات في وصف وإعداد الإضاءة الأساسية في برنامج OpenGL ، ويبدو ذلك واضحًا حينما العمل في الأضواء المنتشرة.[1]
على سبيل المثال يقع الضوء على الأسطح مشكلاً بذلك وتر شعاعي ، ويتم من خلاله قياس الزاوية الناتجة عن وقوع الضوء على السطح. وفي حال كان الإسقاط عمودي على السطح يمتص السطح إشعاعات قوية.[1]
بينما في حال الوقوع بشكل مائل سيقل مدى تأثير الضوء على الأسطح عمومًا.[1]
يتم استخدام متجه باسم normal vector لقياس مدى شدة الإسقاط العمودي على الأسطح.[1]
ومع ذلك فإننا نستخرج الزاوية الناتجة بين هذين المتجهين ليتم الوصول إلى قيمة dot product.[1] ويتم الوصول إلى احتساب القيم عن طريق متجه Normal الذي يمثل وقوع المتجه عموديًا على سطح النموذج.[1]
بينما يتم الوصول إلى شعاع الضوء من خلال احتساب المسافة بين موقع الضوء (light source) وموقع السطح المنعكس(surface).[1]
يتكون Normal vector من متجه واحدي عمودي الإسقاط على السطح ، حيث أنه يمثل فقط نقطة واحدة من الفضاء.[1]
ونستطيع استرجاع قيمته من خلال قيم وإحداثيات السطح الذي استقبل الإشعاع.[1]
بالتالي يمكننا احتساب هذه القيم بطريقة cross product. لكن لأن المكعب هو ليس من النماذج المعقدة نستطيع اضافة كل من عناصر المعادلة إلى إحداثياته.[1]
الآن يجب استبدال كافة إحداثيات المكعب ، قد تجد الرابط أسفل المراجع.[2] ن
قوم الآن بإجراء تعديل بسيط على ملف lighting.vs لكي يتم تضمين متجه normal في الظلال.
layout (location = 1) in vec3 normal;
بعد إضافة متجه normal يعمل على قراءة القيم من الإحداثيات ، يجب إجراء تعديل بسيط على وظيفة glVertexAttribPointer ، وذلك لأننا أيضا أجرينا تغيير على إحداثيات المكعب لتصبح كل واحدة مكونة من 6 قيم.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), ( GLvoid*)0);
يتم الآن إضافة متغير باسم Normal في ملف lighting.vs ومن ثم نتصل به في دالة main.
out vec3 Normal; void main() { gl_Position = projection * view * model * vec4(position, 1.0f); Normal = normal; }
يتم الآن الإعلان عن استقبال متغير Normal في ملف lighting.frag.
in vec3 Normal;
تستخدم الإضاءة الأساسية طرق محددة في احتساب معامل الانتشار ، وبما أننا نمتلك متجهات normal لكل إحداثية فإننا نريد احتساب مكان الضوء.[1]
يمثل مكان الضوء متغير ثابت ويمكن الإعلان عنه في ملف lighting.frag.[1]
uniform vec3 lightPos;
وفي العودة إلى كود المشروع يجب القيام بتحديث يونيفورم الضوء ، سوف نقوم بذلك في حلقة while الخاصة بمكتبة openGL.[1]
GLint lightPosLoc = glGetUniformLocation(lightingShader.Program, "lightPos" ); glUniform3f(lightPosLoc, light Pos.x, lightPos.y, lightPos.z);
الآن نقوم باحتساب كافة قيم الضوء في منطقة world space الخاصة بـ lighting.vs.[1] ، ويتم ذلك من خلال ضرب إحداثيات vertex بـ model matrix.
لنبدأ إذن بالإعلان عن متغير FragPos في ملف lighting.vs.[1]
out vec3 FragPos;
وفي دالة void main الخاصة بملف lighting.vs نقوم بتنفيذ المعادلة التالية:
FragPos = vec3(model * vec4(position, 1.0f));
ثم نذهب إلى ملف lighting.frag ونقوم بتعريف متغير تم استقباله من ملف vertex shader. [1]
بعد الانتهاء من المرحلة السابقة في طرق تفعيل الإضاءة الأساسية يتبقى لدينا احتساب الإتجاه بين مصدر الضوء وإحداثيات المكعب.
ولقد ذكرنا سابقا بأن إتجاه الضوء هو مقدار فرق المسافة بين مصدر الضوء ومكان الإحداثيات.[1]
يتم احتساب ذلك عن طريق المصفوفات ويمكن استخراج الفرق بين متجهين عن طريق طرح أحدهما من الآخر كما في تظهر المعادلة في ملف lighting.vs.[1]
vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos);
تتطلب الإضاءة الأساسية أيضا احتساب الانتشار الفعلي للضوء في ملف lighting.frag. وذلك عن طريق استخراج قيمة dot product لكل من norm و lightDir.[1]
float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * light Color;
الآن سوف يتم تطبيق كل من ambient و diffuse عن طريق دمج الألوان ببعضها البعض.[1] ويظهر ذلك عن طريق تطبيق المعادلة التالية:
vec3 result = (ambient + diffuse) * object Color; color = vec4(result, 1.0f);
يمكنك الحصول على كود lighting.frag[3] و مصادر كود المشروع عن طريق المصادر أدناه. [4]
تعتبر الإضاءة البراقة واحدة من أنواع الإضاءة الأساسية التي يتم استخدامها في معادلات الرسم.
فهي لا تختلف كثيرا عن إضاءة الانتشار حيث يتم احتسابها بناء على إتجاه الضوء و متجه normal الواقع على الكائن.
يختلف ذلك الأمر عن الإضاءة السابقة في إضافة وتر جديد من جهة الناظر ويسمى بالانعكاس.
بالتالي يعمل على احتساب المسافة الواقعة بين متجه الانعكاس واتجاه العرض (عين الناظر).
للحصول على إحداثيات world space من جهة صندوق العرض frustum ، نحتاج إلى إحداثيات كائن الكاميرا ولكي يتحقق ذلك يتطلب منا إضافة يونيفورم خاص يتم تعريفه في ملف lighting.frag.
uniform vec3 viewPos;
ثم بعد ذلك نحاول الاتصال به في كود المشروع عن طريق الوظيفة التالية:
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos"); glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera. Position.z);
لدينا جميع المتغيرات التي تساعدنا في احتساب الإضاءة الأساسية للمتجه specular ، وفي بداية الأمر نقوم بتعريف كثافة الضوء البراق في ملف lighting.frag عن طريق المتغير التالي:
float specularStrength = 0.5f;
الآن نقوم باحتساب اتجاه العرض والانعكاس المطابق لكل من المحاور.
vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); vec3 specular = specularStrength * spec * light Color;
وفي نهاية المعادلة نقوم بإضافة مزيج الألوان في متغير result جنبا إلى جنب مع الألوان السابقة:
vec3 result = (ambient + diffuse + specular) * object Color; color = vec4(result, 1.0f);
وقت النشر : 2023-02-04 21:26:34 ·
يعتمد هذا الموقع على عرض الإعلانات في تحقيق الدخل ، نشكر تفهمكم الدائم ونتمنى لكم قضاء وقت رائع ... وشكراً :D .