ظلال GLSL : دورة OpenGL لغة c++ الدرس السادس


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



كل ما تقوم به هو إخراج عناصر الألوان من بطاقة العرض عند استلام المهام من وحدة الإدخال. في الدروس السابقة نستنتج بأن الظلال يمكن إدارتها جيدًا فوق الأسطح.[1] وخاصة عند وضع المزيد من الخصائص في Vertex Shader و غيرها من الأنابيب.[1]


ظلال GLSL



تم كتابة الظلال بلغة سي. وتم إطلاق التسمية OpenGl Shading Language على أنها تابع أساسي لمكتبات اللغة. حيث أنها بذلك مخولة باستخدام المزايا الرائعة وخاصة عند معالجة المصفوفات الكبيرة.[1]

وكما ذكرنا في الدروس السابقة. فإن شيفرة الظلال غالبًا ما تبدأ بالإعلان عن المكتبة أولا مع مجموعة من المدخلات والمخرجات في بقية البرنامج. على سبيل المثال , نعتبر بأن متغيرات Uniforms واحدة منها.[1] وبالتالي يتم الإشارة إلى جميع عمليات المعالجة في دالة main الخاصة بالظلال.[1]

وفيما يلي الصيغة العامة لها نقلاً عن المصادر :

#version version_number
in type in_var_name;
in type in_var_name;
out type out_var_name;

uniform type uniform_name;
int main()
{
// Input Processing
...
// Output exported
out_var_name = our_stuff_we_processed;
}

كل متغير في vertex shader يعبر عن صفة ويستوعب ظلال GLSL كبيرة من المتغيرات بشرط أن تدعم البطاقة ذلك.[1] يمكن أن تستوعب البطاقات القديمة إلى مدى 16 مكون vertex بينما يتضاعف الأمر كثيرا عند البطاقات المتطورة.[1]

يمكنك فحص مدى دعم الظلال لبطاقتك عن طريق الكود التالي:

GLint attributes;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, & attributes);
std::cout << "Maximum number of vertex attributes supported: " << attributes
<< std::endl;

 


أنواع متغيرات GLSL[1]


تقدم لغة GLSL مجموعة واسعة من المتغيرات فقد تم بناؤها بلغة سي كما ذكرنا سابقا.[1] وبالتالي فإنها تتكون من متغيرات صحيحة وطبقية ومنطقية وغير محدودة. وفي ما يلي أنواع المتغيرات بأسماءها:

  • رقمية : المتجه بقيمة رقمية طبقية.
  • المنطقية: وهي مثال على القيم المنطقية.
  •  Integer متغيرات : مثال على قيمة من نوع Integer(أعداد صحيحة).
  • غير محدودة : متغيرات غير معينة (unsigned).
  • ازدواجية : القيم المزدوجة (double).

يمكن اعتبار الحالات السابقة نادرة وربما لن نستخدمها في دورتنا.[1] باستثناء المتغيرات من نوع vercn , حيث سيتم التركيز على استخدامها كثيرًا. في ظلال GLSL يمكن الوصول إلى متغيرات المتجهات عن طريق العناصر XYZ W. وعلى سبيل المثال لو أردنا الوصول لقيمة x فإن ذلك يتطلب كتابتها على النحو التالي: vec.x.[1]

تتمتع قيم المتجهات بمرونة عالية جدًا عند التحكم بالألوان والإحداثيات. وبالتالي يمكن اعتبارها أحد طرق sizzling في تعيين البيانات.[1]

vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;

تزودك طريقة التعيين السابقة بعض العمليات التي تستطيع استخدامها عند استخدام لغة GLSL.[1] على سبيل المثال تدل الشيفرة الأولى على تعريف متجه محدد , بينما تدل العمليات التالية لها على جمع متجهين وإجراء Assigning (مساواة في القيم) وما دون ذلك الكثير من الوظائف المنطقية.[1]

وهنا مثال آخر من المصادر حول طرق استخدام المتجهات في ظلال GLSL.

vec2 myvec = vec2(0.5f, 0.7f);
vec4 result = vec4(myvec , 0.0f, 0.0f);
vec4 otherResult = vec4(result.xyz, 1.0f);

 


المدخلات والمخرجات


يمكن اعتبار الظلال على أنها برامج رائعة بالفعل!, عدا عن أنها تحتل جزء كبير للغاية من عمليات الإدخال والإخراج التي سنستخدمها.

يمكن استخدام نوعين من الصيغ المحجوزة فيها مثل in التي تدل على المدخلات بينما out تدل على المخرجات. على سبيل المثال , يتعين على كل ظل من ظلال GLSL استخدام عبارات in و out وذلك للتحكم في المدخلات لكل نموذج يتم رسمه.

على سبيل المثال , يستقبل vertex shader البيانات بطريقة مختلفة. لأنه يستلمها مع الإحداثيات وذلك لمعرفة كم من البيانات التي سيتم تحديدها للمراحل القادمة من الأنابيب. يمكن اعتبار أن vertex shader لا يقتصر على بطاقة GPU فحسب. بل إنه يعطي وحدة CPU الإحداثيات ليتم قراءتها قبل إعداد الرسم.

تشير العبارة location = 0 إلى أن هناك مكان محدد في الذاكرة قيمته صفر يتعين على بقية الظلال التعامل معه في جلب الألوان.

 

من الممكن ارسال قيمة layout (location = 0 ) على أنها محدد فعلي لمكان الرسم. ومن ثم يتعين على شيفرة OpenGL الإشارة إليها من Vertex Shader وحفظها ليتم تمريرها إلى بقية مراحل الظلال.

 

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

 


مثال عملي على استخدام الظلال



لدينا الآن شيفرة Pipeline من لغة GLSL يجب أن تدرك أن ما تم شرحه سابقًا ستجده في هذه الشيفرة والمسألة لن تصعب عليك بعد الآن. وفي حال وجدت صعوبة في فهمها يمكنك العودة والقراءة من جديد أو يمكنك انتظار الأمثلة القادمة لتكشف لك كل شيء.

vertex Shader
#version 330 core
layout (location = 0) in vec3 position; // The position variable has
attribute position 0
out vec4 vertexColor; // Specify a color output to the fragment shader
void main()
{
gl_Position = vec4(position, 1.0); // See how we directly give a vec3
to vec4’s constructor
vertexColor = vec4(0.5f, 0.0f, 0.0f, 1.0f); // Set the output variable
to a dark-red color
}

سيتم تمرير مكان الإحداثيات عن طريق layout (location=0) مع مواقعها في الفضاء باستخدام العبارة in يليها متجه باسم position. السطر التالي يشير إلى تصدير متجه باسم vertexColor سيتم استقباله في مرحلة Fragment Shader.

متغير gl_position ثابت سيستقبل الإحداثيات القادمة من شيفرة OpenGL. بالتالي يتم تعيين اللون المراد وضعه للنموذج وهو على ما يبدو من إحدى درجات dark red.

fragment shader
#version 330 core
in vec4 vertexColor; // The input variable from the vertex shader (same
name and same type)
out vec4 color;
void main()
{
color = vertexColor;
}

مرحلة fragment Shader تستقبل البيانات عن طريق تعريف متغير من نفس الإسم vertex Color. ولا ننسى أن عبارة in تعني استقبال المدخلات والتي هي عبارة عن الألوان التي تم تعيينها في شيفرة vertex Shader.

وقد قمنا بتعريف متغير باسم color ومن نوع vec4 يعمل على إرجاع قيمة الألوان إلى شيفرة OpenGL عن طريق تعيين out. وعند النظر إلى النتائج النهائية باستخدام ظلال GLSL فإن مخرجات الشيفرة الخاصة بناء ستكون على النحو التالي:

نتائج ظلال GLSL
صورة يظهر فيها تمرير الألوان من خلال ظلال GLSL.

 

 

 

 

 

 

المراجع
  1. [1]^ كتاب ـــــــ offline learn OpenGL created by Joey de Vries.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *