 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
Visigotico
Joined: 23 Apr 2008 Posts: 11
|
Posted: Tue Dec 22, 2009 12:26 am Post subject: shadows... |
|
|
gta chinatown wars apparently uses stencil shadow volume, but for a scene where there are many shadow cast objects, this technique can be a great performance hit.
does anyone know how shadows are achieved in silent hill game? Based in artifacts sometimes visible in the edges of shadows, the technique used must be shadowmap, but the PSP hardware doesn't have pixel shader or something like the opengl extensions necessary to make it work... |
|
| Back to top |
|
 |
Raphael

Joined: 17 Jan 2006 Posts: 646 Location: Germany
|
|
| Back to top |
|
 |
Visigotico
Joined: 23 Apr 2008 Posts: 11
|
Posted: Wed Dec 30, 2009 2:09 am Post subject: |
|
|
shadowmap implementantion modifying SDK reflexion sample.
----------------------------------------------------------------------------
#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <pspgu.h>
#include <pspgum.h>
#include <pspvfpu.h>
PSP_MODULE_INFO("ShadowMap Sample", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
static unsigned int __attribute__((aligned(16))) list[262144];
extern unsigned char logo_start[];
struct Vertex
{
float u, v;
unsigned int color;
float x,y,z;
};
struct Vertex __attribute__((aligned(16))) obj[36] = {
{0, 0, 0xff6666ff,-1,-1, 1},
{1, 0, 0xff6666ff, 1,-1, 1},
{1, 1, 0xff6666ff, 1, 1, 1},
{0, 0, 0xff6666ff,-1,-1, 1},
{1, 1, 0xff6666ff, 1, 1, 1},
{0, 1, 0xff6666ff,-1, 1, 1},
{1, 1, 0xff66ff66, 1, 1, 1},
{0, 1, 0xff66ff66, 1,-1, 1},
{0, 0, 0xff66ff66, 1,-1,-1},
{1, 1, 0xff66ff66, 1, 1, 1},
{0, 0, 0xff66ff66, 1,-1,-1},
{1, 0, 0xff66ff66, 1, 1,-1},
{0, 1, 0xffff6666,-1, 1, 1},
{0, 0, 0xffff6666, 1, 1, 1},
{1, 0, 0xffff6666, 1, 1,-1},
{0, 1, 0xffff6666,-1, 1, 1},
{1, 0, 0xffff6666, 1, 1,-1},
{1, 1, 0xffff6666,-1, 1,-1},
{1, 1, 0xff6666ff, 1.0f,-1.0f,-1.0f},
{0, 1, 0xff6666ff,-1.0f,-1.0f,-1.0f},
{0, 0, 0xff6666ff,-1.0f, 1.0f,-1.0f},
{1, 1, 0xff6666ff, 1.0f,-1.0f,-1.0f},
{0, 0, 0xff6666ff,-1.0f, 1.0f,-1.0f},
{1, 0, 0xff6666ff, 1.0f, 1.0f,-1.0f},
{1, 0, 0xff66ff66,-1,-1,-1},
{1, 1, 0xff66ff66,-1,-1, 1},
{0, 1, 0xff66ff66,-1, 1, 1},
{1, 0, 0xff66ff66,-1,-1,-1},
{0, 1, 0xff66ff66,-1, 1, 1},
{0, 0, 0xff66ff66,-1, 1,-1},
{0, 1, 0xffff6666,-1,-1,-1},
{0, 0, 0xffff6666, 1,-1,-1},
{1, 0, 0xffff6666, 1,-1, 1},
{0, 1, 0xffff6666,-1,-1,-1},
{1, 0, 0xffff6666, 1,-1, 1},
{1, 1, 0xffff6666,-1,-1, 1},
};
struct Vertex __attribute__((aligned(16))) mirror[6] = {
{0, 0, 0xaa000000, -2.0f, 0, -2.0f},
{2, 2, 0xaa000000, 2.0f, 0, 2.0f},
{2, 0, 0xaa000000, 2.0f, 0, -2.0f},
{0, 0, 0xaa000000, -2.0f, 0, -2.0f},
{0, 2, 0xaa000000, -2.0f, 0, 2.0f},
{2, 2, 0xaa000000, 2.0f, 0, 2.0f}
};
struct Vertex __attribute__((aligned(16))) border[6] = {
{0, 0, 0xff0055aa, -2.125f, -0.01, -2.125f},
{2, 2, 0xff0055aa, 2.125f, -0.01, 2.125f},
{2, 0, 0xff0055aa, 2.125f, -0.01, -2.125f},
{0, 0, 0xff0055aa, -2.125f, -0.01, -2.125f},
{0, 2, 0xff0055aa, -2.125f, -0.01, 2.125f},
{2, 2, 0xff0055aa, 2.125f, -0.01, 2.125f}
};
int SetupCallbacks();
#define BUF_WIDTH (512)
#define SCR_WIDTH (480)
#define SCR_HEIGHT (272)
#define PIXEL_SIZE (2) /* change this if you change to another screenmode */
#define FRAME_SIZE (BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE)
#define ZBUF_SIZE (BUF_WIDTH * SCR_HEIGHT * 2) /* zbuffer seems to be 16-bit? */
#define ZBUFFER_LINEAR(x) (0x600000 + x)
#define ZBUFFER_UNSWIZ(x) (0x200000 + x)
#define VRAM_OFFSET(x) (0x4000000 + x)
#define ZBUFFER_LINEAR16BPP ZBUFFER_UNSWIZ
ScePspFMatrix4 projMatrix, viewMatrixCam, viewMatrixLight;
ScePspFMatrix4 projFinal, unprojFinal;
void setUnProjMatrix(const float *mat)
{
__asm__ volatile (
"ulv.q C000, 0x0 (%0)\n"
"ulv.q C010, 0x10(%0)\n"
"ulv.q C020, 0x20(%0)\n"
"ulv.q C030, 0x30(%0)\n"
: :"r" (mat) );
}
void setProjMatrix(const float *mat)
{
__asm__ volatile (
"ulv.q C100, 0x0 (%0)\n"
"ulv.q C110, 0x10(%0)\n"
"ulv.q C120, 0x20(%0)\n"
"ulv.q C130, 0x30(%0)\n"
: :"r" (mat) );
}
float output[4] __attribute__((aligned(VFPU_ALIGNMENT)));
void TransformArraysInOutByMatUnProj(const float *vec, float *out)
{
__asm__ volatile (
"ulv.q R200, 0x0(%1)\n"
"vone.s S230\n"
"vtfm4.q R300, E000, R200\n"
"sv.q R300, 0x0(%0)\n"
: : "r"(output) , "r" (vec) );
out[0]=output[0];
out[1]=output[1];
out[2]=output[2];
out[3]=output[3];
}
void TransformArraysInOutByMatProj(const float *vec, float *out)
{
__asm__ volatile (
"ulv.q R200, 0x0(%1)\n"
"vone.s S230\n"
"vtfm4.q R300, E100, R200\n"
"sv.q R300, 0x0(%0)\n"
: : "r"(output) , "r" (vec) );
out[0]=output[0];
out[1]=output[1];
out[2]=output[2];
out[3]=output[3];
}
void toScreen(float nx, float ny, float nz,
int *sx, int *sy, int *sz)
{
*sx = ((nx+1.0f)/2.0f) * 480.0f;
*sy = (1.0f - ((ny+1.0f)/2.0f)) * 272.0f;
*sz = (1.0f-nz)*32768;
}
void fromScreen(int sx, int sy, int sz,
float *nx, float *ny, float *nz)
{
*nx = sx*(2.0f/480.0f)-1.0f;
*ny = 1.0f-sy*(2.0f/272.0f);
*nz = 1.0f-sz/32768.0f;
}
ScePspFMatrix4 finalMatrix;
void gumProjectF2(float objx, float objy, float objz,
float *winx, float *winy, float *winz)
{
float in[4];
in[0]=objx;
in[1]=objy;
in[2]=objz;
in[3]=1.0;
TransformArraysInOutByMatProj(in,in);
if (in[3] == 0.0) return;
*winx = in[0]/in[3];
*winy = in[1]/in[3];
*winz = in[2]/in[3];
}
void gumProjectI2(float objx, float objy, float objz,
int *winx, int *winy, int *winz)
{
float fwx,fwy,fwz;
gumProjectF2(objx,objy,objz,&fwx,&fwy,&fwz);
toScreen(fwx,fwy,fwz,winx,winy,winz);
}
void gumUnProjectF2(float winx, float winy, float winz,
float *objx, float *objy, float *objz)
{
float in[4];
in[0]=winx;
in[1]=winy;
in[2]=winz;
in[3]=1.0;
TransformArraysInOutByMatUnProj(in,in);
if (in[3] == 0.0) return;
*objx = in[0]/in[3];
*objy = in[1]/in[3];
*objz = in[2]/in[3];
}
void gumUnProjectI2(int winx, int winy, unsigned short winz,
float *objx, float *objy, float *objz)
{
float x,y,z;
fromScreen(winx,winy,winz,&x,&y,&z);
gumUnProjectF2(x,y,z,objx,objy,objz);
}
int main(int argc, char* argv[])
{
SetupCallbacks();
pspDebugScreenInit();
// setup GU
sceGuInit();
sceGuStart(GU_DIRECT,list);
sceGuDrawBuffer(GU_PSM_4444,(void*)0,BUF_WIDTH);
sceGuDispBuffer(SCR_WIDTH,SCR_HEIGHT,(void*)(FRAME_SIZE),BUF_WIDTH);
sceGuDepthBuffer((void*)(2*FRAME_SIZE),BUF_WIDTH);
sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2));
sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT);
sceGuDepthRange(65535,0);
// sceGuDepthRange(0xc350,0x2710);
sceGuScissor(0,0,SCR_WIDTH,SCR_HEIGHT);
sceGuEnable(GU_SCISSOR_TEST);
sceGuDepthFunc(GU_GEQUAL);
sceGuEnable(GU_DEPTH_TEST);
sceGuFrontFace(GU_CCW);
sceGuShadeModel(GU_SMOOTH);
sceGuEnable(GU_CULL_FACE);
sceGuFinish();
sceGuSync(0,0);
sceGumMatrixMode(GU_PROJECTION);
sceGumLoadIdentity();
sceGumPerspective(60.0f,16.0f/9.0f,0.5f,1000.0f);
sceGumStoreMatrix(&projMatrix);
sceDisplayWaitVblankStart();
sceGuDisplay(GU_TRUE);
// run sample
int val = 0;
unsigned short *buf = (void *)VRAM_OFFSET(0);
for(;;)
{
float move = sinf(((float)val / 180.0f) * GU_PI);
if(move < 0) {
move *= -1;
}
move += 1;
float rot = ((float)val / 180.0f) * GU_PI;
sceGuStart(GU_DIRECT,list);
sceGuDepthBuffer((void*)(2*FRAME_SIZE),BUF_WIDTH);
sceGuFrontFace(GU_CW);
sceGuPixelMask(0xFFFFFFFF);
sceGuClearDepth(0);
sceGuClear(GU_DEPTH_BUFFER_BIT);
sceGumMatrixMode(GU_VIEW);
float eye1[3]={0.0f,6.0f,4.0f};
float center1[3]={0,0,0};
float up1[3]={0,1,0};
sceGumLoadIdentity();
sceGumLookAt(eye1,center1,up1);
sceGumStoreMatrix(&viewMatrixLight);
sceGumMatrixMode(GU_MODEL);
sceGumLoadIdentity();
// draw normal view
sceGuDisable(GU_TEXTURE_2D);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, 0, mirror);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, 0, border);
{
ScePspFVector3 pos = {0,move,0};
ScePspFVector3 rvec = {0,rot * -0.83f, 0};
sceGumTranslate(&pos);
sceGumRotateXYZ(&rvec);
}
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 36, 0, obj);
sceGuFinish();
gumMultMatrix(&projFinal, &projMatrix, &viewMatrixLight);
sceGuSync(0,0);
sceGuStart(GU_DIRECT,list);
sceGuDepthBuffer((void*)(2*FRAME_SIZE+ZBUF_SIZE),BUF_WIDTH);
sceGuFrontFace(GU_CCW);
sceGuPixelMask(0);
// clear screen
sceGuClearColor(0xff554433);
sceGuClearDepth(0);
sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT);
// setup matrices for cube
sceGumMatrixMode(GU_VIEW);
float eye2[3]={0.0f,3.0f,5.0f};
float center2[3]={0,0,0};
float up2[3]={0,1,0};
sceGumLoadIdentity();
sceGumLookAt(eye2,center2,up2);
sceGumStoreMatrix(&viewMatrixCam);
sceGumMatrixMode(GU_MODEL);
sceGumLoadIdentity();
// draw normal view
sceGuEnable(GU_TEXTURE_2D);
sceGuTexMode(GU_PSM_4444,0,0,0);
sceGuTexImage(0,64,64,64,logo_start);
sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGBA);
sceGuTexFilter(GU_LINEAR,GU_LINEAR);
sceGuTexScale(1.0f,1.0f);
sceGuTexOffset(0.0f,0.0f);
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, 0, mirror);
sceGuDisable(GU_BLEND);
sceGuDisable(GU_TEXTURE_2D);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 6, 0, border);
sceGuEnable(GU_TEXTURE_2D);
sceGuTexMode(GU_PSM_4444,0,0,0);
sceGuTexImage(0,64,64,64,logo_start);
sceGuTexFunc(GU_TFX_ADD,GU_TCC_RGB);
sceGuTexFilter(GU_LINEAR,GU_LINEAR);
sceGuTexScale(1.0f,1.0f);
sceGuTexOffset(0.0f,0.0f);
{
ScePspFVector3 pos = {0,move,0};
ScePspFVector3 rvec = {0,rot * -0.83f, 0};
sceGumTranslate(&pos);
sceGumRotateXYZ(&rvec);
}
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 36, 0, obj);
sceGuDisable(GU_TEXTURE_2D);
sceGuFinish();
gumMultMatrix(&unprojFinal, &projMatrix, &viewMatrixCam);
gumFullInverse(&unprojFinal,&unprojFinal);
sceGuSync(0,0);
int i,j;
unsigned short *zbufptr = (void *)VRAM_OFFSET(ZBUFFER_LINEAR16BPP(2*FRAME_SIZE));
unsigned short *zbuf = (void *)VRAM_OFFSET(ZBUFFER_LINEAR16BPP(2*FRAME_SIZE+ZBUF_SIZE));
unsigned short *bufptr = buf;
setUnProjMatrix(&unprojFinal);
setProjMatrix(&projFinal);
#define HALF
#ifdef HALF
for(i=0;i<272;i+=2)
#else
for(i=0;i<272;i++)
#endif
{
#ifdef HALF
for(j=0;j<480;j+=2)
#else
for(j=0;j<480;j++)
#endif
{
float fx,fy,fz;
int x,y,z;
if(zbuf[j]==0) continue;
gumUnProjectI2(j,i,zbuf[j],&fx,&fy,&fz);
gumProjectI2(fx,fy,fz,&x,&y,&z);
int shadow=1;
if((x<0)||(x>479)||(y<0)||(y>271)) shadow=0;
if(z>zbufptr[y*512+x]) shadow=0;
if(shadow)
{
bufptr[j]=(bufptr[j]&0xeeee)>>1;
#ifdef HALF
bufptr[j+1]=(bufptr[j+1]&0xeeee)>>1;
bufptr[j+512]=(bufptr[j+512]&0xeeee)>>1;
bufptr[j+512+1]=(bufptr[j+512+1]&0xeeee)>>1;
#endif
}
}
#ifdef HALF
zbuf+=512*2;
bufptr+=512*2;
#else
zbuf+=512;
bufptr+=512;
#endif
}
sceDisplayWaitVblankStart();
buf = (void *)VRAM_OFFSET(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;
} |
|
| Back to top |
|
 |
anmabagima
Joined: 01 Oct 2009 Posts: 96
|
Posted: Mon Jan 11, 2010 7:39 pm Post subject: |
|
|
Hi,
your example looks very much complicated. I've tried the one delivered with the SDK. This looks more clear to me and I'v already adopted it for my 3D scenes.
I guess some more inline comments would help some times to understand way you are doing certain things in they way you do ;) |
|
| Back to top |
|
 |
a_noob
Joined: 17 Sep 2006 Posts: 97 Location: _start: jr 0xDEADBEEF
|
Posted: Tue Jan 12, 2010 5:22 pm Post subject: |
|
|
In all honesty most scenes can just have baked shadows, then you can just do real time/dynamic shadows on a few select objects that move, saving performance. _________________
| Code: | .øOº'ºOø.
'ºOo.oOº' |
|
|
| Back to top |
|
 |
anmabagima
Joined: 01 Oct 2009 Posts: 96
|
Posted: Wed Jan 13, 2010 5:35 pm Post subject: |
|
|
Hi,
did you mean shadow which is precalculated into the textures already ?
This may be difficult as you may need a seperate texture for each object, don't you ? |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Wed Jan 13, 2010 8:06 pm Post subject: |
|
|
If the lights are not dynamic and your objects are tessellated well then you can bake the shadows into the vertex lighting.
Jim _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
Raphael

Joined: 17 Jan 2006 Posts: 646 Location: Germany
|
Posted: Wed Jan 13, 2010 8:50 pm Post subject: |
|
|
Either that, or if your objects are not tesselated enough to give good enough results, it comes down to lightmapping. In this case, yes, you need seperate (light) texture for each object, but those are relatively low-res, though require a two-pass texturing scheme.
What you thought of was a one-pass scheme, where you'd have to combine the lightmaps into the object textures as a pre-process step. That could waste a lot of memory though for duplicate textures with slightly different lighting, yes. _________________ <Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl |
|
| Back to top |
|
 |
anmabagima
Joined: 01 Oct 2009 Posts: 96
|
Posted: Wed Jan 13, 2010 10:23 pm Post subject: |
|
|
Hi,
thanks to both of you. Now I've a clear picture in my mind :o)
Great - maybe I will try that in my currentproject as I've 1 ore 2 lightsources and only 1 moving object ;o) |
|
| Back to top |
|
 |
Visigotico
Joined: 23 Apr 2008 Posts: 11
|
Posted: Sat Jan 16, 2010 1:09 pm Post subject: |
|
|
| Ok, it's complicated and unoptimized because this is only a test code, done in 5 minutes. Actualy I have a optimized (on VFPU) and better code, running at 132 FPS. If anyone has interest... |
|
| Back to top |
|
 |
anmabagima
Joined: 01 Oct 2009 Posts: 96
|
Posted: Sun Jan 17, 2010 6:36 am Post subject: |
|
|
Hi,
sure. I'm interested in, as in my current code I've currently no real clue how to deal with the following issues (may be you have solved them).
Rendering the shadow caster from light point of view results in strange block shadows if the object is far away from light source (due to the resolution of the rendering i guess)
Secondly the usage of texture matrix for rendering of shadow reciever results in shadows applied to an object which is closer to the light than the shadow caster.
Thanks regards
AnMaBaGiMa |
|
| Back to top |
|
 |
Visigotico
Joined: 23 Apr 2008 Posts: 11
|
Posted: Tue Jan 19, 2010 12:36 am Post subject: |
|
|
Are you using the SDK samples? The technique I'm using is a little
different, you can read about Shadow Mapping to understand
better how it works, how it should be used and their problems and bugs. |
|
| Back to top |
|
 |
anmabagima
Joined: 01 Oct 2009 Posts: 96
|
Posted: Tue Jan 19, 2010 1:41 am Post subject: |
|
|
Hi,
yes I'm using the SDK samples with some minor adjustments ;)
I've read the article on shadow mapping posted at the beginning of this thread. This is using a multi pass approach which looked very similar to the one implemented in the SDK example. But as I'm a beginner in using GU and all the matrix stuff may be I didn't get the full picture out of this page. The openGL stuff mentioned there as sample code is completely new to me as I've used Direct3D in the past on PC for 3D rendering.
Thanks for any hints as I'm interested more into a "how do I" and I want to understand what I'm doing rather then just copy/paste other once code ;)
Best regards |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|