/* * PSP Software Development Kit - https://github.com/pspdev * ----------------------------------------------------------------------- * Licensed under the BSD license, see LICENSE in PSPSDK root for details. * * rendertarget.c - Sample to demonstrate usage of ofscreen * texture as a render target * * Copyright (c) 2005 Jesper Svennevid * Copyright (c) 2005 Renaldas Zioma */ #include #include #include #include #include #include #include #include #include #include #include PSP_MODULE_INFO("RenderTarget Sample", 0, 1, 1); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); #define printf pspDebugScreenPrintf static unsigned int __attribute__((aligned(16))) list[262144]; typedef struct Vertex_ColorUV { float u, v; unsigned int color; float x,y,z; } Vertex_ColorUV; typedef struct Vertex_Normal { float nx,ny,nz; float x,y,z; } Vertex_Normal; typedef struct Texture { int format; int mipmap; int width, height, stride; const void* data; } Texture; /* cube */ Vertex_ColorUV __attribute__((aligned(16))) cube_vertices[12*3] = { {0, 0, 0xff7f0000,-1,-1, 1}, // 0 {1, 0, 0xff7f0000,-1, 1, 1}, // 4 {1, 1, 0xff7f0000, 1, 1, 1}, // 5 {0, 0, 0xff7f0000,-1,-1, 1}, // 0 {1, 1, 0xff7f0000, 1, 1, 1}, // 5 {0, 1, 0xff7f0000, 1,-1, 1}, // 1 {0, 0, 0xff7f0000,-1,-1,-1}, // 3 {1, 0, 0xff7f0000, 1,-1,-1}, // 2 {1, 1, 0xff7f0000, 1, 1,-1}, // 6 {0, 0, 0xff7f0000,-1,-1,-1}, // 3 {1, 1, 0xff7f0000, 1, 1,-1}, // 6 {0, 1, 0xff7f0000,-1, 1,-1}, // 7 {0, 0, 0xff007f00, 1,-1,-1}, // 0 {1, 0, 0xff007f00, 1,-1, 1}, // 3 {1, 1, 0xff007f00, 1, 1, 1}, // 7 {0, 0, 0xff007f00, 1,-1,-1}, // 0 {1, 1, 0xff007f00, 1, 1, 1}, // 7 {0, 1, 0xff007f00, 1, 1,-1}, // 4 {0, 0, 0xff007f00,-1,-1,-1}, // 0 {1, 0, 0xff007f00,-1, 1,-1}, // 3 {1, 1, 0xff007f00,-1, 1, 1}, // 7 {0, 0, 0xff007f00,-1,-1,-1}, // 0 {1, 1, 0xff007f00,-1, 1, 1}, // 7 {0, 1, 0xff007f00,-1,-1, 1}, // 4 {0, 0, 0xff00007f,-1, 1,-1}, // 0 {1, 0, 0xff00007f, 1, 1,-1}, // 1 {1, 1, 0xff00007f, 1, 1, 1}, // 2 {0, 0, 0xff00007f,-1, 1,-1}, // 0 {1, 1, 0xff00007f, 1, 1, 1}, // 2 {0, 1, 0xff00007f,-1, 1, 1}, // 3 {0, 0, 0xff00007f,-1,-1,-1}, // 4 {1, 0, 0xff00007f,-1,-1, 1}, // 7 {1, 1, 0xff00007f, 1,-1, 1}, // 6 {0, 0, 0xff00007f,-1,-1,-1}, // 4 {1, 1, 0xff00007f, 1,-1, 1}, // 6 {0, 1, 0xff00007f, 1,-1,-1}, // 5 }; /* torus */ #define TORUS_SLICES 48 // numc #define TORUS_ROWS 48 // numt #define TORUS_RADIUS 1.0f #define TORUS_THICKNESS 0.5f Vertex_Normal __attribute__((aligned(16))) torus_vertices[TORUS_SLICES*TORUS_ROWS]; unsigned short __attribute__((aligned(16))) torus_indices[TORUS_SLICES*TORUS_ROWS*6]; int SetupCallbacks(); void genTorus( unsigned slices, unsigned rows, float radius, float thickness, Vertex_Normal* dstVertices, unsigned short* dstIndices ); #define BUF_WIDTH (512) #define SCR_WIDTH (480) #define SCR_HEIGHT (272) #define PIXEL_SIZE (4) /* change this if you change to another screenmode */ #define FRAME_SIZE (BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE) void drawCube( Texture* texture, int val ) { // setup matrices for cube sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(75.0f,16.0f/9.0f,0.5f,1000.0f); sceGumMatrixMode(GU_VIEW); { ScePspFVector3 pos = {0.0f,0.0f,-2.5f}; sceGumLoadIdentity(); sceGumTranslate(&pos); } sceGumMatrixMode(GU_MODEL); { ScePspFVector3 rot = {val * 0.263f * (GU_PI/180.0f), val * 0.32f * (GU_PI/180.0f), val * 0.44f * (GU_PI/180.0f)}; sceGumLoadIdentity(); sceGumRotateXYZ(&rot); } // setup texture sceGuTexMode(texture->format,0,0,0); sceGuTexImage(texture->mipmap,texture->width,texture->height,texture->stride,texture->data); sceGuTexFunc(GU_TFX_ADD,GU_TCC_RGB); sceGuTexFilter(GU_LINEAR,GU_LINEAR); sceGuTexScale(1.0f,1.0f); sceGuTexOffset(0.0f,0.0f); sceGuAmbientColor(0xffffffff); sceGuEnable(GU_TEXTURE_2D); // draw cube sceGumDrawArray(GU_TRIANGLES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D,12*3,0,cube_vertices); sceGuDisable(GU_TEXTURE_2D); } void drawTorus( int val ) { // setup a light ScePspFVector3 dir = { 0, 0, 1 }; sceGuLight(0,GU_DIRECTIONAL,GU_DIFFUSE,&dir); sceGuLightColor(0,GU_DIFFUSE,0x00ff4040 ); sceGuLightAtt(0,1.0f,0.0f,0.0f); sceGuAmbient(0x00202020); // setup texture sceGuDisable(GU_TEXTURE_2D); sceGuEnable(GU_LIGHTING); sceGuEnable(GU_LIGHT0); // setup matrices for torus sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(75.0f,16.0f/9.0f,0.5f,1000.0f); sceGumMatrixMode(GU_VIEW); { ScePspFVector3 pos = {0.0f,0.0f,-2.5f}; sceGumLoadIdentity(); sceGumTranslate(&pos); } sceGumMatrixMode(GU_MODEL); { ScePspFVector3 rot = {val * 0.79f * (GU_PI/180.0f), val * 0.98f * (GU_PI/180.0f), val * 1.32f * (GU_PI/180.0f)}; sceGumLoadIdentity(); sceGumRotateXYZ(&rot); } // draw torus sceGuColor(0xffffff); sceGumDrawArray(GU_TRIANGLES,GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_INDEX_16BIT|GU_TRANSFORM_3D,sizeof(torus_indices)/sizeof(unsigned short),torus_indices,torus_vertices); // restore state sceGuDisable(GU_LIGHTING); sceGuDisable(GU_LIGHT0); sceGuEnable(GU_TEXTURE_2D); } int main(int argc, char* argv[]) { SetupCallbacks(); // generate geometry genTorus( TORUS_ROWS, TORUS_SLICES, TORUS_RADIUS, TORUS_THICKNESS, torus_vertices, torus_indices ); // flush cache so that no stray data remains sceKernelDcacheWritebackAll(); // setup Edram buffers void* frameBuffer = (void*)0; const void* doubleBuffer = (void*)0x44000; const void* renderTarget = (void*)0x88000; const void* depthBuffer = (void*)0x110000; // setup GU sceGuInit(); sceGuStart(GU_DIRECT,list); sceGuDrawBuffer(GU_PSM_4444,frameBuffer,BUF_WIDTH); sceGuDispBuffer(SCR_WIDTH,SCR_HEIGHT,(void*)doubleBuffer,BUF_WIDTH); sceGuDepthBuffer((void*)depthBuffer,BUF_WIDTH); sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2)); sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT); sceGuDepthRange(0xc350,0x2710); sceGuScissor(0,0,SCR_WIDTH,SCR_HEIGHT); sceGuEnable(GU_SCISSOR_TEST); sceGuDepthFunc(GU_GEQUAL); sceGuEnable(GU_DEPTH_TEST); sceGuFrontFace(GU_CW); sceGuShadeModel(GU_SMOOTH); sceGuEnable(GU_CULL_FACE); sceGuEnable(GU_TEXTURE_2D); sceGuFinish(); sceGuSync(GU_SYNC_FINISH, GU_SYNC_WHAT_DONE); sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); // run sample int val = 0; Texture offscreenTexture = { GU_PSM_4444, 0, 128, 128, 128, sceGeEdramGetAddr() + (int)renderTarget }; for(;;) { sceGuStart(GU_DIRECT,list); { sceGuDrawBufferList(GU_PSM_4444,(void*)renderTarget,offscreenTexture.stride); // setup viewport sceGuOffset(2048 - (offscreenTexture.width/2),2048 - (offscreenTexture.height/2)); sceGuViewport(2048,2048,offscreenTexture.width,offscreenTexture.height); // clear screen sceGuClearColor(0xffffffff); sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); // draw torus to offscreen texture drawTorus( val ); } { // set frame buffer sceGuDrawBufferList(GU_PSM_4444,(void*)frameBuffer,BUF_WIDTH); // setup viewport sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2)); sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT); // clear screen sceGuClearColor(0xff554433); sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); // draw cube using offscreen texture drawCube( &offscreenTexture, val ); } sceGuFinish(); sceGuSync(GU_SYNC_FINISH, GU_SYNC_WHAT_DONE); sceDisplayWaitVblankStart(); frameBuffer = sceGuSwapBuffers(); val++; } sceGuTerm(); sceKernelExitGame(); return 0; } /* Exit callback */ int exit_callback(int arg1, int arg2, void *common) { sceKernelExitGame(); return 0; } /* Callback thread */ int CallbackThread(SceSize args, void *argp) { int cbid; cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } /* Sets up the callback thread and returns its thread id */ int SetupCallbacks(void) { int thid = 0; thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); if(thid >= 0) { sceKernelStartThread(thid, 0, 0); } return thid; } /* usefull geometry functions */ void genTorus( unsigned slices, unsigned rows, float radius, float thickness, Vertex_Normal* dstVertices, unsigned short* dstIndices ) { unsigned int i,j; // generate torus (TODO: tri-strips) for (j = 0; j < slices; ++j) { for (i = 0; i < rows; ++i) { struct Vertex_Normal* curr = &dstVertices[i+j*rows]; float s = i + 0.5f; float t = j; float cs,ct,ss,st; cs = cosf(s * (2*GU_PI)/slices); ct = cosf(t * (2*GU_PI)/rows); ss = sinf(s * (2*GU_PI)/slices); st = sinf(t * (2*GU_PI)/rows); curr->nx = cs * ct; curr->ny = cs * st; curr->nz = ss; curr->x = (radius + thickness * cs) * ct; curr->y = (radius + thickness * cs) * st; curr->z = thickness * ss; } } for (j = 0; j < slices; ++j) { for (i = 0; i < rows; ++i) { unsigned short* curr = &dstIndices[(i+(j*rows))*6]; unsigned int i1 = (i+1)%rows, j1 = (j+1)%slices; *curr++ = i + j * rows; *curr++ = i1 + j * rows; *curr++ = i + j1 * rows; *curr++ = i1 + j * rows; *curr++ = i1 + j1 * rows; *curr++ = i + j1 * rows; } } }