بتـــــاريخ : 3/1/2011 10:09:49 PM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 1638 0


    [دروس] تعلم كيفية الاستفادة من ذاكرة التقنيع Stencil الجزء الثاني ( إنشاء الظلال)

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : time1 | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :

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

    السلام عليكم ورحمة الله وبركاته :

    كنا قد تكلمنا في السابق عن ذاكرة التقنيع "Stencil" وقد وضحنا اهمية هذه الذاكرة , وعرضنا بعض الامثلة على استخدام هذه الذاكرة , مثل : " إنشاء المرايا , إنشاء الظل للاجسام "

    وقد تكلمنا بالجزء الأول عن كيفية إنشاء المرايا , للإطلاع على الجزء الأول
    مــن هنـــا

    سنكمل الحديث اليوم عن هذه الذاكرة وسنستعرض المثال الثاني , الظل .

    ********************************************************************************
    ******************

    اولا : نقوم بإنشاء مشهد بسيط مثلا :
    غرفة بداخلها مرآة وفي منتصفها ابريق شاي " Teapot "

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

    ارفق صورة : monthly_07_2008/post-82612-1215671243.jpg

    الان وبعد تجهيز المشهد نقوم بكتابة الدالة 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);


    لتصبح النتيجة :

    ارفق صورة : monthly_07_2008/post-82612-1215671268.jpg

    ارفق صورة : monthly_07_2008/post-82612-1215672047.jpg

    هذا واسأل المولى القدير ان اكون قد وفقت في كتابتي لهذا الدرس , واعتذر عن تأخري في كتابته نظرا لظروفي الدراسية في التيرم السابق .

    تحياتي . .

    كلمات مفتاحية  :

    تعليقات الزوار ()