الصفحة الرئيسية/ التقنية / برمجة الألوان : دورة OpenGL لغة c++ الدرس الثالث عشر

برمجة الألوان : دورة OpenGL لغة c++ الدرس الثالث عشر


for Large تمت الكتابة بواسطة : محمد



برمجة الألوان هي إحدى صفات ملفات GLSL التي يمكن استخدامها وتضمينها في مشاريع OpenGL.

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

في العالم الحقيقي يمكن ملاحظة الألوان ونسبها إلى أقرب لون معلوم بشكل جزئي.[1] لكن في العالم الإفتراضي سوف نحتاج إلى برمجة الألوان بواسطة خريطة مكونة من قيم رقمية.

 

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

ومن جهة أخرى تستند الألوان على ثلاث قيم الأحمر والأخضر والأزرق ويمكن اختصارها بالرمز RGB.[1]

نستطيع تمثيل آلاف الألوان من خلال درجات القيم السابقة.[1]

وفيما لو أردنا التعبير عن لون كورال في معادلة الرسم سوف نقوم باستخدام مكتبة متجهات glm على النحو التالي:

glm::vec3 coral(1.0f, 0.5f, 0.31f);

تختلف بالفعل ألوان العالم الحقيقي عن برمجة الألوان في لغات البرمجة ، وفي الواقع فإن أي متغير يستمد لونه من الإنعكاسات.[1]

على سبيل المثال ، ينظر إلى ضوء الشمس على أنه لون أبيض مكون من مجموعة من قيم الألوان التي أنتجت منه ذلك السطوع.

بالتالي لو أردنا إجراء لون لامع على جسم ما لونه أزرق فإن الجسم سوف يمتص جميع الألوان باستثناء اللون الأزرق الذي يحمله.[1]

 

 


برمجة الألوان


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

على سبيل المثال يظهر ذلك جليًا في ألوان قوس قزح عندما تقوم قطرات الماء بالكشف عنه.

وفي حال تم تسليط ضوء الشمس على جسم لونه أحمر ، فإنه سوف سيمتص كافة الألوان الواقعة عليه باستثناء اللون الأحمر الذي بالفعل أظهرتها أشعة الشمس.[1]

بينما يمكن لعين الإنسان أن ترى الجسم باللون الأحمر.[1] يتم تطبيق جميع الوظائف السابقة في برمجة الألوان.

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


مكونات الإضاءة

  1. مصدر الضوء.
  2. جسم قابل لاستقبال الإنعكاس.
  3. نتيجة الانعكاس.

يمكن اختصار جميع ما ذكر في الكود التالي:

glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor;

يعبر متجه toy color عن لون جسم مكون من لون خاص به ، وسوف تلاحظ بأن هذا الجسم سوف يمتص جزء كبير من الضوء.[1]

لكنه يعكس اللون الأحمر بشكل كبير وذلك بسبب أن القيمة الأولى التي تحتوي على الأحمر تأتي بدرجات مشبعة.[1]

 

glm::vec3 lightColor(0.0f, 1.0f, 0.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor;

 

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

   


تطبيق برمجة الألوان


لكي نتمكن من برمجة الألوان لا بد لنا من المرور في ملفات GLSL وخاصة مرحلة fragment shader.[1] وكل ما نحتاجه هو كائن موجود مسبقا ليتم تطبيق المعادلات عليه.[1] 

ومع ذلك في حال كنت لا تجد أي إحداث لتمثيل عمليات الرسم يمكنك مشاهدة المراجع في المرفق أدناه.[2]

بحسب المصادر المرفقة لدينا سوف يتم إلغاء وجود متغيرات texture من ملف vertex Shader ، وبالتالي يمكن إلغاؤها مع الإبقاء على نظام الإحداثيات كما هو.

ولأننا نريد إضافة lamp cube مكعب مضيء ، سوف نقوم بتوليد VAO جديدة لتلك المهمة وخاصة عند برمجة الألوان والأضواء.

نذهب الآن إلى مشروع OpenGL ونقوم بتعيين ملفات VAO من جديد لتصبح على النحو التالي.

GLuint lightVAO;
    glGenVertexArrays(1, &lightVAO);
    glBindVertexArray(lightVAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    glBind Vertex Array(0);

لا يتصف الكود بالصعوبة في بداية برمجة الألوان والأضواء ، بالتالي لن يتم إعداد النسيج Texture أو مصفوفات indices على الإطلاق.

سوف نتجه الآن إلى ملفات shaders لكي نتمكن من إضافة يونيفورم خاص ، يمكن أن يتضمن ذلك متغيرين الأول يشير إلى لون النموذج والثاني يشير إلى نموذج الضوء.  

يعمل كل من الضوء وكائن الجسم المطبق عليه بمعادلات وملفات مختلفة من vertex shader و fragment shader.
بالتالي قد نحتاج إلى إضافة أربع ملفات shader في هذا الدرس.

 


إعداد ملفات GLSL


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

بالتالي قد يتطلب الأمر إضافة ملفات مستقلة ، وفي البداية سنعمل على إضافة ملفي lamp.frag و lamp.vs. ملف lamp.vs

#version 330 core


layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;


void main()
{
   gl_Position = projection * view * model * vec4(position, 1.0f);
}

بما أننا نريد برمجة الألوان في نظام الإحداثيات الجديد ، فإن صفات الضوء يجب أن تحتوي أيضًا على إحداثيات منظور الإسقاط كما تم إرفاقها في الكود. ملف lamp.frag

#version 330 core


out vec4 color;

void main()
{
  color = vec4(1.0f); 
}

يشير الكود السابق إلى أن هذا المتغير يصدر ضوء يتم استلامه وتحديده من قبل مكتبة OpenGL.

على سبيل المثال ، تظهر لنا مكتبة GLSL أن لكل كائن صفات خاصة تمكننا من فصل الملفات وقراءتها فيما بعد عند استدعاء المشروع. ملف lighting.vs

#version 330 core


layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;


void main()
{
   gl_Position = projection * view * model * vec4(position, 1.0f);
}

  ملف lighting.frag

#version 330 core


out vec4 color;
uniform vec3 objectColor;
uniform vec3 lightColor;


void main()
{
   color = vec4(lightColor * objectColor, 1.0f);
}

نلاحظ في الكود السابق أن ملفات lamp ليست سوى ضوء لا يمتلك أي معادلات خاصة من ملفات GLSL.

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

lightingShaders = new OurShaders("C:/Users/Mmutawe/source/repos/Test OpenGL/Test OpenGL/shaders/lighting.vs", "C:/Users/Mmutawe/source/repos/Test OpenGL/Test OpenGL/shaders/lighting.frag");
lampShaders = new OurShaders("C:/Users/Mmutawe/source/repos/Test OpenGL/Test OpenGL/shaders/lamp.vs", "C:/Users/Mmutawe/source/repos/Test OpenGL/Test OpenGL/shaders/lamp.frag");

 

 


إعداد النموذج (Model)


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

سوف يتكون النموذج من الإحداثيات.[2] وتوليد الرسم وتطبيقه في حلقة مكتبة OpenGL.

بالتالي نعمل على نسخ الكود التالي في الدالة الخاصة بمنطقة الإعداد:

GLuint modelVAO;
glGenVertexArrays(1, &modelVAO);
glGenBuffers(1, &VBO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBind Vertex Array(modelVAO);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBind Vertex Array(0);

وفي منطقة الاستدعاء يتم تطبيق الكود التالي:

//******************************************Model code*****************************************************
    lightingShaders->Use();
    GLint object Color Loc = glGetUniformLocation(lightingShaders->Program, "objectColor");
    GLint light Color Loc = glGetUniformLocation(lightingShaders->Program, "lightColor");
    glUniform3f(object Color Loc, 1.0f, 0.5f, 0.31f);
    glUniform3f(light ColorLoc, 1.0f, 0.5f, 1.0f);

    // Create camera 
    glm::mat4 view(1.0);
    view = camera.GetViewMatrix();
    glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)screen Width / (GLfloat)scrnHeight, 0.1f, 100.0f);
    // Get the uniform locations
    GLint modelLoc = glGetUniformLocation(lightingShaders->Program, "model");
    GLint viewLoc = glGetUniformLocation(lightingShaders->Program, "view");
    GLint projLoc = glGetUniformLocation(lightingShaders->Program, "projection");
    // Pass the matrices to the shader
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    // Draw the container (using container's vertex attributes)
    glBind Vertex Array(VAO);
    glm::mat4 model(1.0);
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertex Array(0);
    //***********************************************************************************************************

عند محاولة تفعيل المشروع الآن ستجد النتائج التالية:  

لا بأس في حال قررت عرض الشاشة باللون الأسود ليتم البدء في عملية الإنارة. glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

 


إعداد نموذج الإضاءة


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

glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

  الآن في منطقة إعداد الكائن نعمل على نسخ كود نموذج الإضاءة ليصبح على النحو التالي:

GLuint lightVAO;
glGenVertexArrays(1, &lightVAO);
glBind Vertex Array(lightVAO);
// We only need to bind to the VBO (to link it with glVertexAttribPointer), no need to fill it; the VBO's data already contains all we need.
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Set the vertex attributes (only position data for the lamp))
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBind Vertex Array(0);

بينما يتم تمثيله على الرسم 3D عن طريق الكود التالي:

// Also draw the lamp object, again binding the appropriate shader
    lampShaders->Use();
    // Get location objects for the matrices on the lamp shader (these could be different on a different shader)
    modelLoc = glGetUniformLocation(lampShaders->Program, "model");
    viewLoc = glGetUniformLocation(lampShaders->Program, "view");
    projLoc = glGetUniformLocation(lampShaders->Program, "projection");
    // Set matrices
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
    model = glm::mat4(1.0);
    model = glm::translate(model, lightPos);
    model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    // Draw the light object (using light's vertex attributes)
    glBindVertex Array(lightVAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertex Array(0);

   

     

المراجع

  1. [1]^ كتاب ـــــــ offline learn OpenGL created by Joey de Vries.
  2. [2]^ احداثيات النموذج.
  3. [3]^كائن الكاميرا.
  4. [4]^ كود المشروع من المصادر.

 

وقت النشر : 2023-02-04 21:24:57 ·

1    التصنيفات






2    مقالات من التقنية

يعتمد هذا الموقع على عرض الإعلانات في تحقيق الدخل ، نشكر تفهمكم الدائم ونتمنى لكم قضاء وقت رائع ... وشكراً :D .