الشبكة العربية لمطوري الألعاب

خبير  أحمد عزالدين مشاركة 11

السلام عليكم

وفي 23 يوليو 2008 11:13 م، أعرب وسام البهنسي عن رأيه بالموقف كالآتي:

تخيل معي الحجرة، وبها ثلاث مشاعل مثبتة على الجدار، وكل منها يضيء المكان حوله ضمن نطاق دائرة . كيف نستطيع تنفيذ هذا التأثير؟  إن حيلة الـ mask التي طرحها أحمد صقر جيدة، لكنها تنفع لمشعل واحد فقط ... هل تخيلتم معي الموقف؟

-->> تحدثت انا والاخ سلوان واشكره علي تلميحاته ومساعدته

اعتقد انه يوجد حل مبدئي اتمني ان تتخيلوه وهو مبني علي الفكرة التي يمكن البدء من مفهومها كما بالاتي:



الفكرة ببساطة تعتمد علي تطبيق قناع او ماسك لكل مشعل نود تحريكه وايضا قناع او ماسك للخلفية وكافة المشاعل الثابتة فيها
طبعا صورة قناع الخلفية ستصمم لتظلم darken كل البيكسلات وبها ثقوب مناسبة لاماكن المشاعل الثابتة
للتبسيط:-
 سأطلق علي قناع الخلفية والمشاعل الثابتة:"طبقة الخلفية" وسأطلق علي قناع مشعل اللاعب المتحرك "طبقة مشعل اللاعب"
 ملاحظة مهمة: يجب ان تكون طبقة الخلفية بحجم الشاشة او احجرة وسيتم تطبيقها كاملة
     اما طبقة (صورة) مشعل اللاعب فسيكون حجمها صغيرا ويساوي فقط حجم ضوء المشعل كما بالجزء الاوسط في الصورة العليا.
الان تخيل اننا نريد مشهد يضم الحجرة ومثبت بها 3 مشاعل ثابتة ولا يمكن تحريكها وايضا مشعل متحرك يمكن ان يحمله اللاعب ونريد ان يتحرك مكان ضوئه مع مكان اللاعب.

طريقة رسم هذا التأثير في المشهد
اولا: نرسم الحجرة بالطريقة العادية فتكون مسنيرة بالكامل ثم نرسم مشعل اللاعب لكن قبل ذلك نعدل ذاكرة العمق Depth Buffer
او ذاكرة التنقيع  Stencil Buffer لنسمح الان فقط بالكتابة في ذاكرة العرض ودمج بيكسلات مشعل اللاعب مع بيكسلات الحجرة الموجودة مسبقا
ونراعي تفعيل ال alpha blending المناسبة لاحداث التأثير المرغوب كما بالجزء الايمن في الصورة العليا مثلا
الان نأتي لاخر جزئية في رسم المشهد وهي بالبدء في رسم طبقة الخلفية لتطبيق الاظلام علي الحجرة ولكن فقط نسمح لبيسكلات طبقة الخلفية
بحيث لا تندمج او تسبب overwritten للبيكسلات المكتوبة مسبقا من طبقة مشعل اللاعب
وذلك طبعا بتعديل القيم المناسبة لذاكرة التنقيع Stencil او حتي بالشفافية او بذاكرة ال Depth Buffer (حسب ما نريد)

الان كيف سيتحرك ضوء مشعل اللاعب معه وينير الخلفية كل مرة يناميكيا حسب مكانه
لانه يتم رسم ضوء مشعل اللاعب ودمجه مع الحجرة ومنع بيكسلات طبقة الاظلام والتي يتم رسمها ودمجها في اخر مرحلة من الكتابة فوق البيكسلات الموجودة حاليا فان ذلك يضمن ان يتم ظهور التأثير بطريقة صحيحة
لكن قد توجهنا صعوبة عندما نريد تحريك طبقة مشعل اللاعب - يعني اننا سنقوم بتغيير احداثيات ال mapping كل مرة من صورة مشعل اللاعب حسب مكانه او لنقل اننا سنقوم بحساب Bounding Square من مكان منتصف اللاعب وهذا المربع الوهمي هو المكان الذي سنقوم بتطبيق اكساء صورة مشعل اللاعب فيه وبالطبع حجم هذا المربع هو حجم صورة مشعل اللاعب ومكانه سيتغير مع مكان اللاعب

ارجوا ان تكون قد وصلت الفكرة وان يكون الحل مناسب (مع العلم ان الحل غير مجرب)
الا ان الفكرة ترتكز بصورة كبيرة علي مفهوم ال MultiTexture ومفهوم ال Alpha Blending
ويمكن تعديل امكانية الكتابة في ذاكرتي ال Depth and/or Stencil للحصول علي التأثير المرغوب

في انتظار تعليقكم
والسلام عليكم

أحمد عزالدين
طالب دراسات عليا
جامعة كالجري

خبير مدير وسام البهنسي مشاركة 12

وفي 24 يوليو 2008 02:35 م، قال ahmed ezz متحمساً:

اولا: نرسم الحجرة بالطريقة العادية فتكون مسنيرة بالكامل ثم نرسم مشعل اللاعب لكن قبل ذلك نعدل ذاكرة العمق Depth Buffer
او ذاكرة التنقيع  Stencil Buffer لنسمح الان فقط بالكتابة في ذاكرة العرض ودمج بيكسلات مشعل اللاعب مع بيكسلات الحجرة الموجودة مسبقا
ونراعي تفعيل ال alpha blending المناسبة لاحداث التأثير المرغوب كما بالجزء الايمن في الصورة العليا مثلا

لا تستطيع الاستفادة من ذاكرة العمق لأن جميع مكونات اللعبة يتم رسمها كصور شبحية sprites على عمق ثابت يساوي صفر. أما خيار الـ stencil فقد يكون وارداً.. لكن التأثير الظاهر في الصورة بعيد عما نريد...
 
كي نفهم المطلوب، وما هي المشكلة، سأقوم بالتوضيح بالرسومات:
 
بفرض أن لدينا صورة المرحلة:



فلنتخيل أن اللاعب يحمل الآن مشعلاً، ونريد فقط إظهار المنطقة المحيطة به بشكل دائري. إن فكرة الـ mask تعتمد على استخدام صورة كهذه:
 


وتطبيقها على الشاشة باستخدام الـ alpha blending، ليظهر فقط كل ما يقع داخل الدائرة:
 



والآن فلنفرض أن الوحش الأصفر أيضاً يحمل مشعلاً هو الآخر. نستخدم له قناعاً آخراً خاصاً به:
 


لو طبقنا هذا القناع على المرحلة الأصلية أيضاً، فسنحصل على:
 



الآن نريد إظهار تأثير كلا المشعلين في نفس الوقت. لكن عندما نطبق القناعين سوية على الصورة، فإن ما سيظهر هو:
 



كيف نفهم ما حصل، انظر الصورة الآتية:




 
إن ما حصلنا عليه في النتيجة هو تقاطع للدائرتين وليس اتحاد لهما، وذلك لأن كل منهما تقوم بإظلام المشهد ما عدا ما يقع ضمن الدائرة.
 
يجب علينا الحصول على mask ناتج عن اتحاد الدائرتين أولاً:




ومن ثم تطبيقه مرة واحدة على المرحلة المضاءة بشكل كامل... فنحصل على:



وللتوضيح:



 
التحدي يكمن في فكرة الـ mask بإنتاج القناع النهائي الموحد قبل تطبيقه مرة واحدة على المرحلة المضاءة بشكل كامل...
أرجو أن تكون الفكرة قد وصلت...
 
والآن، هل من أفكار؟  ☺

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

خبير  أحمد عزالدين مشاركة 13

السلام عليكم

أما في 25 يوليو 2008 06:09 ص، فقد تنهد وسام البهنسي بارتياح وهو يرد:

إن ما حصلنا عليه في النتيجة هو تقاطع للدائرتين وليس اتحاد لهما، وذلك لأن كل منهما تقوم بإظلام المشهد ما عدا ما يقع ضمن الدائرة. يجب علينا الحصول على mask ناتج عن اتحاد الدائرتين أولاً:

الا يمكننا تعديل صورتي القناع ودمجهما يدويا بعمل Lock والتعديل علي البيكسلات مباشرة - ام تقصد ان هناك حل اخر بتغيير طريقة تطبيق ودمج الاقنعة مع بعضها

هناك حل اخر بأن نقوم بدمج صور الاقنعة مع بعضهم باستخدام وظائف ال GDI وخصوصا الدوال التي تتيح اختيار نمط ال ROP او ال Raster operation
المناسبة لدمج بيكسلات صورة القناع ال source وصورة القناع ال Dest مع بعضهما.
واظن انه يمكن ايضا عمل نفس الوظيفة بالاعتماد علي بعض دوال ال D3DX وخصوصا الدوال التي تتعامل وتعدل علي ال Textures

ايضا اود ان أتسائل : كيف سنقوم بتخليق القناع كل مرة ليناسب مكان اللاعب وهو يتحرك؟
يعني كيف سنقوم بتخليق صورة القناع والدائرة الموجودة في الصورة والممثلة للمشعل تتحرك؟
الا ينبغي هنا ان نستخدم فقط صورة قناع بحجم المشعل وندمجها في المكان الذي نريده يدويا لينتج لنا القناع النهائي
يعني نقوم بتطبيق عدة اقنعة كل منهم يمثل مشعلا (ولو متحركا) في صورة واحدة يدويا بحيث ان حجم كل صورة قناع مشعل معين لا بد فقط ان تساوي حجم دائرة الضوء
ونعمل نحن الاتحاد بين صور الاقنعة يدويا
ثم نطبق الصورة النهائية

ارجو التوضيح؟
واعذروني علي عدم فهمي الكامل للموضوع بعد
وجزاكم الله خيرا

أحمد عزالدين
طالب دراسات عليا
جامعة كالجري

خبير مدير وسام البهنسي مشاركة 14

كما ذكرت يا أحمد، هناك عدة طرق لتوليد القناع. فقط أحببت أن أوضح أن المشكلة الرئيسية في أسلوب التقنيع الذي ذكره صقر هي في توليد القناع نفسه.
 
لا يمكنك افتراض أماكن ثابتة للمشاعل، لأن اللاعب يستطيع حملها وتحريكها في أي لحظة. لذلك حيلة إعداد القناع بشكل مسبق ليست فعالة.
بسبب أن مواقع المشاعل قد تتغير في كل لقطة، فإننا مضطرون لحساب القناع في كل لقطة (أو على الأقل عند كل تغير في موقع أحد المشاعل)...
 
شخصياً أنا أؤيد تنفيذ التأثير باستخدام التقنيع، لذلك أعتقد أن السؤال الآن هو كيف نقوم بتوليد القناع في كل لقطة بشكل صحيح وسريع؟ 😒
 
الجواب بين أيدينا، فهيا بنا... هذا أول مؤثر جرافيكي حقيقي ننجزه في هذه اللعبة 😄

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

خبير  أحمد عزالدين مشاركة 15

السلام عليكم

وفي 27 يوليو 2008 03:25 م، قال وسام البهنسي متحمساً:

شخصياً أنا أؤيد تنفيذ التأثير باستخدام التقنيع، لذلك أعتقد أن السؤال الآن هو كيف نقوم بتوليد القناع في كل لقطة بشكل صحيح وسريع؟
اذن الان للبدء في استخدام وتطبيق القناع بطريقة ذاكرة التنقيع فاننا سنحتاج لتوليد القناع ليحتوي كل المشاعل الموجودة حاليا في اي لحظة ما
اعتقد للتسهيل مبدئيا يمكننا يمكننا افتراض ان كل مشعل يمثل دائرة لها Bounding Box بحيث لو لدينا اكثر من دائرة فسيكون لدينا اكثر من BB
-- ايضا نعرف ان كل المشاعل ذات حجم ثابت وبالتالي فان حساب ال BB سيكون مرة واحدة فقط وبعدها نضيف مربعات تمثل المشاعل كما نريد
 حسب مكان المشعل في صورة القناع السوداء

لكن ايضا كتحسين عند تنفيذ هذه الطريقة نريد فقط تطبيق القناع اذا كان مكان اللاعب الحالي في المشهد يحتوي علي اي مشاعل سواء ثابتة او متحركة
والا فسنقوم بالرسم دون تفعيل استخدام ذاكرة التنقيع😏

الان لكل مشعل نحدد مكانه ونقوم باضافة مربع ال BB لهذا المشعل في المكان المناسب داخل
صورة قناع مبدئية كلها سوداء وحجمها يمثل حجم الشاشة ثم نقوم بحساب واضافة كل مربع من مربعات المشاعل علي حدة في كل مرة

وذلك بالبدء والتكرار بعدد المشاعل الموجودة ولكل مشعل نجده نقوم باضافة مربع وهمي لونه ابيض داخل الصورة السوادء التي تمثل القناع

يعني الخلاصة هي باضافة مربع ابيض يمثل دائرة المشعل للصورة السوادء وذلك لكل مشعل

وعندها في النهاية سيكون لدينا صورة بها عدد من المربعات البيضاء (حتي لو بعضها متداخل) وعندها نطبق هذا القناع😄

أحمد عزالدين
طالب دراسات عليا
جامعة كالجري

خبير مدير وسام البهنسي مشاركة 16

وفي 27 يوليو 2008 10:29 ص، أعرب ahmed ezz عن رأيه بالموقف كالآتي:

وعندها في النهاية سيكون لدينا صورة بها عدد من المربعات البيضاء (حتي لو بعضها متداخل) وعندها نطبق هذا القناع😄

ظننت أننا نريد دوائر حول المشاعل وليس مربعات؟ 😧
هل يمكنك توضيح كيف ستتحول هذه المربعات إلى دوائر؟

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

خبير  أحمد عزالدين مشاركة 17

السلام عليكم

عذرا ما كنت قصدت المرعات الا للتسهيل
لكن يمكن اضافة دوائر مباشرة لصورة القناع بحيث كل دائرة تمثل المشعل
تخيل لدينا صورة القناع الاسود في الذاكرة والتي بحجم الشاشة والتي نريد اضافة اي دوائر بيضاء لها قبل استخدام صورة القناع لاظلام الحجرة
ولاضافة الدوائر ببساطة يمكننا تجهيز مبدئيا صورة في الذاكرة بحيث تكون علي هيئة دائرة وتكون بحجم المشعل
ثم نقوم بعمل copy او blitting من الصورة البيضاء الي صورة القناع السوداء مع تعديل قيم ال raster operation المناسبة او تعديل قيم الشفافية
وعند نسخ كافة المشاعل حيث كل مشعل في المكان المناسب في صورة القناع السوداء ففي النهاية يكون لدينا صورة القناع السوداء جاهزة وبها اجزاء بيضاء تمثل اماكن المشاعل التي لن يتم يها اظلام الحجرة في هذه الاماكن

اما عن كيفية توليد صورة القناع البيضاء المؤقتة والتي بحجم المشعل والتي سيتم اضافتها في المكان المناسب في صورة القناع السوداء فهذا فقط لا يحتاج الا لمعرفة مكان المشعل وهذا متاح وعندها يمكن نسخ الصورة البيضاء الي القناع الاسود النهائي وذلك بحيث يكون مكان مركز الدائرة عند نسخها الي القناع الاسود هو مكان المشعل حاليا في الشاشة

يعني الفكرة كلها تكمن في تطبيق صورة القناع السوداء وهي بحجم الشاشة حاليا الي المشهد الذي تم رسمه ولكن قبل تطبيق صورة القناع السوداء
يجب اضافة دوائر بيضاء تمثل المشاعل

ولا اري مشكلة الان في عمل التأثير بذلك
يبقي فقط التنويه الي ان الصورة البيضاء يجب ان تكون متدرجة البياض بحيث تعطي تدرج للون المشعل حيث يزداد الاظلام في نهاية ضوء المشعل عن مركزه

عذرا ان كان هناك شئ لا ازال لم افهمه بعد - فأرجو التوضيح
والسلام عليكم

أحمد عزالدين
طالب دراسات عليا
جامعة كالجري

خبير مدير وسام البهنسي مشاركة 18

جميل جداً. الحل الذي وصفته ناجح وفعال. بقي أن نحدد الأدوات التي سنستخدمها لتنفيذه...
لقد ذكرت أنت GDI والقفل المباشر والتعديل. إلا أنني أعتقد أن هناك أسلوب آخر أسرع من هذين الأسلوبين. 😒
 
هل لدى أحد أي فكرة عن أسلوب أسرع؟ أرجو ذكر الأسلوب مع السبب في كونه أسرع من GDI أو القفل اليدوي.

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

محترف مشرف عبد اللطيف حاجي علي مشاركة 19

هل نتكلم هنا عن "خوارزمية" أسرع؟ أم عن "طريقة" أو "تكنيك" أخرى أسرع؟

عبد اللطيف حاجي علي
مبرمج
In|Framez

خبير مدير وسام البهنسي مشاركة 20

في 28 يوليو 2008 08:11 ص، قال عبد اللطيف حاجي علي بهدوء وتؤدة:

هل نتكلم هنا عن "خوارزمية" أسرع؟ أم عن "طريقة" أو "تكنيك" أخرى أسرع؟

نتكلم عن طريقة أو تكنيك أسرع. الخوارزمية صحيحة وناجحة، فقط طريقة تنفيذها تحتاج إلى المزيد من التفكير. فاستخدام GDI لرسم الدوائر على المسطح الأسود في كل لقطة ومن ثم تصعيد هذه الذاكرة إلى الـ VRAM ليس سريعاً، وكذلك قفل المسطح ورسم الدوائر بشكل يدوي لن يكون سريعاً...
نريد طريقة يتم تنفيذها بسرعة ودون تعطيل الـ GPU والانتظار ريثما الـ CPU يقوم بتجهيز القناع. 😒

وسام البهنسي
مبرمج في إنفيديا وإنفريمز