فى هذه المشاركة اريد ان القى الضوء على موضوع جيد هو Blending
ترجمتى الشخصية لهذه الكلمة "الدمج" (لاننا ندمج اكثر من لون حتى نحصل على
اللون المطلوب).
تخيل انك تقف فى النقطة 0,0,0 و تنظر فى اتجاه النقطة 0,0,1 و كان هناك ابريق
يقع على النقطة 0,0,5 و اخر فى النقطة 0,0,3.
فى عملية الرسم لهذا المشهد, يمكن ان نرسم الابريق الاول فى الاول و الابريق الثانى فى النهاية
او العكس. فاذا رسمنا الاول فى الاول و الثانى فى النهايةفى هذه الحالة سوف يحدث الاتى:-
يتم رسم الابريق الاول و يطبق نوع ال Culling و الاضاءات .... الى بقية ال pipeline الى ان يوضع
فى شكل pixels على ال Back Buffer.
و عند رسم الابريق الثانى, فى البداية ترسم كل الpixels التى لا تقاطع اى pixel نتج من رسم الابريق الاول.
كل الpixels التى تقع فى الابريق الاول (التى رسمها فى ال BackBuffer الابريق الاول)و التى يغطيها اخوه
الثانى, سوف يتم استبدالها بالاخرى التى تتبع للابريق الثانى.
اذا تم عكس العملية و تم رسم الا بريق الثانى فى الاول و الابريق الاول فى الثانى
(قد تبدو هذه الجملة مربكة قليلا) سيتم:-
رسم الابريق الثانى كاملا.
عند رسم الابريق الاول يتم رسم النقاط pixels التى تقع على الاول و لا تتقاطع مع الابريق الثانى.
اما ال pixels التى تتقاطع مع الابريق الثانى(و التى هى اساسا جذء من الابريق الاول " تذكر انه لايمكن ان نراها
لانها تقع ال الخلف منه على حسب موقع الكاميرا و موقع كل من الابريقين" ) لن يتم رسمها
لان الZ-Buffer Test سوف يفشل و لن ترسم نهائيا.
هذا جميل اليس كذلك. فى كل من هاتين الحالتين ستكون النتيجة هى نفسها ( الشئ الذى يقوله المنطق).
انا احبذ الطريقة الاولى و التى يمكن ان نستعمل ال Blending فيها.
ييمكنك الملاحظة بكل سهولة ان هناك عملية كتابة pixels فوق الاخرى. هذه العملية تمت فى ال pixels
التى كانت فى الابريق الاوال و غطاها الابريق الثانى قد استبدلت بال pixles الجديدة الاتية من الابريق الثانى.
اى ان
ال pixel النهائى و لنعطه الرمز C الناتج من رسم ال pixel A فى نقطة كانت تحوى ال pixel B.
لنرى كيف تم ذلك فى الحالة الاوالى.
C = A
اعتقد ان هذا واضح فقد استبدلت ال pixels التى كانت للابريق الاول بالاخرى التى جاءت من الابريق الثانى.
اى ان الpixel القديم لا وجود له فى المعادلة اى انه لا يؤثر.
الصيغة العامة لهذه المعادلة.
C = a*A + b*B
فى حالتنا هذه a = 1 و b = 0
هذان المعاملان هما اساس عملية ال blending و بالتحكم فى قيم هذه المعاملات نستطيع ان ننتج تاثيرات
رائعة و جميلة. من البديهى ان تكون الشفافية هى المع هذه التاثيرات و من اجمل ما يمكن ان ينجزه ال blending
يعنى مثلا اذا استطعنا تغيير قيم الثابتين a , b
حيث
a = b = 0.50
سوف نحصل على شفافية لا باس بها اليس كذلك؟
لكن الموضوع ليس بهذه البساطة ف Direct3D لا يسمح بتعيين قيم مباشرة لكل من الثابتين كما فعلنا للتو.
و كل الاحتمالات لقيم aوb محددة فى ال enum D3DBLEND . من الوهلة الاولى قد تظن ان هذا يقييد
البرمجة الى حد كبير و كل المسات الجمالية التى تود ان تنتجها بهذه التقنية البسيطة الرائعة. لكن العكس هو
الصحيح, على سبيل المثال مع القيم الموجودة فى D3DBLEND يمكنك ان تحور المعادلة الى الاتى:-
C = A*B
الشئ الذى يستحيل تنفيذه مع لمعاملين aوb اليس كذلك؟
لنتحدث بالاكواد و نترك الكلام الكثير الذى قد لا يدخل الراس.
لكى تقوم بعملية blending نا جحة عليك بالاتى
1/ تفعيل ال belnding :-
فى الحالة الافتراضية يكون غير مفعل, اى انه لن يتم عمل معادلة و سوف نطبق C = A و نحن مغمضين.
و لتفعيل هذه العمليه عليك ب السطر التالى:-
g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
و لكن لا تكتب هذا السطر فى ال RestoreDeviceObjects لان عملية ال belnding يكمن ان تكون
مكلفة الى حد لا نريد ان تكون مفعلة طوال الوقت. لذلك اذا و فقط اذا احتجت الى ال blending يسمح لك
ان تكتب هذا السطر. بشرط ان تكتب السطر التالى لايقاف ال blending عند انتهائك منه.
g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
اى ان كل من السطرين يجب ان يكونا داخل الدالة Render.
سيكون ذلك واضحا اذا تابعت المثال المرفق.
2/ الشئ الثانى و هو الذى يمثل جوهر عملية ال belnding هو المعملات التى تتحكم فى المعادلة.
المعامل الذى قمنا بتسميته a يسمى Source Blend Factor و b يسمى Destination Blend Factor.
يمكننا ضبط العملين بالسطرين التاليين على التوالى.
g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,Source);
g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND,Destination);
3/ الشئ الثالث هو انه لا يوجد هناك شئ فقط قم بقراءة المثال و تلاعب به جيدا فقد تركت لك
الكثير لكى تجربه وحدك.
نصيحة:
فكر معى جيدا, حيث اننا لو غيرنا الترتيب فى عملية الRendering فستحدث اشياء غير متوقعة
اى ان ال Z-BufferTest يسبق عملية الBlending فى الترتيب فى ال pipeline. لذلك يمكن ان يسبب
دوران الكاميرا فى اى لحظة فى تعطيل عملية ال blending. مما يجبرك ان تقوم بترتيب عملية الرسم لكل
من الابريقين على حسب موقع الكاميرا الان (اى بعدها من كل ابريق).
ملاحظة: استخدام ال blending فى الصور قد يعطى تاثيرات جميلة و لكن من مساوئه انه يستهلك زمن
كبيرلتكرار الرسم. مما يرشح استخدام multiple stages لانجاز هذه التاثيرات. لكن لا غنى عن ال blending ابدا.
فكر معى, لما؟
ملاحظة اخرى:
يبو ان ملاجظاتى قد كثرت لكن استحملنى ليها القارئ!
كان من المفترض ايقاف ال culling حتى يبدو الشكل الطبيعى, اى ان الشفافية التى نحصل عليها تقل
كلما زاد عدد الطبقات (ال culling سوف يقوم بحذف الطبقات الخلفية), لكن التجربة العملية تثبت العكس,
لانه عند ايقاف ال culling تضيع الشفافية. هذا من الاجذاء التى تركت للمناقشة بعد طرح الموضوع.
