time1

تعلم كيفية الاستفادة من ذاكرة التقنيع Stencil الجزء الأول

5 ردود في هذا الموضوع

بسم الله الرحمن الرحيم

سأتكلم من خلال درسي هذا عن جزء مهم في برمجة الجرافيكس , وهو ذاكرة التقنيع او مايعرف بـ Stencil

تقدم لنا ذاكرة التقنيع فوائد عديدة تمكننا من اضفاء جماليات على المشاهد يصعب انشاءها الا بالعمليات الرياضية المعقدة ,

سنأخذ على سبيل المثال انشاء المرايا وادخالها داخل المشهد ..

انشاء المرايا :

تكمن الفكرة بأنه يوجد جزء من المشهد يمثل المرآة تنعكس من خلاله اي جسم يمر من امامه ولهذا يجب ان نأخذ بعين الاعتبار بأن هذا الجسم المنعكس يجب ان لاينعكس الا اذا وقع امام هذه المرآة اما اذا وقع امام اي جسم اخر فأنه لاينعكس .

نستطيع ان نكون المرآة من خلال عمليات رياضيه معقدة تسمى برياضيات الانعكاس , ولكن سنستخدم هنا طريقة ابسط توفرها لنا ذاكرة التقنيع Stencil ......

انشاء المرايا بواسطة ذاكرة التقنيع Stencil

سنقسم الموضوع إلى ثلاثة اقسام :

اولا: انشاء المشهد مع المرايا ..

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

post-82612-1208114050_thumb.jpg

بعد ذلك انشأنا مجسم كسوناه بخامة ثلجية لتمثل لنا جسم المرآة .

سنقوم بجعل هذه المرآة تعكس ابريق الشاي فقط اذا كان امام هذه المرآة اما اذا كان امام الجدار فإنه لاينعكس .

ثانيا : انشاء المرآة

اولا نقوم بملأ ذاكرة Stencil بالقيمة صفر من خلال المنهج Clear

		Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,0xffffffff,1.0f,0);

الوسيط السادس يحدد لنا القيمة التي سنملأ بها ذاكرة التقنيع .

ثانيا : ننشأ الدالة Mirror التي ستمثل لنا الانعكاس .

داخل هذه الدالة نقوم بتفعيل ذاكرة التقنيع Stencil

	Device->SetRenderState(D3DRS_STENCILENABLE,true);

بعد ذلك نحدد القيمة المرجعية ref والتي هنا ستكون 1

ان مانقوم به هو ملأ الذاكرة باكملها بالقيمة 0 ثم تحديد المرآة وملأها بالقيمة 1 وهذا من شأنه يمنع تصيير مناطق معينة بالذاكرة .

	Device->SetRenderState(D3DRS_STENCILREF,0x1);

بعدها نحدد قيمة القناع mask لحجب بتات من ref و value وقناع الكتابة الذي يحجب بتات اي قيمة نقوم بكتابتها داخل ذاكرة Stencil

	Device->SetRenderState(D3DRS_STENCILMASK,0xffffffff);
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);

الان تبقى لنا مرحلة الاختبار او المقارنة وهي حالة من احدى الحالات التاليه :

D3DCMP_NEVER : وهي تحدد بأن الاختبار لن ينجح ابدا .

D3DCMP_LESS : ينجح عندما يكون الطرف الايسر من المقارنة اصغر من الطرف الايمن

D3DCMP_EQUAL: ينجح الاختبار عندما يتساوى طرفي المقارنة.

D3DCMP_LESSEQUAL : ينجح الاختبار في حالة طرف المقارنة الايسر اصغر من او يساوي طرف المقارنة الايمن .

D3DCMP_GREATER: ينجح الاختبار في حالة طرف المقارنة الايسر اكبر من طرف المقارنة الايمن .

D3DCMP_NOTEQUAL : ينجح الاختبار عندما يكون طرفا المقارنة غير متساويين .

D3DCMP_ALWAYS: ينجح الاختبار دائما .

هناك بقية من انواع الاختبارات لكن هذه اهمها .

سنختار هنا نجاح الاختبار دائما .

	Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);

بعدها نقوم بتحديث ذاكرة التقنيع من خلال :

1 - تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال فشل التقنيع لأي بيكسل

2- تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال فشل العمق Z-Buffer لأي بيكسل

3-تحديد الطريقة التي يتم فيها تحديث اي حجرة من حجرات ذاكرة التقنيع في حال نجاح اختبار التقنيع والعمق Z-Buffer لأي بيكسل :

ويمكن ان نعطي لكل حالة قيمة من مجموعة القيم التاليه :

D3DSTENCILOP_KEEP : تبقى حجرات الذاكرة كما هي وبنفس قيمها السابقة .

D3DSTENCILOP_REPLACE: سيتم استبدال حجرات الذاكرة بالقيمة المرجعيه ref

D3DSTENCILOP_ZERO : عندها ستصبح قيمة الحجرات صفرا.

هناك العديد من القيم المعرفة مسبقا والتي يمكن اعطائها للحالات السابقة ولكن هذه اهمها .

في مثالنا هذا سنبقي الحجرات كما هي عليه في حال فشل اختبار العمق والتقنيع ولكن سنغير القيمة إلى القيمة المرجعيه في حال نجاح الاختبار , ولو دققنا الملاحظة سنجد ان القيم ستتغير دائما وذلك لاننا قلنا بأن الاختبار سينجح دائما !!

	Device->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE);

الجزء التالي هو رسم المرآه فقط إلى ذاكرة التقنيع Stencil ومنع الكتابة على ذاكرة الاماميه Target او ذاكرة العمقZbuffer

	Device->SetRenderState(D3DRS_ZWRITEENABLE,false);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);

نقوم بإعادة رسم المرآة ولكن هذه المرة إلى ذاكرة التقنيع ,

هنا سيحدث انه سيكون فقط الجسم الذي يمثل لنا المرآة يحمل القيمة المرجعية 1 اما بقية اجزاء الغرفة تحمل القيمة 0 والتي تم اعطائها عندما تم ملأ ذاكرة التقنيع بهذا من خلال المنهج Clear

قمنا بتعطيل الكتابة للذاكرة الامامية Target من خلال المزج Blending بتحديد المصدر صفر والهدف 1 , وناتج هذه المعادلة سيكون نفس قيمة الذاكرة الامامية Target

	Device->DrawPrimitive(D3DPT_TRIANGLELIST,30,2);

post-82612-1208114321_thumb.jpg

الان نقوم بإعادة تفعيل ذاكرة العمق والذاكرة الامامية مرةاخرى

	Device->SetRenderState(D3DRS_ZWRITEENABLE,true);
Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);

الان حان موعد رسم الابريق المعكوس على المرآة , وهنا سيكون الاختبار هذه المرة فقط في حال التساوي ونلاحظ هنا بأنه لن يتساوى الا مع المرآة والتي سبق ان قمنا بملأها بالقيمة المرجعيه 1

اما في حال النجاح فأننا نجعل القيم كما هي D3DSTENCILOP_KEEP

	Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);

نقوم بتجهيز الرسم

1- نحدد السطح الذي سيتم الانعكاس عليه , ونعكس مركبة z لاننا نرغب في هذا المثال بعكس المستوى xy

اما في حال رغبتنا بعكس المستوى yz فأننا نعكس المركبة x وهكذا ....إلخ

2-ننشأ مصفوفة الانعكاس D3DXMatrixReflect

	D3DXPLANE plane(0,0,1,0);
D3DXMatrixReflect(&R,&plane);
D3DXMatrixTranslation(&T,Tr.x,Tr.y,Tr.z);
W=T*R;

Device->SetTransform(D3DTS_WORLD,&W);

رسم الابريق

نرسم الابريق في ذاكرة العمق ZBuffer مع مراعاة تعديل غربلة الاوجه إلى D3DCULL_CW لتصحيح الخطأ الذي ينتج عن الانعكاس

	Device->Clear(0,0,D3DCLEAR_ZBUFFER,0,1,0);
Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);

وفي نهاية الدالة نقوم بإعادة الوضع كما كان ,نلغي تفعيل ذاكرة التقنيع Stencil ونلغي المزج ونعيد ضبط الغربلة إلى D3DCULL_CCW

	Device->SetRenderState(D3DRS_STENCILENABLE,false);
Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,false);

وهنا ستكون النتيجة :

post-82612-1208114119_thumb.jpg

في المرة القادمة سنتعلم كيفية إنشاء ظلال للاجسام من خلال ذاكرة التقنيع Stencil ..

وشكرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

رائع و نتمني المزيد .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكرا جزيلا اخي الكريم

انا اقدر جدا جهدك في هذا الموضوع بل اعترف لك انه احد اروع ما طرح في هذا المتندى الى حد الان و كما يبدو فانك على المام جيد ، فالموضوع يعالج احد اعمق الافكار في ديراكت اكس ، كما ارجو ان تواصل في شرح ماتبقى كالظل .. و ساكون شاكرا فلقد وفقت جدا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

-

تم تعديل بواسطه sharks
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .