Reason I ask, is because I'm rendering a skybox which works perfectly fine on my slim psp, but on the phat psp it looks like the uv coordinates are screwing up in strange ways when I start clipping the skybox polys against my world geometry (when it isn't getting clipped, it looks fine). Same eboot, same rendering code, doing nothing specific for the slim or phat psp's.
Slim:
Phat:
Rendering Code (sorry its a lot, would be great if I could get it cut down):
Code: Select all
vec3_t skyclip[6] = {
{1,1,0},
{1,-1,0},
{0,-1,1},
{0,1,1},
{1,0,1},
{-1,0,1}
};
int c_sky;
// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
{
{3,-1,2},
{-3,1,2},
{1,3,2},
{-1,-3,2},
{-2,-1,3}, // 0 degrees yaw, look straight up
{2,-1,-3} // look straight down
// {-1,2,3},
// {1,2,-3}
};
// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
{-2,3,1},
{2,3,-1},
{1,3,2},
{-1,3,-2},
{-2,-1,3},
{-2,1,-3}
// {-1,2,3},
// {1,2,-3}
};
float skymins[2][6], skymaxs[2][6];
void DrawSkyPolygon (int nump, vec3_t vecs)
{
int i,j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
c_sky++;
// decide which face it maps to
VectorCopy (vec3_origin, v);
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
{
VectorAdd (vp, v, v);
}
av[0] = fabs(v[0]);
av[1] = fabs(v[1]);
av[2] = fabs(v[2]);
if (av[0] > av[1] && av[0] > av[2])
{
if (v[0] < 0)
axis = 1;
else
axis = 0;
}
else if (av[1] > av[2] && av[1] > av[0])
{
if (v[1] < 0)
axis = 3;
else
axis = 2;
}
else
{
if (v[2] < 0)
axis = 5;
else
axis = 4;
}
// project new texture coords
for (i=0 ; i<nump ; i++, vecs+=3)
{
j = vec_to_st[axis][2];
if (j > 0)
dv = vecs[j - 1];
else
dv = -vecs[-j - 1];
j = vec_to_st[axis][0];
if (j < 0)
s = -vecs[-j -1] / dv;
else
s = vecs[j-1] / dv;
j = vec_to_st[axis][1];
if (j < 0)
t = -vecs[-j -1] / dv;
else
t = vecs[j-1] / dv;
if (s < skymins[0][axis])
skymins[0][axis] = s;
if (t < skymins[1][axis])
skymins[1][axis] = t;
if (s > skymaxs[0][axis])
skymaxs[0][axis] = s;
if (t > skymaxs[1][axis])
skymaxs[1][axis] = t;
}
}
#define MAX_CLIP_VERTS 64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS];
int sides[MAX_CLIP_VERTS];
vec3_t newv[2][MAX_CLIP_VERTS];
int newc[2];
int i, j;
if (nump > MAX_CLIP_VERTS-2)
Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
if (stage == 6)
{ // fully clipped, so draw it
DrawSkyPolygon (nump, vecs);
return;
}
front = back = qfalse;
norm = skyclip[stage];
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
d = DotProduct (v, norm);
if (d > ON_EPSILON)
{
front = qtrue;
sides[i] = SIDE_FRONT;
}
else if (d < ON_EPSILON)
{
back = qtrue;
sides[i] = SIDE_BACK;
}
else
sides[i] = SIDE_ON;
dists[i] = d;
}
if (!front || !back)
{ // not clipped
ClipSkyPolygon (nump, vecs, stage+1);
return;
}
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy (vecs, (vecs+(i*3)) );
newc[0] = newc[1] = 0;
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
switch (sides[i])
{
case SIDE_FRONT:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
break;
case SIDE_BACK:
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
case SIDE_ON:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
}
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
d = dists[i] / (dists[i] - dists[i+1]);
for (j=0 ; j<3 ; j++)
{
e = v[j] + d*(v[j+3] - v[j]);
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
// continue
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
{
int i;
for (i=0 ; i<6 ; i++)
{
skymins[0][i] = skymins[1][i] = 9999;
skymaxs[0][i] = skymaxs[1][i] = -9999;
}
}
float s_axis;
float t_axis;
vec3_t v_axis;
void MakeSkyVec (float s, float t, int axis)
{
vec3_t b;
int j, k;
b[0] = s*r_skyclip.value;
b[1] = t*r_skyclip.value;
b[2] = r_skyclip.value;
for (j=0 ; j<3 ; j++)
{
k = st_to_vec[axis][j];
if (k < 0)
v_axis[j] = -b[-k - 1];
else
v_axis[j] = b[k - 1];
v_axis[j] += r_origin[j];
}
// avoid bilerp seam
s = (s+1)*0.5;
t = (t+1)*0.5;
if (s < 1.0/512)
s = 1.0/512;
else if (s > 511.0/512)
s = 511.0/512;
if (t < 1.0/512)
t = 1.0/512;
else if (t > 511.0/512)
t = 511.0/512;
t = 1.0 - t;
s_axis = s;
t_axis = t;
}
/*
==============
R_DrawSkyBox
==============
*/
void R_DrawSkyBox (void)
{
int i;
float r,g,b,a;
for (i=0 ; i<6 ; i++)
{
// Allocate memory for this polygon.
const int unclipped_vertex_count = 4;
glvert_t* const unclipped_vertices =
static_cast<glvert_t*>(sceGuGetMemory(sizeof(glvert_t) * unclipped_vertex_count));
if (skymins[0][i] >= skymaxs[0][i]
|| skymins[1][i] >= skymaxs[1][i])
continue;
GL_Bind (skyimage[skytexorder[i]]);
MakeSkyVec (skymins[0][i], skymins[1][i], i);
unclipped_vertices[0].st[0] = s_axis;
unclipped_vertices[0].st[1] = t_axis;
unclipped_vertices[0].xyz[0] = v_axis[0];
unclipped_vertices[0].xyz[1] = v_axis[1];
unclipped_vertices[0].xyz[2] = v_axis[2];
MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
unclipped_vertices[1].st[0] = s_axis;
unclipped_vertices[1].st[1] = t_axis;
unclipped_vertices[1].xyz[0] = v_axis[0];
unclipped_vertices[1].xyz[1] = v_axis[1];
unclipped_vertices[1].xyz[2] = v_axis[2];
MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
unclipped_vertices[2].st[0] = s_axis;
unclipped_vertices[2].st[1] = t_axis;
unclipped_vertices[2].xyz[0] = v_axis[0];
unclipped_vertices[2].xyz[1] = v_axis[1];
unclipped_vertices[2].xyz[2] = v_axis[2];
MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
unclipped_vertices[3].st[0] = s_axis;
unclipped_vertices[3].st[1] = t_axis;
unclipped_vertices[3].xyz[0] = v_axis[0];
unclipped_vertices[3].xyz[1] = v_axis[1];
unclipped_vertices[3].xyz[2] = v_axis[2];
if (clipping::is_clipping_required(
unclipped_vertices,
unclipped_vertex_count))
{
// Clip the polygon.
const glvert_t* clipped_vertices;
std::size_t clipped_vertex_count;
clipping::clip(
unclipped_vertices,
unclipped_vertex_count,
&clipped_vertices,
&clipped_vertex_count);
// Did we have any vertices left?
if (clipped_vertex_count)
{
// Copy the vertices to the display list.
const std::size_t buffer_size = clipped_vertex_count * sizeof(glvert_t);
glvert_t* const display_list_vertices = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
memcpy(display_list_vertices, clipped_vertices, buffer_size);
if(cl.worldmodel)
VID_SetPaletteSKY ();
Fog_DisableGFog();
if (r_refdef.fog_end > 0 && r_skyfog.value)
{
a = r_refdef.fog_end * 0.00025f;
r = r_refdef.fog_red * 0.01f + (a * 0.25f);
g = r_refdef.fog_green * 0.01f + (a * 0.25f);
b = r_refdef.fog_blue * 0.01f + (a * 0.25f);
if (a > 1)
a = 1;
if (r > 1)
r = 1;
if (g > 1)
g = 1;
if (b > 1)
b = 1;
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, GU_COLOR(r,g,b,a), GU_COLOR(r,g,b,a));
}
sceGuDepthRange(32767, 65535);
// Draw the clipped vertices.
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
clipped_vertex_count, 0, display_list_vertices);
sceGuDepthRange(0, 65535);
if (r_refdef.fog_end > 0 && r_skyfog.value)
{
sceGuDisable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
}
VID_SetPaletteTX ();
Fog_EnableGFog();
}
}
else
{
if(cl.worldmodel)
VID_SetPaletteSKY ();
Fog_DisableGFog();
if (r_refdef.fog_end > 0 && r_skyfog.value)
{
a = r_refdef.fog_end * 0.00025f;
r = r_refdef.fog_red * 0.01f + (a * 0.25f);
g = r_refdef.fog_green * 0.01f + (a * 0.25f);
b = r_refdef.fog_blue * 0.01f + (a * 0.25f);
if (a > 1)
a = 1;
if (r > 1)
r = 1;
if (g > 1)
g = 1;
if (b > 1)
b = 1;
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, GU_COLOR(r,g,b,a), GU_COLOR(r,g,b,a));
}
sceGuDepthRange(32767, 65535);
// Draw the poly directly.
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
unclipped_vertex_count, 0, unclipped_vertices);
sceGuDepthRange(0, 65535);
if (r_refdef.fog_end > 0 && r_skyfog.value)
{
sceGuDisable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
}
VID_SetPaletteTX ();
Fog_EnableGFog();
}
}
}
//===============================================================
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
int i;
vec3_t verts[MAX_CLIP_VERTS];
glpoly_t *p;
if (skybox_name[0]) // if the skybox has a name, draw the skybox
{
c_sky = 0;
// GL_Bind(solidskytexture);
// calculate vertex values for sky box
for (fa=s ; fa ; fa=fa->texturechain)
{
for (p=fa->polys ; p ; p=p->next)
{
for (i=0 ; i<p->numverts ; i++)
{
VectorSubtract (p->verts[i].xyz, r_origin, verts[i]);
}
ClipSkyPolygon (p->numverts, verts[0], 0);
}
}
}
else // otherwise, draw the normal quake sky
{
// used when gl_texsort is on
GL_Bind(solidskytexture);
if (kurok)
speedscale = realtime*2;
else
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
sceGuEnable(GU_BLEND);
// sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
GL_Bind (alphaskytexture);
if (kurok)
speedscale = realtime*4;
else
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
sceGuDisable(GU_BLEND);
// sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
}
}