hellOGL: برنامج OpenGL hello world

سأعرض اليوم كيفية فتح نافذة وإنشاء سياق OpenGL. هذه مهمة صعبة بشكل مدهش ، حيث لا يزال لدى OpenGL أدوات رسمية عبر الأنظمة الأساسية لإنشاء السياق ، لذلك سوف نعتمد على مكتبات الطرف الثالث (في هذه الحالة GLFW وسعيدة). يوجد بالفعل الكثير من عوالم الترحيب المتشابهة على الإنترنت ، لكنني لا أحب كل ما رأيته: إما أنه متطور للغاية ، أو الصور في الأمثلة بدائية للغاية ( أو كليهما !). شكرا جزيلا لجميع المؤلفين ، لكنني سأقوم بتنزيل برنامج تعليمي آخر :)

اليوم سوف نرسم هذا:



قام الفنان صموئيل شاريت (arshlevon) برسم هذا النموذج ، وأشكره كثيرًا على السماح لي باستخدامه كجزء من دورة محاضرتي حول رسومات الكمبيوتر!

المرحلة 0: قراءة tinyrenderer


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



من المثير للدهشة أن العديد من طلابي لا يفهمون أن برنامج تنقيط هذا البرنامج ليس مجرد لعبة ، ولكنه مقدمة حقيقية لكيفية عمل OpenGL. لذلك ، سأعرض اليوم كيفية تقديم مرض السكري من خلال تسريع الأجهزة ، وفي كثير من النواحي ، سأستخدم الكود من مستودع برنامج تنقيط البرمجيات.

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

المرحلة الأولى ، والأكثر صعوبة: إنشاء نافذة


مستودع كامل يعيش هنا . تم إنشاء التزام واحد لكل خطوة من خطوات البرنامج التعليمي ، نظرًا لأن github يوفر عارضًا مناسبًا جدًا لجميع التغييرات التي تم إجراؤها. نبدأ هنا ، هدفنا هو الحصول على هذه النافذة:



يتم تجميع الشفرة باستخدام CMake؛ راجعت تحت Linux (g ++) و Windows (Visual Studio 2017). ضمن Linux ، يقوم أحدث إصدار من التعليمات البرمجية بترجمة مثل هذا:

git clone --recurse-submodules https://github.com/ssloy/hellOGL.git cd hellOGL mkdir build cd build cmake .. make 

استخدم `git checkout` إذا كنت تريد ترجمة التزام منفصل ، وليس الإصدار الأخير. يتم تحميل هذا الرمز بشكل سعيد و GLFW ، ويقوم بإنشاء نافذة مع معاودة الاتصال الضرورية بلوحة المفاتيح ، ويقوم بتحميل تظليلات رأسية وبكسل فارغة من القرص.

المرحلة الثانية: تحميل نموذج ثلاثي الأبعاد


التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا . في هذه المرحلة ، هدفنا هو تحليل ملف النماذج ثلاثية الأبعاد ، ورسم المثلثات الأولى دون القلق بشأن الإضاءة في الوقت الحالي:



يرجى ملاحظة أن كل من النموذج نفسه والمكتبة للعمل مع المتجهات ، وأخذت محلل النموذج بالكامل من tinyrenderer. ربما العارض البرمجيات ليست عديمة الفائدة جدا؟

الفكرة الأساسية في OpenGL الحديثة بسيطة للغاية. قمنا أولاً بتحميل نموذج ثلاثي الأبعاد ، ثم قمت بإنشاء مجموعة رؤوس ذات حجم 3 * 3 * (عدد المثلثات). كل مثلث له ثلاثة رؤوس ، أليس كذلك؟ يتم وصف كل قمة بثلاثة أرقام (س ، ص ، ض). في المجموع ، 3 * 3 * model.nfaces () كافية بالنسبة لنا لوصف النموذج بأكمله:

  std::vector<GLfloat> vertices(3*3*model.nfaces(), 0); for (int i=0; i<model.nfaces(); i++) { for (int j=0; j<3; j++) { for (int k=0; k<3; k++) vertices[(i*3+j)*3 + k] = model.point(model.vert(i, j))[k]; } } 

ثم نقول لبرنامج OpenGL أنه هنا صفيف ، رسم ، أصلي!

  while (!glfwWindowShouldClose(window)) { [...]  glDrawArrays(GL_TRIANGLES, 0, vertices.size()); [...] } 

تظليل قمة الرأس لا يفعل شيئًا مثيرًا للاهتمام ، فهو ببساطة ينقل البيانات إلى تظليل القطعة كما هو:

 #version 330 core // Input vertex data, different for all executions of this shader layout(location = 0) in vec3 vertexPosition_modelspace; void main() { gl_Position = vec4(vertexPosition_modelspace, 1); // Output position of the vertex, in clip space } 

حسنا ، إن شظية شظية هو أيضا متواضع. إنه ببساطة يرسم المخلل الحالي باللون الأحمر:

 #version 330 core // Output data out vec3 color; void main() { color = vec3(1,0,0); } 

يتم أصعب شيء ، الآن هي مسألة تقنية!

المرحلة الثالثة: الإضاءة المنتشرة


التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا . يجب أن نحصل على هذه الصورة:



تعتبر الإضاءة المنتشرة في نموذج Phong ، كما تعلمون ، منتجًا بسيطًا بيني
ناقلات طبيعية وناقلات الإضاءة. لذلك ، بالإضافة إلى مجموعة القمم ، أضفت مجموعة أخرى عادية. دون النظر إلى الكود ، أخبرني ما حجمه؟

يحدث الشيء الأكثر إثارة للاهتمام في تظليل الأجزاء ، في ملف .cpp الرئيسي ، يتم تحميل البيانات فقط:

 #version 330 core // Output data out vec3 color; // Interpolated values from the vertex shaders in vec3 Normal_cameraspace; in vec3 LightDirection_cameraspace; void main() { vec3 n = normalize(Normal_cameraspace); // Normal of the computed fragment, in camera space vec3 l = normalize(LightDirection_cameraspace); // Direction of the light (from the fragment to the light) float cosTheta = clamp(dot(n,l), 0, 1); // Cosine of the angle between the normal and the light direction, color = vec3(1,0,0)*(0.1 + // ambient lighting 1.3*cosTheta); // diffuse lighting } 

المرحلة الرابعة: مصفوفات التحول


التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا . في هذه المرحلة ، قمت بترميز مصفوفات النموذج والعرض والإسقاط. في البداية ، تكون مفردة فقط ، ولكن إذا ضغطت على مفتاح المسافة ، سيبدأ النموذج في التدوير: في كل مرة أرسم صورة ، أقوم بتدوير مصفوفة النموذج حول المحور z بمقدار 0.01 راديان:

  { // rotate the model around the z axis with each frame Matrix R = rot_z(0.01); if (animate) M = R*M; } 

هنا تقوم دالة rot_z () بإرجاع مصفوفة الدوران حول المحور z بزاوية معينة. نظرًا لأن OpenGL لا يعرف شيئًا عن فئة المصفوفة الخاصة بي ، فقد اضطررت إلى إضافة باطل تصدير المصفوفة export_row_major () إلى مؤشر بسيط إلى تعويم.



الخطوة الخامسة: الخرائط العادية


التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا . في هذه المرحلة سوف نتعلم كيفية تراكب القوام. نظرًا لأن النسيج المنتشر المعتاد ممل ، فسوف أطبق الخريطة العادية على الفور ، وحتى في الفضاء المماسي. تبدو الخرائط العادية مثل هذا:



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



المرحلة الخامسة: نسيج منتشر


حسنًا ، إذا كنا نعرف بالفعل كيفية حساب الخرائط العادية ، فإن تطبيق مادة منتشرة عادية أمر بسيط تمامًا. التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا .



المرحلة السادسة: الوهج


التغييرات في المشروع التي تم إجراؤها في هذه المرحلة ، انظر هنا . المرحلة الأخيرة ، أضف نسيجًا آخر سيسمح لنا بمحاكاة وهج الإضاءة من الأسطح اللامعة:



الخاتمة


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

كامتداد ، جرب ، على سبيل المثال ، إضافة الظلال ، أو عد الإضاءة العالمية ، أو ، أخيرًا ، رسم خريطة توهج: بعد كل شيء ، يجب أن تتوهج العيون والكريستال في جبين Diablo!

Source: https://habr.com/ru/post/ar443174/


All Articles