Beberapa bulan yang lalu, saya kembali mengeluarkan PSP berdebu dari sebuah kotak dan memutuskan untuk port
mesin saya yang sebelumnya ditampilkan di
sana . Tidak ada masalah dengan perenderan perangkat lunak - semuanya berjalan seperti ini. Tetapi menggunakan GU tidak sesederhana itu. Pada artikel ini, saya akan menunjukkan kepada Anda contoh bagaimana Anda dapat menulis aplikasi tiga dimensi sederhana untuk PSP menggunakan GU.
Saya memperingatkan Anda sebelumnya bahwa tidak ada panduan pemrograman yang cukup untuk PSP, dan karena itu beberapa kesimpulan saya mungkin ternyata salah. Tapi, to the point.
Fungsi utama program untuk PSP, jika ada yang tidak tahu, tampilannya seperti ini:
#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); }
Inisialisasi GU adalah sebagai berikut:
Pertama, kami meminta pointer ke tiga buffer - layar, off-screen, dan buffer kedalaman (Z-buffer). Buffer disejajarkan pada 512 piksel per baris (meskipun PSP memiliki garis 480 piksel). Anda juga perlu mempertimbangkan format warna piksel. Dalam contoh ini, format GU_PSM_8888 digunakan - 8 bit per R, G, B dan komponen Alpha dari warna piksel. Untuk Z-buffer, format GU_PSM_4444 digunakan hanya karena 16 bit - 16-bit Z-buffer PSP.
Fungsi untuk query pointer ke buffer didefinisikan sebagai
#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()))); }
Ini bukan fungsi saya - saya mengambilnya dari beberapa program sejak lama dan hanya sedikit berubah. Memori dialokasikan di area memori video. Tekstur juga harus ditempatkan di sana jika memungkinkan, meminta pointer melalui getStaticVramTexture, jika tidak kinerjanya akan turun tajam. Tentu saja, tidak ada memori dinamis yang dialokasikan selama permintaan tersebut, tetapi hanya sebagian dari ruang alamat PSP yang ditentukan dialokasikan untuk layar dan tekstur. Sejauh yang saya ingat, PSP hanya memiliki 2 megabita memori video - sangat kecil untuk menyimpan banyak tekstur.
Pemrograman GU PSP mirip dengan pemrograman untuk OpenGL dengan satu perbedaan - pelaksanaan perintah memerlukan penempatannya dalam daftar tampilan, dan memori untuk daftar ini harus dialokasikan sebelumnya dan disejajarkan:
static unsigned char __attribute __ ((aligned (16))) DisplayList [262144];
Perintah yang terkait dengan transformasi koordinat tidak memerlukan daftar tampilan dan dapat dijalankan di mana saja dalam program ini.
Anda dapat menginisialisasi GU, misalnya, seperti ini:
Setelah menyelesaikan pekerjaan dengan GU, Anda perlu memanggil sceGuTerm ().
Setelah memuat tekstur ukuran (WidthImage; HeightImage) dengan cara apa pun yang nyaman (penunjuk Data ke data tekstur - dan lebih baik mendapatkannya di area memori video), kami dapat menampilkannya.
Bagaimana cara menampilkan poligon? Untuk menggambar geometri GU, PSP meminta untuk meletakkan semua titik dalam sebuah array, penunjuk yang pertama-tama harus diperoleh dengan perintah sceGuGetMemory, meneruskan ukuran blok memori yang diminta dalam byte. Lebih jauh ke bawah pointer ini, Anda harus menulis array poin dan meminta PSP untuk menampilkannya, misalnya, dengan perintah sceGumDrawArray dengan parameter yang diperlukan. Tetapi bagaimana format dari titik-titik ini? Untuk PSP, data titik disusun dalam urutan tertentu dan ukuran array yang menggambarkan satu titik harus kelipatan 32 byte: bobot titik, koordinat tekstur, warna titik, normal ke titik, koordinat titik. Dalam urutan itu. Agar tidak repot dengan format, saya mendefinisikan satu set struktur dan fungsi untuk bekerja dengan mereka:
Kemudian Anda dapat menentukan geometri (dalam hal ini, kuadrat), misalnya, seperti ini:
Dan mengeluarkannya, misalnya, seperti ini:
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); }
Untuk output, saya menunjukkan fungsi sceGumDrawArray apa yang sebenarnya saya gambar dan apa format intinya (GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D | GU_NORMAL_32BITF | GU_TEXTURE_32BITF - titik terdiri dari warna, koordinat yang sesuai dengan tekstur, koordinat, dan tekstur dengan koordinat), dengan titik yang terdiri dari warna, koordinat, dan tekstur dengan koordinat titik yang diperlukan. Menggambar hanya mungkin dengan segitiga. Tapi itu belum semuanya ...
Segalanya tampak bekerja, tetapi hanya berfungsi jika semua titik ada di depan mata dan terlihat. Setelah setidaknya satu titik masuk ke jarak berkabut, GU menolak untuk menggambar seluruh poligon. Seperti yang saya pahami, GU PSP mensyaratkan bahwa, relatif terhadap empat pesawat kliping (kiri, kanan, atas dan bawah (dan yang depan akan berubah secara otomatis)), intinya terletak di dalam volume ini, jika tidak, GU tidak setuju untuk menampilkannya. Masalah Namun dalam game, grafik 3D hadir dan artefak seperti itu tidak diamati! Mari kita lihat bagaimana mereka memecahkan masalah ini di PSP Quake 1, karena sumber tersedia untuk analisis.
Apa yang kita lihat dari analisis sumber? Namun faktanya, inilah yang:
Yaitu, dalam Gempa 1, sebelum kesimpulan, mereka hanya memindahkan semua poin ke bagian dalam volume yang membatasi tampilan, atau membuangnya sama sekali (jika keseluruhan gambar tidak terlihat). Bagaimana cara melakukannya? Anda hanya perlu membaca tiga matriks - GU_PROJECTION, GU_MODEL, GU_VIEW. Lipat gandakan dan dapatkan matriks transformasi koordinat akhir. Dari matriks ini, Anda dapat menarik semua bidang yang diperlukan untuk membatasi tampilan (4 komponen vektor yang dihasilkan menentukan bidang dengan persamaan kapak + oleh + cz + w = 0). (a, b, c) adalah vektor normal, dan w = a * x0 + b * y0 + c * z0 - mencirikan titik tertentu (x0, y0, z0) dari pesawat. Kita tidak membutuhkan koordinat titik itu sendiri - cukup ketahui w.
Kliping dilakukan sebagai berikut (untuk empat pesawat yang disebutkan di atas dalam satu siklus):
Tetapi untuk fokus ini, kita memerlukan fungsi-fungsi berikut (dinonaktifkan dari Quake 1):
Dan hanya setelah melakukan cut-off seperti itu, Anda akhirnya akhirnya dengan benar menerima output grafis tiga dimensi pada PSP menggunakan GU. Anda bisa membuat game! :)

Omong-omong, Anda juga dapat menggunakan prosesor vektor PSP untuk produk skalar vektor. Sebagai contoh, berikut adalah fungsi yang menentukan apakah kliping diperlukan sama sekali (dirobek berkeping-keping dari Gempa 1 yang sama untuk PSP):
Semuanya sederhana di sini - mereka menempatkan vektor bidang dan titik koordinat dalam register dan meminta VFPU untuk melakukan produk skalar.
→
Tautan ke aplikasi tampilan tekstur paling sederhana
→
Tautan ke mesin PSP menggunakan GU
PS Saya tahu ada pemrograman profesional untuk PSP. Mungkin mereka akan memberi tahu Anda mengapa GU PSP diatur sedemikian rupa dan cara menggunakannya dengan benar.