يونيفورم OpenGL وهو طريقة أخرى لتمرير البيانات من مشروعنا إلى وحدة CPU ومن ثم إلى وحدة معالجة الرسومات GPU.[1] لكن يونيفورم OpenGL يختلف قليلاً عند المقارنة مع سمات Vertex.
حيث تعبر يونيفورم OpenGL عن متغيرات عامة ما يعني أنها متغيرات فريدة من نوعها لكل ظل من ظلال GLSL يجري استخدامه.[1]
تعمل متغيرات يونيفورم بشكل عام لحظة عمل المشروع ويتم الوصول إليها من قبل أي ظلال يتم تضمينها في عملية الرسم.[1] وبالتالي يتم الاحتفاظ بكافة القيم طوال حياة البرنامج.
بينما يتم الإشارة إلى يونيفورم OpenGL بطريقة سهلة وبسيطة فهي تحمل العبارة uniform بالانجليزية مع نوع المتجه المراد استخدامه ومن ثم يتم تمريرها إلى المراحل القادمة من GLSL.[1]
الآن وبعد أن أدركنا بأن 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]
نلاحظ في الكود السابق بأن متغير يونيفورم OpenGL هو فارغ تمامًا في شيفرة المشروع ولم يتم إرفاق أية بيانات له. ولذلك نحاول إجراء بعض التعديلات على البرنامج.[1]
نحتاج الآن البحث عن أماكن 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]
الآن كل ما نريد فعله هو تفعيل القيم التي ذكرناها في السابق ويتطلب ذلك وضعها في حلقة 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 وبعدها قمنا بتبديل القيم بينهما.