Skip to: Site menu | Main content


Welcome to PSP-Programming.com, a place for developers to get together.

Welcome to the forums. Here you can find other user tutorials as well as homebrew releases and the source code repository. You can also ask for help with your code here and post your own homebrew!

PSP-Programming.com Forums
March 21, 2010, 12:11:25 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

News: Welcome to PSP-Programming.com
Home Help Search Shop Login Register
Digg This!
Pages: [1]
Print
Author Topic: Simple GU Sprite Demo  (Read 5500 times)
lokust
Full Member
***

Karma: +1/-0
Offline Offline

Posts: 186
0.00 points

View Inventory
Send Money to lokust


View Profile WWW
« on: June 11, 2006, 06:47:53 AM »

[Rapheal has shown how to implement a faster version of drawing sprites with the same flexibility described below, check it out here here.]

For even more information and a solid explanation of texture cache look here and check out the speed demo in your sdk.

[DISCLAIMER: The following is just an observation, and what I have learned so far. I cannot verify 100% whether these methods are better or worse than anything else out there, and I have not done any extensive testing. So, be very critical of every detail listed below and of course call me out on anything that looks strange or doesnt make sense!]

The following is a simple demonstration of basic sprite functionality using the GU library from the PSPSDK. I am starting to believe that handling sprites though the GU will help alot of people with certain operations.

In brief, here is how you render a sprite using the GU.

1. Upload your image to the gu using sceGuTexImage(). This will prepare the gu to map your image to any geometry specified after this call (like our sprite). Subsequent calls to sceGuTexImage() will replace the current texture with the one provided.

2. Define two vertices that represent the "top-left" and "bottom-right" corner of your sprite. Each vertex must be supplied with valid UV texture coordinates which map from 0 to imageWidth and 0 to imageHeight respectivley. You will probably want the top left hand corner of the image, to map to the top left hand corner of your sprite. To do this we will set the u,v coordinate of the first vertex to 0,0. And of course the bottom right hand corner of the sprite should map to the bottom right hand corner of the image, so we will set the u,v of the second vertex to imageHeight, imageWidth.

Code:

vertices[0].u = 0;
vertices[0].v = 0;
vertices[1].u = pImg->imageWidth;
vertices[1].v = pImg->imageHeight;


Of course, it is common to store more than one image in a single file. For example you might want each frame of an explosion animation stored in the same image. If the width of each image is 64, then you just increment the u coordinate for the bottom right vertex and top left vertex by 64 to grab each frame.

NOTE: When you are rendering in 2D (by specifying GU_TRANSFORM_2D) the gu bypasses the transformation pipeline and thus uv coodinates cannot be remaped. I mention this here because the BlitAlphaImageToScreen() routine in graphics.h tries to do this, and I believe it is wrong.

3. Render using the vertex array by calling sceDrawArray(). Once you call this the rasterizer will map your image to the bounds defined by the two sprite vertices.

Alright, now here is some code that I put together real quick to demonstrate the above. Again, please point out anything that looks wrong or doesnt make sense.

Code:

#include "main.h"
#include "graphics.h"

PSP_MODULE_INFO("PSPSplash", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);

int main(int argc, char **argv)
{
SceCtrlData pad;
bool done = false;

pspDebugScreenInit();
SetupCallbacks();

sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

initGraphics();

Image *pImg = loadImage("./real.png");

unsigned short imgScaleX = pImg->imageWidth;
unsigned short imgScaleY = pImg->imageHeight;
short xPos = 0;
short yPos = 0;

unsigned short offset = 5;

while(!done)
{
sceCtrlReadBufferPositive(&pad, 1);

if(pad.Buttons & PSP_CTRL_TRIANGLE)
imgScaleY += offset;
if(pad.Buttons & PSP_CTRL_CROSS)
imgScaleY -= offset;
if(pad.Buttons & PSP_CTRL_SQUARE)
imgScaleX -= offset;
if(pad.Buttons & PSP_CTRL_CIRCLE)
imgScaleX += offset;

if(pad.Buttons & PSP_CTRL_UP)
yPos -= offset;
if(pad.Buttons & PSP_CTRL_DOWN)
yPos += offset;
if(pad.Buttons & PSP_CTRL_LEFT)
xPos -= offset;
if(pad.Buttons & PSP_CTRL_RIGHT)
xPos += offset;

sceKernelDcacheWritebackInvalidateAll();
guStart();

sceGuClearColor(RGB(0, 0, 0));
sceGuClearDepth(0);
sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);

sceGuTexImage(0, pImg->textureWidth, pImg->textureHeight, pImg->textureWidth, (void*) pImg->data);

Vertex *vertices = (Vertex*) sceGuGetMemory(2 * sizeof(Vertex));
vertices[0].u = 0;
vertices[0].v = 0;
vertices[0].x = xPos;
vertices[0].y = yPos;
vertices[0].z = 0;

vertices[1].u = pImg->imageWidth;
vertices[1].v = pImg->imageHeight;
vertices[1].x = xPos+imgScaleX;
vertices[1].y = yPos+imgScaleY;
vertices[1].z = 0;

sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices);
sceGuFinish();
sceGuSync(0, 0);

sceDisplayWaitVblankStart();
flipScreen();
}

if(pImg)
{
delete [] pImg->data;
delete pImg;
}

sceGuTerm();
sceKernelExitGame();

return 0;
}


Executable
Source
Logged

<flashram> we just lack the rock ... everbody is stoned already
<whazilla> i'm the dark Yoda but i speak as the one green


darkplastic
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 16
250.00 points

View Inventory
Send Money to darkplastic

View Profile
« Reply #1 on: December 21, 2006, 06:04:14 AM »

Nice man easy image scaling FTW i encorperated it into the graphics.cpp source:

Code:
void blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
{
if (!initialized) return;

sceGumLoadIdentity();
sceGuTexMode(GU_PSM_8888, 0, 0, 0);

unsigned short imgScaleX =source->imageWidth;
unsigned short imgScaleY =source->imageHeight;
int xPos = dx;
int yPos = dy;

sceGuTexImage(0, source->textureWidth, source->textureHeight, source->textureWidth, (void*) source->data);

Vertex *vertices = (Vertex*) sceGuGetMemory(2 * sizeof(Vertex));
vertices[0].u = sx;
vertices[0].v = sy;
vertices[0].x = xPos;
vertices[0].y = yPos;
vertices[0].z = 0;

vertices[1].u = width;
vertices[1].v = height;
vertices[1].x = xPos+width;
vertices[1].y = yPos+height;
vertices[1].z = 0;

sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices);
}


Now just to figure out how to make it work with texture swizzling and image rotation!
Logged
Pages: [1]
Print
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 0.325 seconds with 27 queries.
Sister Sites: Guitar Hero 4   BrokeniTouch.com