بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته :
كنا قد تكلمنا في السابق عن ذاكرة التقنيع "Stencil" وقد وضحنا اهمية هذه الذاكرة , وعرضنا بعض الامثلة على استخدام هذه الذاكرة , مثل : " إنشاء المرايا , إنشاء الظل للاجسام "
وقد تكلمنا بالجزء الأول عن كيفية إنشاء المرايا , للإطلاع على الجزء الأول مــن هنـــا
سنكمل الحديث اليوم عن هذه الذاكرة وسنستعرض المثال الثاني , الظل .
********************************************************************************
******************
اولا : نقوم بإنشاء مشهد بسيط مثلا :
غرفة بداخلها مرآة وفي منتصفها ابريق شاي " Teapot "
وسأقوم باستخدام إضاءة موجهة Directional واضبط موقعها بحيث تظهر كأنها مسلطة على الجدار الامامي والايمن من الغرفة .
الان وبعد تجهيز المشهد نقوم بكتابة الدالة Set_Shadow والتي ستقوم بإنشاء الظل .
ثانيا : انشاء الظل .
اولا نقوم بملأ ذاكرة Stencil بالقيمة صفر من خلال المنهج Clear
Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,0xffffffff,1.0f,0);
الوسيط السادس يحدد لنا القيمة التي سنملأ بها ذاكرة التقنيع .
بعدها نكتب الدالة Shadow :
اولا: نقوم بتفعيل ذاكرة التقنيع
Device->SetRenderState(D3DRS_STENCILENABLE,true);
بعد ذلك نحدد القيمة المرجعيه Ref وهنا سنغير القيمة المرجعية إلى صفر , بدلا من 1 كما في الدرس السابق لأننا نرغب بإظهار الظل على اي مكان , بخلاف المرآة .
Device->SetRenderState(D3DRS_STENCILREF,0x0);
بعدها نحدد قيمة القناع mask لحجب بتات من ref و value وقناع الكتابة الذي يحجب بتات اي قيمة نقوم بكتابتها داخل ذاكرة Stencil
Device->SetRenderState(D3DRS_STENCILMASK,0xffffffff);
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);
بعد ذلك تأتي مرحلة الاختبار او المقارنة , وقد تكلمنا في الدرس السابق عن مجموعة الحالات الممكنة للاختبار او المقارنة .
سنستخدم في هذه المرة D3DCMP_EQUAL اي ينجح الاختبار في حال تساوي طرفي المقارنة .
Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL)
بعدها نقوم بتحديث ذاكرة التقنيع من خلال :
1 - تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال فشل التقنيع لأي بيكسل
2- تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال فشل العمق Z-Buffer لأي بيكسل
3-تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال نجاح اختبار التقنيع والعمق Z-Buffer لأي بيكسل
ستبقى حجارات الذاكرة Stencil كما هي في حال فشل ذاكرة التقنيع او العمق , اما في حال نجاح اختبار التقنيع او العمق فسنستخدم في هذه المرة الثابت D3DSTENCILOP_INCR والذي يعني بأن قيمة الحجرة ستزيد , وهذا يفيدنا في منع الكتابة على اي بكسل تم الكتابة عليه سابقا , مما يعني عدم حصول مزج مضاعف لانه عند الكتابة لأول مرة على اي بكسل فإن الاختبار سينجح , عندها الثابت D3DSTENCILOP_INCR يفيد بزيادة حجرة التقنيع للبكسل من 0x0 إلى 0x1 بالتالي سيفشل الاختبار عند محاولة الكتابة مرة اخرى على البكسل نفسه , مما يخلصنا من مشكلة المزج المضاعف .
Device->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_INCR);
المرحلة التالية هي انشاء خامة الظل .
سنقوم اولا بتفعيل المزج
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
بعدها نحدد عوامل المزج المناسبة , على سبيل المثال قمنا بتحديد العامل D3DBLEND_SRCALPHA للمصدر , والعامل D3DBLEND_INVSRCALPHA للهدف .
Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
بعدها ننشأ المادة التي ستمثل ظل الابريق , وبعد الانتهاء من انشاء المادة سنقوم بتحديد درجة الشافية إلى 50 %
TeapotMaterial.Diffuse.a=0.5f;
المرحلة التالية , هي التجهيز للرسم .
اولا سنقوم بتحديد المستوى الذي سيرسم عليه الظل , وقد تكلمنا في الدرس السابق عن كيفية تحديد المستويات , على سبيل المثال , في مثالنا الحالي سنقوم بتحديد المركبة y بالقيمة 1-
D3DXPLANE plane(0.0f,-1.0f,0.0f,0.0f);
بعد ذلك سنقوم بتعريف شعاع رباعي لتحديد مكان الضوء اذا كان نقطيا , او اتجاه الضوء اذا كان متوازيا .
D3DXVECTOR4 Dir(-1,-1,-1, 0.0f);
سأتكلم عن المركبة الرابعه w .
اذا كانت w= 1 عندها المركبات الثلاث الاولى تصف موقع الضوء النقطي .
اذا كانت w=0 عندها المركبات الثلاث الاولى تصف اتجاه الضوء المتوازي .
بعد ذلك نقوم بإنشاء الدالة التي تمثل لنا مصفوفة الظل , بحيث الوسيط الاول هو المخرج , والثاني هو الشعاع والثالث هو المستوى :
D3DXMatrixShadow(&S,&Dir,&plane);
بعد ذلك نقوم بكتابة مصفوفة Translation لتحديد مكان الظل على ان يكون هو نفسه مكان الابريق ,
كما يمكننا تعريف متجه عام لتمثل مركباته موقع الابريق والظل في حال الرغبة بتحريك الابريق .
D3DXMatrixTranslation(&T,x,y,z);
الان نقوم بضرب المصفوفتين مع مراعاة الترتيب T اولا ثم S
W=T*S;
Device->SetTransform(D3DTS_WORLD,&W);
بعدها نقوم بتعطيل اختبار العمق وذلك للتخلص مما يسمى Z-Fighting والذي يحدث عندما يكون لسطحين نفس القيم في ذاكرة العمق .
Device->SetRenderState(D3DRS_ZENABLE,false);
المرحلة التالية هي رسم الابريق :
نقوم بتحديد المادة التي انشائنها قبل قليل ومن ثم رسم الابريق
Device->SetMaterial(&TeapotMaterial);
Teapot->DrawSubset(0);
المرحلة الاخيرة هي اعادة تفعيل اختبار العمق , وتعطيل كلا من المزج و التقنيع
Device->SetRenderState(D3DRS_ZENABLE,true);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,false);
Device->SetRenderState(D3DRS_STENCILENABLE,false);
لتصبح النتيجة :
هذا واسأل المولى القدير ان اكون قد وفقت في كتابتي لهذا الدرس , واعتذر عن تأخري في كتابته نظرا لظروفي الدراسية في التيرم السابق .
تحياتي . .