قبل شهرين ، أخرجت مرة أخرى PSP متربة من صندوق وقررت نقل محركي الذي أظهرته سابقًا
هناك . لم تكن هناك مشاكل في عرض البرامج - كل شيء يعمل بهذه الطريقة. لكن استخدام GU لم يكن بهذه البساطة. في هذه المقالة ، سأوضح لك مثالًا لكيفية كتابة تطبيق بسيط ثلاثي الأبعاد لـ PSP باستخدام GU.
أحذرك مقدمًا من عدم وجود أدلة برمجة كافية لـ PSP ، وبالتالي قد تتضح أن بعض استنتاجاتي غير صحيحة. ولكن ، في صميم الموضوع.
الوظيفة الرئيسية لبرنامج PSP ، إذا كان أي شخص لا يعرف ، يبدو كما يلي:
#include <pspkernel.h> #include <pspdebug.h> #include <pspdisplay.h> //---------------------------------------------------------------------------------------- PSP_MODULE_INFO("GUTexture", 0, 1, 1); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER|THREAD_ATTR_VFPU); void dump_threadstatus(void); bool done=false; int exit_callback(int arg1,int arg2,void *common) { done=true; return(0); } int CallbackThread(SceSize args, void *argp) { int cbid; cbid=sceKernelCreateCallback("Exit Callback",exit_callback,NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return(0); } int SetupCallbacks(void) { int thid = 0; thid=sceKernelCreateThread("update_thread",CallbackThread,0x11,0xFA0,0,0); if(thid>=0) sceKernelStartThread(thid, 0, 0); return(thid); } //---------------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------------- int main(int argc, char **argv) { pspDebugScreenInit(); // SetupCallbacks(); // ………. // sceKernelExitGame(); return(0); }
تهيئة GU على النحو التالي:
أولاً ، نطلب مؤشرات إلى ثلاثة مخازن مؤقتة - حاجز للشاشة ، وخارج الشاشة ، ومخزن للعمق (Z-buffer). تتم محاذاة المخازن المؤقتة عند 512 بكسل لكل سطر (على الرغم من أن PSP يحتوي على خط 480 بكسل). تحتاج أيضًا إلى مراعاة تنسيق لون البكسل. في هذا المثال ، يتم استخدام التنسيق GU_PSM_8888 - 8 بت لكل مكون من مكونات R و G و B و Alpha بلون البكسل. بالنسبة إلى المخزن المؤقت Z ، يتم استخدام تنسيق GU_PSM_4444 ببساطة لأنه 16 بت - المخزن المؤقت Z 16 بت الخاص بـ PSP.
يتم تعريف وظيفة الاستعلام عن المؤشرات إلى المخازن المؤقتة على أنها
#include <pspge.h> #include <pspgu.h> static unsigned int staticOffset=0; static unsigned int getMemorySize(unsigned int width,unsigned int height,unsigned int psm) { switch (psm) { case GU_PSM_T4: return((width*height)>>1); case GU_PSM_T8: return(width*height); case GU_PSM_5650: case GU_PSM_5551: case GU_PSM_4444: case GU_PSM_T16: return(2*width*height); case GU_PSM_8888: case GU_PSM_T32: return(4*width*height); default: return(0); } } void* getStaticVramBuffer(unsigned int width,unsigned int height,unsigned int psm) { unsigned int memSize=getMemorySize(width,height,psm); void* result=(void*)staticOffset; staticOffset+=memSize; return(result); } void* getStaticVramTexture(unsigned int width,unsigned int height,unsigned int psm) { void* result=getStaticVramBuffer(width,height,psm); return((void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr()))); }
هذه ليست وظائفي - لقد أخذتها من برنامج ما منذ فترة طويلة ولم تتغير إلا قليلاً. يتم تخصيص الذاكرة في منطقة ذاكرة الفيديو. يجب أيضًا وضع القوام هناك إذا أمكن ، وطلب مؤشر من خلال getStaticVramTexture ، وإلا سينخفض الأداء بشكل حاد. بالطبع ، لا يتم تخصيص ذاكرة ديناميكية أثناء هذه الطلبات ، ولكن ببساطة يتم تخصيص جزء من مساحة عنوان PSP المحددة للشاشة والقوام. بقدر ما أتذكر ، فإن PSP لا يحتوي إلا على 2 ميغابايت من ذاكرة الفيديو - وهي صغيرة جدًا لتخزين الكثير من الأنسجة.
تشبه برمجة PSP GU البرمجة الخاصة بـ OpenGL بفارق واحد - يتطلب تنفيذ الأوامر وضعها في قائمة العرض ، ويجب تخصيص ذاكرة هذه القائمة مسبقًا ومواءمتها:
حرف ثابت غير موقّع __صفة __ ((محاذاة (16))) DisplayList [262144] ؛
لا تتطلب الأوامر المتعلقة بتنسيق التحويل قائمة عرض ويمكن تنفيذها في أي مكان في البرنامج.
يمكنك تهيئة GU ، على سبيل المثال ، مثل:
بعد الانتهاء من العمل مع GU ، من الضروري استدعاء sceGuTerm ().
بعد تحميل نسيج الحجم (WidthImage ؛ HeightImage) بأي طريقة مناسبة (مؤشر البيانات إلى بيانات النسيج - ومن الأفضل الحصول عليه في منطقة ذاكرة الفيديو) ، يمكننا عرضه.
كيفية عرض مضلع؟ لرسم هندسة GU ، يطلب PSP وضع جميع النقاط في مصفوفة ، يجب الحصول على المؤشر أولاً باستخدام الأمر sceGuGetMemory ، بتمريره حجم كتلة الذاكرة المطلوبة بالبايت. بعد هذا المؤشر ، يجب كتابة مجموعة من النقاط واطلب من PSP عرضها ، على سبيل المثال ، باستخدام الأمر sceGumDrawArray مع المعلمات الضرورية. ولكن ما هو شكل هذه النقاط؟ بالنسبة لـ PSP ، يتم ترتيب بيانات النقاط بترتيب معين ويجب أن يكون حجم المصفوفة التي تصف نقطة واحدة مضاعفات 32 بايت: وزن الرأس ، إحداثيات النسيج ، لون النقطة ، عادي إلى نقطة ، إحداثيات نقطة. بهذا الترتيب. لكي لا تهتم بالتنسيق ، حددت مجموعة من الهياكل والوظائف للعمل معها:
ثم يمكنك تحديد الشكل الهندسي (في هذه الحالة ، المربع) ، على سبيل المثال ، مثل:
وإخراجها ، على سبيل المثال ، مثل هذا:
size_t vertex_amount=vector_point.size(); SGuNVCTPoint *sGuNVCTPoint_Ptr=(SGuNVCTPoint*)sceGuGetMemory(vertex_amount*sizeof(SGuNVCTPoint)); if (sGuNVCTPoint_Ptr!=NULL) { for(size_t n=0;n<vertex_amount;n++) sGuNVCTPoint_Ptr[n]=vector_point[n]; sceGumDrawArray(GU_TRIANGLE_FAN,GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D|GU_NORMAL_32BITF|GU_TEXTURE_32BITF,vertex_amount,0,sGuNVCTPoint_Ptr); }
للإخراج ، أشرت إلى وظيفة sceGumDrawArray إلى ما أرسمه بالضبط وما هو تنسيق النقطة (GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D | GU_NORMAL_32BITF | GU_TEXTURE_32BITF - النقطة تتكون من اللون ، الإحداثيات ، العادي ، إحداثيات المصفوفة وتتطلب الضرب). الرسم ممكن فقط مع المثلثات. ولكن هذا ليس كل شيء ...
يبدو أن كل شيء يعمل ، ولكنه يعمل فقط إذا كانت جميع النقاط أمام العين ومرئية. بمجرد أن تصل نقطة واحدة على الأقل إلى مسافة ضبابية ، يرفض GU رسم المضلع بأكمله. كما أفهمها ، يتطلب GU's PSP ، بالنسبة إلى طائرات القطع الأربع (اليسار واليمين والجزء العلوي والسفلي (وستتحول الواجهة الأمامية تلقائيًا)) ، تكمن النقطة داخل هذا المجلد ، وإلا لن يوافق GU على عرضه. مشكلة. ولكن في الألعاب ، توجد رسومات ثلاثية الأبعاد ولا يتم ملاحظة مثل هذه القطع الأثرية! دعونا نرى كيف حلوا هذه المشكلة في PSP Quake 1 ، حيث أن المصادر متاحة للتحليل.
ماذا نرى من تحليل المصدر؟ لكن في الواقع ، هذا ما يلي:
أي في Quake 1 ، قبل الاستنتاج ، يقومون ببساطة بنقل جميع النقاط إلى داخل المجلد الذي يقيد العرض ، أو يطرحها تمامًا (إذا لم يكن الرقم بالكامل مرئيًا). كيف تفعل ذلك؟ تحتاج فقط إلى قراءة ثلاث مصفوفات - GU_PROJECTION ، GU_MODEL ، GU_VIEW. اضربهم واحصل على مصفوفة تحويل الإحداثيات النهائية. من هذه المصفوفة ، يمكنك سحب جميع الطائرات اللازمة لتقييد العرض (4 مكونات للمتجه الناتج تحدد مستوى مع فأس المعادلة + بواسطة + cz + w = 0). (a، b، c) هو المتجه العادي ، و w = a * x0 + b * y0 + c * z0 - يميز نقطة معينة (x0 ، y0 ، z0) للمستوى. نحن لسنا بحاجة إلى إحداثيات النقطة أنفسنا - فقط نعرف ث.
يتم تنفيذ القطع على النحو التالي (للطائرات الأربع المذكورة أعلاه بدورها في دورة):
ولكن من أجل هذا التركيز ، نحتاج إلى الوظائف التالية (خرجت من الزلزال 1):
وفقط بعد إجراء مثل هذا القطع ، ستحصل أخيرًا بشكل صحيح أخيرًا على إخراج رسومات ثلاثية الأبعاد على PSP باستخدام GU. يمكنك إنشاء لعبة! :)

بالمناسبة ، يمكنك أيضًا استخدام معالج ناقل PSP للمنتج القياسي للمتجهات. على سبيل المثال ، فيما يلي وظيفة تحدد ما إذا كان القطع مطلوبًا على الإطلاق (ممزق إلى قطع من نفس Quake 1 لـ PSP):
كل شيء بسيط هنا - وضعوا ناقلات المستوى وإحداثيات النقطة في السجلات وطلبوا من VFPU أداء المنتج القياسي.
→
رابط إلى أبسط تطبيق عرض نسيج
←
ارتباط بمحرك PSP باستخدام GU
PS أعرف أن هناك مهنيين برمجة لـ PSP. ربما سيخبرونك عن سبب ترتيب PSP GU وكيفية التعامل معه بشكل صحيح.