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

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

السلام عليكم

اعتقد لنفس الوضع السابق يمكن عمل الاتي:
يمكن تحسين الوضع قليلا باستخدام Texture في ال Managed Memory بوبالتالي عمل Lock له سيرجع لنا ذاكرة نعدل عليها
والمسئول عن عمل update هو ال D3D
او حتي يمكننا استخدام دوال D3D device المسئولة عن عمل update من الذاكرة والتي هي اسرع من دوال ال GDI
مثل StretchRect أو UpdateSurface

لكن كحل بديل اري ان استخدام ذاكرة التنقيع سيكون اسرع
بان نرسم دوائر المشاعل مباشرة الي ذاكرة التنقيع فقط ثم بعدها نقوم بتفعيل الرسم في ال back buffer حسب ما كتبناه في ذاكرة التنقيع
بحيث لا يتم رسم الا البيكسلات التي لها مناظر يجتاز اختبار ال stencil

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

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

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

وفي 28 يوليو 2008 03:56 م، قال ahmed ezz متحمساً:

يمكن تحسين الوضع قليلا باستخدام Texture في ال Managed Memory بوبالتالي عمل Lock له سيرجع لنا ذاكرة نعدل عليها
والمسئول عن عمل update هو ال D3D
او حتي يمكننا استخدام دوال D3D device المسئولة عن عمل update من الذاكرة والتي هي اسرع من دوال ال GDI
مثل StretchRect أو UpdateSurface

طالما أن هناك Lock فإن الـ CPU سيكون المسؤول عن تعبئة البيانات في الإكساء. وهذا يعني أنك ستضطر لكتابة الكود الذي يقوم برسم الدائرة المصمتة بنفسك. بفرض أن هذا الكود أداؤه خارق وسريع جداً، فإن عملية تصعيد التعديلات إلى الـ VRAM ستبقى بطيئة مهما كانت الطريقة (سواءً UpdateSurface أو غيره).


وفي 28 يوليو 2008 03:56 م، ظهر شبح ابتسامة على وجه ahmed ezz وهو يقول:

لكن كحل بديل اري ان استخدام ذاكرة التنقيع سيكون اسرع
بان نرسم دوائر المشاعل مباشرة الي ذاكرة التنقيع فقط ثم بعدها نقوم بتفعيل الرسم في ال back buffer حسب ما كتبناه في ذاكرة التنقيع
بحيث لا يتم رسم الا البيكسلات التي لها مناظر يجتاز اختبار ال stencil

حل وارد.. لكن ألا ترى معي أنه ملتف قليلاً وسيتطلب تعديلات في كود الرسم في كل جانب من جوانب اللعبة تقريباً؟ 
(مساعدة خفية: Render Target) ـ 😳 ـ

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

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

أما في 28 تموز 2008 11:27 م، فقد تنهد وسام البهنسي بارتياح وهو يرد:

حل وارد.. لكن ألا ترى معي أنه ملتف قليلاً وسيتطلب تعديلات في كود الرسم في كل جانب من جوانب اللعبة تقريباً؟ 
(مساعدة خفية: Render Target) ـ 😳 ـ

أوو.. أوو.. أعرفها
لما لا نقوم بتحديد الـ render target كـ texture بحجم النافذة ثم نقوم باستخدام هذا الـ texture كـ mask?
ممم... أعتقد أن هذه الطريقة ستشغل الـ GPU بدلاً عن الـ CPU. هل في هذا مشكلة؟

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

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

في 29 يوليو 2008 05:54 ص، غمغم عبد اللطيف حاجي علي باستغراب قائلاً:

أوو.. أوو.. أعرفها
لما لا نقوم بتحديد الـ render target كـ texture بحجم النافذة ثم نقوم باستخدام هذا الـ texture كـ mask?
ممم... أعتقد أن هذه الطريقة ستشغل الـ GPU بدلاً عن الـ CPU. هل في هذا مشكلة؟

إطلاقاً. هذا هو الحل الأمثل! 😄
 
نقوم بإنشاء إكساء بصيغة تعمل كـ Render Target، وقبل البدء بكل لقطة، نضع هذا الإكساء كهدف للرسم، ونرسم عليه الدوائر البيضاء باستخدام مربعات مكسية بإكساء دائرة (أو حتى أي شكل آخر).
بعد الانتهاء من رسم الدوائر، نعيد الـ back buffer الأصلي كهدف للرسم، ونرسم المرحلة كاملةً، ومن ثم نطبق عليها الإكساء الذي جهزناه للتو.
 
بهذه الطريقة، فإن الـ CPU سيعمل بشكل مستقل تماماً عن الـ GPU. إذ أن كل ما يفعله هو فقط إرسال الأوامر، وسينفذها الـ GPU بسعادة ودون أي تدخل.
 
والآن، من يود تنفيذ هذه الميزة في اللعبة؟ ☺
 
مبدئياً وحتى يتم دعم المشاعل بشكل كامل، فلنفرض أن المستكشف والوحوش جميعها تحمل مشاعلاً بيدها وهي تتحرك.

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

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

السلام عليكم

هذه اول محاولة لي لتطبيق التأثير باستخدام طريقة ال Render Target

للاسف حدثت معي مشاكل اثناء تنفيذ الطريقة فقمت بفصل كود تأثير هذه الطريقة
ووضعته في مشروع منفصل صغير جدا لتجربة الطريقة علي حدة
لكن يظهر لي عدة اخطأ اولها رسالة تحذير تخبرني بالاتي:
Direct3D9: (WARN) :Can not render to a render target that is also used as a texture. A render target was detected as bound, but couldn't detect if texture was actually used in rendering.بصراحة لم افهم كيف احل المشكلة
لقد جعلت الكود يحاول انشاء اكساء يمكن استخدامه كـ  render target
ثم بجعله هو ال main render target مع حفظ ال old render target
بعد ذلك ابدأ بالرسم بطريقة عادية وذلك برسم مربع ابيض بدون اكساء علي خلفية اللاكساء الذي من المفترض ان يتم الرسم عليه الان
ثم بعد ذلك ارجع ال render target الاصلي لكن تظهر الرسالة كما بالاعلي
المفترض انني اضع الاكساء الان وارسمه
لقد ارفقت المشروع وهو اعتقد انه مفتاح لحل المشكلة في كود المشروع عندي

عذرا سأرفق المشروع قريبا

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

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

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

تأكد من أن الإكساء غير مربوط مع الـ device أثناء الرسم عليه كـ render target. فلو كنت قد ربطت الإكساء باستخدام كود كهذا:
 

pDevice->SetTexture(0,pRenderTargetTexture);
 
فقم بإزالة الربط قبل نداء SetRenderTarget كهكذا:
 

pDevice->SetTexture(0,NULL);
 
ومن ثم:


pDevice->SetRenderTarget(pTextureRTSurface);
 
وعند الانتهاء من الرسم على الـ render target، فقم بإعادة الـ back buffer واربط الإكساء مرة أخرى مع الـ device.

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

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

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

شكرا اخي وسام علي التوضيح

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

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

السلام عليكم

اخي وسام هذا اخر كود كتبته وهو لا يظهر النتيجة بالرغم من تجربته في كود منفصل وهو يعمل بنجاح
لقد ارفقت اخر كود للمشروع عندي
ايضا الكود يتسبب في تسريب للذاكرة لا ادري سببه وفقط يحدث التسريب اذا تم الدخول لاي مرحلة للعب
هناك ايضا استفسار بالنسبة للدالة CoreLib::LibGetD3DDevice(); 
هل تقوم هذه الدالة تلقائيا بزيادة ال RefCount ام لا لان معرفة ذلك ضرورية لتجنب تسريب للذاكرة
كذلك هل يتم استدعاء ال BeginScene قبل دخول الدالة من قبل ال CoreLib
حيث سبب لي ذلك الكثير من المشاكل عند اول محاولة لكتابة الكود
الان لقد عدلت الكثير من الكود وقمت بحفظ قيم كافة ال device state التي اغيرها اثناء الكود واسترجعها
طبعا الكود يحتاج للتنظيم وهو فقط بهذا الشكل لان التعديل فيه كثير لاخراج الناتج

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

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

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

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

وفي 30 يوليو 2008 08:04 ص، ظهر شبح ابتسامة على وجه ahmed ezz وهو يقول:

هناك ايضا استفسار بالنسبة للدالة CoreLib::LibGetD3DDevice(); 
هل تقوم هذه الدالة تلقائيا بزيادة ال RefCount ام لا لان معرفة ذلك ضرورية لتجنب تسريب للذاكرة

كلا. الـ RefCount للـ device يبقى ثابتاً عند استخدام هذا الإجراء.
 
 

أما في 30 يوليو 2008 08:04 ص، فقد تنهد ahmed ezz بارتياح وهو يرد:

هل يتم استدعاء ال BeginScene قبل دخول الدالة من قبل ال CoreLib

نعم. عندما تكون داخل الإجراء GameApp::OnDraw فإن BeginScene يكون قد تم نداؤه مسبقاً، ولن تحتاج لندائه بنفسك. مما يعني أن جميع نداءات BeginScene و EndScene التي قمت بإضافتها لا داعي لها 😨 .

 

في 30 يوليو 2008 08:04 ص، غمغم ahmed ezz باستغراب قائلاً:

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

لديك أحد خيارين. إما أن تستخدم نقاط transformed وتقوم بتعديل إحداثياتها بنفسك في كل لقطة، أو أن تستخدم نقاط نظامية وتضبط المصفوفات بشكل صحيح للرسم ثنائي البعد، مما سيعيد تأثير أي مصفوفة تستخدمها لتحريك المربع الذي ترسمه.
 
يمكنك أيضاً استخدام DrawPrimitiveUP و DrawIndexedPrimitiveUP مع نقاط transformed لتريح نفسك من عناء تعديل مكونات الـ vertex buffer في كل لقطة.

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

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

السلام عليكم

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

ايضا الصور الاتيه توضح مشكلة قابلتني ولم افهم لماذا

في هذه الصورة نلاحظ انه لما يكون اللاعب في احدي زوايا الحجرة فان ضوء المربع يكون علي مسافة منه والمفترض ان يكون في نفس مكان اللاعب



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


مع اني متأكد من احداثيات كل شئ

ايضا هناك مشكلة غريبة لاحظ في الصورتين كلمة Konami في اسفل الصورة غير كاملة وهذا غير منطقي فالمفترض ان لا يتم اظلام المناطق التي
فوق الحجرة او اسفلها وبالرغم من اني دعلت الكود ليتم تصحيح ذلك الا اني لم اجد سببا للمشكلة هذه ولقد حاولت استخدام pix لتتبع عرض
المشكلة الا انه من الغريب ان اوامر الرسم التي استخدمتها لمنع القناع من اظلام المناطق الخارجة عن الحجرة الا ان هذه الاوامر لا اجدها تؤثر في
نافذة ال render اسفل يمين ال pix

هذا هو الكود المسئول عن منع القناع من اظلام المناطق الخارجية ويتم رسمه مبدئيا في القناع
	CoreLib::Begin2D();	
	// draw up white rect	
	CoreLib::SplashFill(0xFFFFFFFF, 0, 0, CHAMBER_TOP-1, SCREEN_WIDTH);
	// draw down white rect
	CoreLib::SplashFill(0xFFFFFFFF, CHAMBER_BOTTOM, 0, SCREEN_HEIGHT , SCREEN_WIDTH);	
	// draw left white rect
	CoreLib::SplashFill(0xFFFFFFFF, 0, 0, SCREEN_HEIGHT, CHAMBER_LEFT-1);
	// draw right white rect
	CoreLib::SplashFill(0xFFFFFFFF, 0, CHAMBER_RIGHT, SCREEN_HEIGHT, SCREEN_WIDTH);	

الكود كله تقريبا في الكلاس GameState_Play في الملف stateFlow.cpp

هناك في الكود بعض التعليقات التي تركتها وسيتم تنفيذها فيما بعد لكن بعد ان ننتهي من تنفيذ التأثير بنجاح
وهي تتعلق مثلا بعدم اظلام المربع game over box والذي يظهر عند الضغط علي F3
وايضا ان نحسن من عمل كود الاضاءة بجعله يعمل فقط في حالة كان تصميم الحجرة به مشاعل واظلام واضاءة والا لا ننفذ اصلا كود تأثير الاضاءة

تم اضافة دوال للتحويل من مكان اللاعب او الوحش حيث كان المكان يتم وصفه بالنوع fixed وكان (relative to chamber (bottom-left
هذه الدوال تقوم بتحويل هذا الاحداثي الي مكان بيكسل في الشاشة (top-left)
ارجو ايضا توضيح النوع fixed ولماذا نقوم بحفظ القيمة فيه بعد عمل shift لها 16 مرة

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

اسف علي الاطالة - اعلم اني اتكلم كثيرا
في انتظار مشاركة الجميع
والسلام عليكم

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