| |

تمثيل الإضاءة : دورة OpenGL لغة c++

هناك العديد من أنواع تمثيل الإضاءة لكي نتمكن من محاكاة أنواع مختلفة من مصادر الضوء و تحقيق مزايا العالم الحقيقي.[1]

بالتالي يتم الآن مناقشة الضوء ذات الإتجاه والتعمق في مفهوم spotlight ، ما يعني دمج العديد من الأدوات في المشهد الواحد.[1]

 

 


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

 


تمثيل الإضاءة ذات الإتجاه


غالبا ما تشير الأضواء ذات الاتجاه إلى أشعة الضوء القادمة من مصدر الضوء بشكل موازي للنموذج.[1]

ما يعني أن جميع مصادر الإضاءة كانت قادمة من مصدر واحد مع الأخذ بعين الاعتبار مواقع مختلفة من النموذج.[1]

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

عند استخدام أضواء ذات اتجاه في تمثيل الإضاءة فإننا نستغني عن متغير position في ملف model.frag ونضع مكانه vec3 direction.[1]

بالتالي سوف نقوم بإجراء تعديل على Structure الإضاءة ليصبح على النحو التالي:

struct Light {
// vec3 position; // No longer necessary when using directional lights.
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};

نجري أيضًا تعديل على متغير lightDir ليصبح على النحو التالي:

vec3 lightDir = normalize(-light.direction);

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

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

بالتالي يتم تطبيق الكود التالي في المشروع وهو عبارة عن حلقة تكرارية لتمثيل 10 مكعبات باتجاهات عشوائية.[1]

for(GLuint i = 0; i < 10; i++)
{
model = glm::mat4();
model = glm::translate(model, cubePositions[i]);
GLfloat angle = 20.0f * i;
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}

نقوم الآن بتفعيل تمثيل الإضاءة من خلال يونيفورم في حلقة while الخاصة بالمشروع على النحو التالي:

GLint lightDirPos = glGetUniformLocation(lightingShaders->Program, "light.direction");
        glUniform3f(light Dir Pos, -0.2f, -1.0f, -0.3f);

 


الإضاءة النقطية (Point light)


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

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

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

يمكن استخدام معادلة attenuation  أيضا على ضبابية المشهد (جو مغبر مليء بالضباب).[1]

نقوم الآن بتنفيذ الكود التالي على structure الخاص بـ model.frag. ليصبح على النحو التالي:

struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};

الآن نقوم بتعيين الشروط والقيم بالتالي يتم التواصل مع معادلات الضباب على أنها يونيفورم.

ندعوك إلى اضافة الكود التالي في المشروع.

glUniform1f(glGetUniformLocation(lightingShaders->Program, "light.constant"),1.0f);
    glUniform1f(glGetUniformLocation(lightingShaders->Program, "light.linear"),0.09);
    glUniform1f(glGetUniformLocation(lightingShaders->Program, "light.quadratic"), 0.032);

يعد تطبيق معادلات attenuation أمر مباشر في ملف model.frag.[1] ، وبالتالي يتم حساب القيم بناء على ضرب المتجهات بـ ambient.

كما يمكن إعداد تمثيل الإضاءة عن طريق احتساب المسافة distance لمصادر الضوء.[1] نقوم أولا بإضافة المعادلة التالية في ملف model.frag.[1]

float distance = length(light.position - Position);
float attenuation = 1.0f / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));

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

وبالتالي يمكن الاعتماد على معادلة Point light في محركات الرسم حيث أنها لا تستنزف الكثير من الموارد.[1]


تمثيل الإضاءة على أضواء الكشاف (Spotlight)


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

على سبيل المثال عند تشغيل كشاف ضوئي على حائط نلاحظ وجود دائرة ضوئية منبثقة في الإضاءة.[1]

يتطلب منا تطبيق تمثيل الإضاءة spotlight العديد من التعديلات على كود model.frag متمثلة بإضافة متغيرين الأول متجه direction والثاني هو زاوية cut off وهي المسؤولة عن قص الإضاءة بشكل دائري.[1]

بالتالي نعمل على إضافة المتغيرين إلى light structure:

vec3 direction;
float cutOff;

نقوم بالاتصال في هذه المتغيرات عن طريق معادلات يونيفورم التالية:

GLint lightSpotdirLoc = glGetUniformLocation(lightingShaders->Program, "light.direction");
    GLint lightSpotCutOffLoc = glGetUniformLocation(lightingShaders->Program, "light.cutOff");

    glUniform3f(lightPosLoc, camera.Position.x, camera.Position.y,camera.Position.z);
    glUniform3f(light Spot dir Loc, camera.Front.x, camera.Front.y, camera.Front.z);
    glUniform1f(lightSpotCutOffLoc, glm::cos(glm::radians(12.5f)));

الآن يتم إجراء تغيير على كود void main المتعلق بملف model.frag على النحو التالي:

vec3 lightDir = normalize(light.position - FragPos);
   
   // Check if lighting is inside the spotlight cone
   float theta = dot(lightDir, normalize(-light.direction)); 
   
   if(theta > light.cutOff) .
   {    
       // Ambient
       vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
       
       // Diffuse 
       vec3 norm = normalize(Normal);        
       float diff = max(dot(norm, lightDir), 0.0);
       vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));  
       
       // Specular
       vec3 viewDir = normalize(viewPos - FragPos);
       vec3 reflectDir = reflect(-lightDir, norm);  
       float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
       vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
       
       // Attenuation
       float distance    = length(light.position - FragPos);
       float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    

       // ambient  *= attenuation;    ambient lighting).
       diffuse  *= attenuation;
       specular *= attenuation;   
               
       color = vec4(ambient + diffuse + specular, 1.0f);  
   }
   else    .
       color = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0f);

 

المراجع
  1. [1]^ كتاب ـــــــ offline learn OpenGL created by Joey de Vries.
  2. [2]^ مشروع Directional light ______  ملف model.frag.
  3. [3]^ مصادر مشروع Point light _________ ملف model.frag.
  4. [4]^ مشروع Spot light __________ ملف model.frag.
تقييم هذا المنشور

Similar Posts

اترك تعليقاً

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