يونيفورم OpenGL : دورة OpenGL لغة c++ الدرس السابع


يونيفورم OpenGL وهو طريقة أخرى لتمرير البيانات من مشروعنا إلى وحدة CPU ومن ثم إلى وحدة معالجة الرسومات GPU.[1] لكن يونيفورم OpenGL يختلف قليلاً عند المقارنة مع سمات Vertex. حيث تعبر يونيفورم OpenGL عن متغيرات عامة ما يعني أنها متغيرات فريدة من نوعها لكل ظل من ظلال GLSL يجري استخدامه.[1]تعمل متغيرات يونيفورم بشكل عام لحظة عمل المشروع ويتم الوصول إليها من قبل أي ظلال يتم تضمينها في عملية الرسم.[1] وبالتالي يتم الاحتفاظ بكافة القيم طوال حياة البرنامج. يتم الإشارة إلى يونيفورم OpenGL بطريقة سهلة وبسيطة فهي تحمل العبارة uniform بالانجليزية مع نوع المتجه المراد استخدامه ومن ثم يتم تمريرها إلى المراحل القادمة من GLSL.[1]



البدء بتفعيل يونيفورم OpenGL


الآن وبعد أن أدركنا بأن uniform هو متغير بسيط سيتسنى لنا إبرازه في كود بسيط مثل:

#version 330 core
out vec4 color;
uniform vec4 our Color; // We set this variable in the OpenGL code.
void main()
{
color = our Color;
}

لقد قمنا بالإعلان عن متغير يونيفورم من نوع vec4 و قمنا بتسميته our Color في ملف Fragment Shader.[1] وكذلك الأمر بالنسبة للمخرجات حيث تولت بذلك عملية إرسال القيم إلى وحدة المعالجة ملحوقة بالقيمة التي بداخلها.[1]

وبما أن قيم يونيفورم عبارة عن متغيرات عامة بالتالي يمكن تحديدها بأي من الظلال. ولا داعي للعودة إلى قيم Vertex Shader وإعطاء ألوان أساسية منها.[1]

 

نضع بالاعتبار أنه في حال قمت بالإعلان عن متغير uniform غير مستخدم. فسيتم حذفه من لغة GLSL متجاهلة بذلك وجوده مع ظهور بعض الأخطاء.

 

نلاحظ في الكود السابق بأن متغير يونيفورم OpenGL هو فارغ تمامًا في شيفرة المشروع ولم يتم إرفاق أية بيانات له. ولذلك نحاول إجراء بعض التعديلات على البرنامج.[1]


تعيين الألوان من كود OpenGL


نحتاج الآن البحث عن أماكن index المفهرسة في سمات العناصر الخاصة بالظلال وبمجرد العثور على تلك الأماكن.[1] نستطيع إجراء بعض التحديثات عليها بدلا من تمرير ألوان أحادية القيم.[1] وبالرجوع إلى كود OpenGL نجري بعض الإضافات التالية لتبدو كما يلي:

GLfloat timeValue = glfwGetTime();
GLfloat greenValue = (sin(timeValue) / 2) + 0.5;
GLint vertexColorLocation = glGetUniformLocation(shaderProgram, "our Color")
;
glUseProgram(shaderProgram);
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

في حال وجدت صعوبة ببعض المعادلات السابقة فلا داعي للقلق , حيث أن شيفرة اللون تخضع لمعادلات رياضية معقدة لا نريد الخوض بها على الإطلاق.[1]

الدالة الأولى glfw GetTime(); سترجع قيمة باللون الأخضر وذلك من خلال جيب قيمة الوقت مقسومة على اثنين زائد قيمة سطحية FLoat.[1]

بعد ذلك نستعلم عن مكان الـ uniform باستخدام الدالة glGetUniformLocation. والتي تمكننا من الإتصال بلغة GLSL وأنظمة الظلال لتخبرها باستلام قيمة من البرنامج. وفي حال تم إرجاع قيمة -1 فإن ذلك يعني تعذر الحصول على الموقع. بينما تدل القيمة glUseProgram على استخدام الظلال وقد قمنا بشرحها في درس ظلال GLSL.[1]

وأخيرًا تعمل الدالة glUniform4f على إرسال اللون من يونيفورم OpenGL إلى GLSL وذلك من خلال ملئ قيمة اللون الأخضر من بين المتغيرات.[1] لا ننسى أن نظام الألوان يعتمد على صيغة 8 بت و 24 بت كقيم RGBA.[2]

 

تحمل دالة glUniform العديد من الخفايا التي سيتم كشفها الآن. على سبيل المثال يشير الحرف f إلى قيمة طبقية . بينما الحرف i إلى قيمة من نوع Integer وهكذا دواليك بالنسبة للقيم التالية. حيث أن ui تعني unsigned integer وقيمة 3f إلى ثلاثية طبقية و fv إلى طبقية من نوع vector.

 


تفعيل الكود في البرنامج


الآن كل ما نريد فعله هو تفعيل القيم التي ذكرناها في السابق ويتطلب ذلك وضعها في حلقة While الخاصة بمكتبة OpenGL أو يمكنك نقلها إلى دالة باسم render ومناداتها فيما بعد لكي تتضح الأمور شيئًا فشيئًا.

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

نحاول الآن وضع كافة قيم يونيفورم OpenGL في حلقة التكرار تمامًا مثل الشيفرة التالية:

 

while(!glfwWindowShouldClose(window))
{
// Check and call events
glfwPollEvents();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Be sure to activate the shader
glUseProgram(shaderProgram);
// Update the uniform color
GLfloat timeValue = glfwGetTime();
GLfloat greenValue = (sin(timeValue) / 2) + 0.5;
GLint vertexColorLocation = glGetUniformLocation(shaderProgram, "
our Color");
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
// Now draw the triangle
gl Bind VertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
gl Bind Vertex Array(0);
}

 

 

عند تفعيل الشيفرة الخاصة بالبرنامج نستنتج بأن المربع ذات اللون الأخضر هو وامض , بحيث تتغير درجاته صعودا ونزولاً  وفقا لمعادلات المدى التي استخدمناها لتفعيل اللون الأخضر. لكن ماذا لو أردنا تغيير الكود ليعرض الأحمر بدلا من ذلك.

الأمر بسيط للغاية , حيث أن التبديل بين القيمتين هو مفتاح الحل , تماما مثل الشيفرة التالية:

 

glUniform4f(vertexColorLocation, redValue , 0.0f, 0.0f, 1.0f);

كل ما فعلناه هو تغيير اسم المتغير ليظهر بالإسم red Value وبعدها قمنا بتبديل القيم بينهما.

 يونيفورم OpenGL
نتائج تفعيل يونيفورم OpenGL على مستطيل قمنا برسمه مسبقًا.

 

 

المراجع
  1. [1]^ كتاب ـــــــ offline learn OpenGL created by Joey de Vries.
  2. [2]^All About Picking Colors.
  3. [3]^ الشيفرة من كتاب learn OpenGL.

اترك تعليقاً

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