Tampilkan grafik 3D di PSP

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.

 //  #define SCREEN_WIDTH 480 #define SCREEN_HEIGHT 272 #define SCREEN_LINE_WIDTH 512 void* fbp0=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_8888); void* fbp1=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_8888); void* zbp=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_4444); 

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:

 //    PSP #define VIRTUAL_SCREEN_SIZE 2048 //   #define SCREEN_ASPECT 16.0f/9.0f //   #define NEAR_PLANE_Z 5.0f //   #define FAR_PLANE_Z 4096.0f //  #define EYE_ANGLE 60.0f //  GU sceGuInit(); //        -    , .. GU_DIRECT sceGuStart(GU_DIRECT,DisplayList); //   -  ,    ,   (,   ) sceGuDrawBuffer(GU_PSM_8888,fbp0,SCREEN_LINE_WIDTH); //    -  ,   ,   sceGuDispBuffer(SCREEN_WIDTH,SCREEN_HEIGHT,fbp1,SCREEN_LINE_WIDTH); //   -           sceGuDepthBuffer(zbp,SCREEN_LINE_WIDTH); //      4096x4096 ( PSP    ) sceGuOffset(VIRTUAL_SCREEN_SIZE-(SCREEN_WIDTH/2),VIRTUAL_SCREEN_SIZE-(SCREEN_HEIGHT/2));//   //   -  -      sceGuViewport(VIRTUAL_SCREEN_SIZE,VIRTUAL_SCREEN_SIZE,SCREEN_WIDTH,SCREEN_HEIGHT); //      -      (     0  65535 !) sceGuDepthRange(65535,0); //        sceGuScissor(0,0,SCREEN_WIDTH,SCREEN_HEIGHT); sceGuEnable(GU_SCISSOR_TEST); sceGuEnable(GU_CLIP_PLANES); //   sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(EYE_ANGLE,SCREEN_ASPECT,NEAR_PLANE_Z,FAR_PLANE_Z); //      sceGuShadeModel(GU_SMOOTH); //   sceGuDepthFunc(GU_GEQUAL); sceGuEnable(GU_DEPTH_TEST); sceGuDepthMask(GU_FALSE); //   ,      sceGuFrontFace(GU_CCW); sceGuDisable(GU_CULL_FACE); //  sceGuDisable(GU_BLEND); sceGuBlendFunc(GU_ADD,GU_SRC_ALPHA,GU_ONE_MINUS_SRC_ALPHA,0,0); //   sceGuFinish(); sceGuSync(GU_SYNC_WAIT,GU_SYNC_FINISH); sceGuDisplay(GU_TRUE); 

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.

  //  sceGuStart(GU_DIRECT,DisplayList); //     sceGuClearColor(0); sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); //   sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(EYE_ANGLE,SCREEN_ASPECT,NEAR_PLANE_Z,FAR_PLANE_Z); sceGumUpdateMatrix();. //  sceGumMatrixMode(GU_TEXTURE); sceGumLoadIdentity(); sceGumMatrixMode(GU_VIEW); sceGumLoadIdentity(); sceGumMatrixMode(GU_MODEL); sceGumLoadIdentity(); //    sceGuColor(0xffffffff);//  sceGuEnable(GU_TEXTURE_2D); sceGuTexMode(GU_PSM_8888,0,0,0); sceGuTexImage(0,WidthImage,HeightImage,WidthImage,Data); sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA); sceGuTexFilter(GU_NEAREST,GU_NEAREST); sceGuTexWrap(GU_REPEAT,GU_REPEAT); sceGuTexScale(1,1); sceGuTexOffset(0,0); //      … sceGuDisable(GU_TEXTURE_2D); //    sceGuFinish(); sceGuSync(GU_SYNC_WAIT,GU_SYNC_FINISH); //  ,     sceDisplayWaitVblankStart(); sceGuSwapBuffers(); 

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:

 //#pragma pack(1) //[for vertices(1-8)] [weights (0-8)] [texture uv] [color] [normal] [vertex] [/for] #pragma pack(1) //  struct SGuVertex { float X; float Y; float Z; }; //   struct SGuNormal { float Nx; float Ny; float Nz; }; //  struct SGuTexture { float U; float V; }; //  struct SGuColor { unsigned long Color; }; #pragma pack() #pragma pack(32) //  , , ,  struct SGuNVCTPoint { SGuTexture sGuTexture; SGuColor sGuColor; SGuNormal sGuNormal; SGuVertex sGuVertex; }; #pragma pack() void SetVertexCoord(SGuVertex &sGuVertex,float x,float y,float z);//   void SetNormalCoord(SGuNormal &sGuNormal,float nx,float ny,float nz);//   void SetTextureCoord(SGuTexture &sGuTexture,float u,float v);//   void SetColorValue(SGuColor &sGuColor,unsigned long color);//  //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetVertexCoord(SGuVertex &sGuVertex,float x,float y,float z) { sGuVertex.X=x; sGuVertex.Y=y; sGuVertex.Z=z; } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetNormalCoord(SGuNormal &sGuNormal,float nx,float ny,float nz) { sGuNormal.Nx=nx; sGuNormal.Ny=ny; sGuNormal.Nz=nz; } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetTextureCoord(SGuTexture &sGuTexture,float u,float v) { sGuTexture.U=u; sGuTexture.V=v; } //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void CMain::SetColorValue(SGuColor &sGuColor,unsigned long color) { sGuColor.Color=color; } 

Kemudian Anda dapat menentukan geometri (dalam hal ini, kuadrat), misalnya, seperti ini:

  //  SGuNVCTPoint sGuNVCTPoint; vector<SGuNVCTPoint> vector_point; SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,0,0); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,100,100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,1,0); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,100,-100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,1,1); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,-100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,0,1); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); 

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:

  //   sceGumMatrixMode(GU_PROJECTION); ScePspFMatrix4 projection_matrix; sceGumStoreMatrix(&projection_matrix); //    sceGumMatrixMode(GU_VIEW); ScePspFMatrix4 view_matrix; sceGumStoreMatrix(&view_matrix); //   sceGumMatrixMode(GU_MODEL); ScePspFMatrix4 model_matrix; sceGumStoreMatrix(&model_matrix); sceGuFinish(); //   view-projection ScePspFMatrix4 projection_view_matrix; MultiplyScePspFMatrix4(view_matrix,projection_matrix,projection_view_matrix); //   view-projection-model ScePspFMatrix4 projection_view_model_matrix; MultiplyScePspFMatrix4(model_matrix,projection_view_matrix,projection_view_model_matrix); //  view-model ScePspFMatrix4 view_model_matrix; MultiplyScePspFMatrix4(model_matrix,view_matrix,view_model_matrix); //      (, , , ) ScePspFVector4 frustum[4];//   : ax+by+cz+d=0 // frustum[0].x=projection_view_model_matrix.x.w+projection_view_model_matrix.xx; frustum[0].y=projection_view_model_matrix.y.w+projection_view_model_matrix.yx; frustum[0].z=projection_view_model_matrix.z.w+projection_view_model_matrix.zx; frustum[0].w=projection_view_model_matrix.w.w+projection_view_model_matrix.wx; NormaliseScePspFVector4(frustum[0]); // frustum[1].x=projection_view_model_matrix.xw-projection_view_model_matrix.xx; frustum[1].y=projection_view_model_matrix.yw-projection_view_model_matrix.yx; frustum[1].z=projection_view_model_matrix.zw-projection_view_model_matrix.zx; frustum[1].w=projection_view_model_matrix.ww-projection_view_model_matrix.wx; NormaliseScePspFVector4(frustum[1]); // frustum[2].x=projection_view_model_matrix.xw-projection_view_model_matrix.xy; frustum[2].y=projection_view_model_matrix.yw-projection_view_model_matrix.yy; frustum[2].z=projection_view_model_matrix.zw-projection_view_model_matrix.zy; frustum[2].w=projection_view_model_matrix.ww-projection_view_model_matrix.wy; NormaliseScePspFVector4(frustum[2]); // frustum[3].x=projection_view_model_matrix.x.w+projection_view_model_matrix.xy; frustum[3].y=projection_view_model_matrix.y.w+projection_view_model_matrix.yy; frustum[3].z=projection_view_model_matrix.z.w+projection_view_model_matrix.zy; frustum[3].w=projection_view_model_matrix.w.w+projection_view_model_matrix.wy; NormaliseScePspFVector4(frustum[3]); 

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):

  //  vector<SGuNVCTPoint> vector_clip_point; for(long n=0;n<4;n++) { float nx=frustum[n].x; float ny=frustum[n].y; float nz=frustum[n].z; float w=frustum[n].w; Clip(vector_point,vector_clip_point,nx,ny,nz,w); vector_point=vector_clip_point; } 

Tetapi untuk fokus ini, kita memerlukan fungsi-fungsi berikut (dinonaktifkan dari Quake 1):

 //---------------------------------------------------------------------------------------------------- //      //---------------------------------------------------------------------------------------------------- void CMain::GetIntersectionPlaneAndLine(const SGuNVCTPoint& A,const SGuNVCTPoint& B,SGuNVCTPoint& new_point,float nx,float ny,float nz,float w) { new_point=A; float ax=A.sGuVertex.X; float ay=A.sGuVertex.Y; float az=A.sGuVertex.Z; float au=A.sGuTexture.U; float av=A.sGuTexture.V; float bx=B.sGuVertex.X; float by=B.sGuVertex.Y; float bz=B.sGuVertex.Z; float bu=B.sGuTexture.U; float bv=B.sGuTexture.V; float dx=bx-ax; float dy=by-ay; float dz=bz-az; float du=bu-au; float dv=bv-av; float top=(nx*ax)+(ny*ay)+(nz*az)+w; float bottom=(nx*dx)+(ny*dy)+(nz*dz); float time=-top/bottom; float vx=ax+time*dx; float vy=ay+time*dy; float vz=az+time*dz; float vu=au+time*du; float vv=av+time*dv; //   SetVertexCoord(new_point.sGuVertex,vx,vy,vz); SetTextureCoord(new_point.sGuTexture,vu,vv); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::Clip(const vector<SGuNVCTPoint>& vector_point_input,vector<SGuNVCTPoint>& vector_point_output,float nx,float ny,float nz,float w) { vector_point_output.clear(); long point=vector_point_input.size(); for(long n=0;n<point;n++) { long next_p=n+1; if (next_p>=point) next_p-=point; const SGuNVCTPoint *sGuNVCTPoint_Current_Ptr=&(vector_point_input[n]); float current_vx=sGuNVCTPoint_Current_Ptr->sGuVertex.X; float current_vy=sGuNVCTPoint_Current_Ptr->sGuVertex.Y; float current_vz=sGuNVCTPoint_Current_Ptr->sGuVertex.Z; //     float current_ret=current_vx*nx+current_vy*ny+current_vz*nz+w; const SGuNVCTPoint *sGuNVCTPoint_Next_Ptr=&(vector_point_input[next_p]); float next_vx=sGuNVCTPoint_Next_Ptr->sGuVertex.X; float next_vy=sGuNVCTPoint_Next_Ptr->sGuVertex.Y; float next_vz=sGuNVCTPoint_Next_Ptr->sGuVertex.Z; //     float next_ret=next_vx*nx+next_vy*ny+next_vz*nz+w; if (current_ret>0)//   { if (next_ret>0)//   { vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr); } else { //    SGuNVCTPoint sGuNVCTPoint_New; GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w); vector_point_output.push_back(sGuNVCTPoint_New); } } else//    { if (next_ret>0)//   { //    SGuNVCTPoint sGuNVCTPoint_New; GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w); vector_point_output.push_back(sGuNVCTPoint_New); //   vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr); } } } } 

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):

 //  vector<SGuNVCTPoint> vector_clip_point; //   PSP __asm__ volatile ( "ulv.q C700, %0\n" //    "ulv.q C710, %1\n" //    "ulv.q C720, %2\n" //    "ulv.q C730, %3\n" //    :: "m"(FrustumPlane[0]),"m"(FrustumPlane[1]),"m"(FrustumPlane[2]),"m"(FrustumPlane[3]) ); //   long vertex=vector_point.size(); bool clipping=false; for(long n=0;n<vertex;n++) { ScePspFVector4 current_vertex; current_vertex.x=vector_point[n].sGuVertex.X; current_vertex.y=vector_point[n].sGuVertex.Y; current_vertex.z=vector_point[n].sGuVertex.Z; current_vertex.w=1; float ret1,ret2,ret3,ret4; __asm__ volatile ( "ulv.q C610, %4\n" //      "vone.s S613\n" //       "vdot.q S620, C700, C610\n" // s620 =    "vdot.q S621, C710, C610\n" // s621 =    "vdot.q S622, C720, C610\n" // s622 =    "vdot.q S623, C730, C610\n" // s623 =    "mfv %0, S620\n" // out1 = s620 "mfv %1, S621\n" // out2 = s621 "mfv %2, S622\n" // out3 = s622 "mfv %3, S623\n" // out4 = s623 : "=r"(ret1), "=r"(ret2), "=r"(ret3), "=r"(ret4) : "m"(current_vertex) ); if (ret1<0 || ret2<0 || ret3<0 || ret4<0)//  { clipping=true; break; } } 

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.

Source: https://habr.com/ru/post/id406049/


All Articles