shpuld's single-pass clipping optimization

This commit is contained in:
Ian 2023-08-28 14:07:02 -04:00
parent 1ce07676cf
commit 85dce28921
4 changed files with 131 additions and 270 deletions

View file

@ -610,75 +610,6 @@ void Host_ServerFrame (void)
SV_SendClientMessages (); SV_SendClientMessages ();
} }
int extshit()
{
u32 size, sizeblock;
u8 *ram;
// Init variables
size = 0;
sizeblock = (1024 * 1024);
// Check loop
while (sizeblock)
{
// Increment size
size += sizeblock;
// Allocate ram
ram = (u8*)malloc(size);
// Check allocate
if (!(ram))
{
// Restore old size
size -= sizeblock;
// Size block / 2
sizeblock >>= 1;
}
else
free(ram);
}
return size;
}
int freememory()
{
u8 **ram, **temp;
u32 size, count, x;
// Init variables
ram = NULL;
size = 0;
count = 0;
// Check loop
for (;;)
{
// Check size entries
if (!(count % 10))
{
// Allocate more entries if needed
temp = (u8**)realloc(ram,sizeof(u8*) * (count + 10));
if (!(temp)) break;
// Update entries and size (size contains also size of entries)
ram = temp;
size += (sizeof(u8 *) * 10);
}
// Find max lineare size available
x = extshit();
if (!(x)) break;
// Allocate ram
ram[count] = (u8*)malloc(x);
if (!(ram[count])) break;
// Update variables
size += x;
count++;
}
// Free ram
if (ram)
{
for (x=0;x<count;x++) free(ram[x]);
free(ram);
}
return (int)size;
}
/* /*
================== ==================
Host_Frame Host_Frame

Binary file not shown.

View file

@ -153,15 +153,11 @@ typedef struct glpoly_s
struct glpoly_s *caustics_chain; // next caustic poly in chain struct glpoly_s *caustics_chain; // next caustic poly in chain
vec3_t midpoint;//MHQuake vec3_t midpoint;//MHQuake
float fxofs; //MHQuake float fxofs; //MHQuake
// This is a variable sized array, and hence must be the last element in
// this structure. // shpuld: for display list allocated temporary memory for psp rendering
// int numclippedverts;
// The array is (numverts * 2) in size. The first half are regular glvert_t * display_list_verts;
// vertices, and the second half have copies of the first half's XYZs but // Variable size array, has to be the last element of the struct. actual size is numverts
// keep the light map texture coordinates. This makes the vertices easier
// to render on the PSP.
// naievil -- changed from verts[1] to verts[2] in order to not have possible out of bounds error during compilation
// and create some sort of condition that causes the verts to not be assigned!
glvert_t verts[2]; glvert_t verts[2];
} glpoly_t; } glpoly_t;
@ -197,6 +193,11 @@ typedef struct msurface_s
byte *samples; // [numstyles*surfsize] byte *samples; // [numstyles*surfsize]
} msurface_t; } msurface_t;
typedef struct lightmap_face_s {
msurface_t *face;
struct lightmap_face_s *next;
} lightmap_face_t;
typedef struct mnode_s typedef struct mnode_s
{ {
// common with leaf // common with leaf

View file

@ -60,10 +60,20 @@ typedef struct glRect_s
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
//For none .lit maps.///////////////////////////////////////////////////////// //For none .lit maps./////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
glpoly_t *lightmap_polys[MAX_LIGHTMAPS];
qboolean lightmap_modified[MAX_LIGHTMAPS]; qboolean lightmap_modified[MAX_LIGHTMAPS];
glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; glRect_t lightmap_rectchange[MAX_LIGHTMAPS];
#define MAX_VISIBLE_LIGHTMAPPED_FACES 1024
// contains references to every msurface_t that's getting rendered.
// in testing 512 is not enough for bigger complicated areas (like parts of dm2).
// consider doubling to 2048 or somewhere inbetween.
// when the limit gets exceeded, there will be some surfaces without lightmaps.
lightmap_face_t lightmap_faces[MAX_VISIBLE_LIGHTMAPPED_FACES];
// chains of lightmap faces for each lightmap num
lightmap_face_t *lightmap_chains[MAX_LIGHTMAPS];
int num_lightmapped_faces;
int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
// the lightmap texture data needs to be kept in // the lightmap texture data needs to be kept in
@ -77,8 +87,6 @@ msurface_t *waterchain = NULL;
glpoly_t *caustics_polys = NULL; glpoly_t *caustics_polys = NULL;
glpoly_t *detail_polys = NULL; glpoly_t *detail_polys = NULL;
void R_RenderDynamicLightmaps (msurface_t *fa);
void VID_SetPaletteLM(); void VID_SetPaletteLM();
// switch palette for lightmaps // switch palette for lightmaps
@ -404,95 +412,41 @@ extern int solidskytexture;
extern int alphaskytexture; extern int alphaskytexture;
extern float speedscale; // for top sky and bottom sky extern float speedscale; // for top sky and bottom sky
static inline void DrawGLPolyLM (glpoly_t *p) static inline void DrawGLPolyLM (glpoly_t * poly)
{ {
// Does this poly need clipped? if (r_showtris.value)
const int unclipped_vertex_count = p->numverts;
const glvert_t* const unclipped_vertices = &(p->verts[p->numverts]);
if (clipping::is_clipping_required(
unclipped_vertices,
unclipped_vertex_count))
{ {
// Clip the polygon. sceGuDisable(GU_TEXTURE_2D);
const glvert_t* clipped_vertices; sceGuDisable(GU_BLEND);
std::size_t clipped_vertex_count;
clipping::clip(
unclipped_vertices,
unclipped_vertex_count,
&clipped_vertices,
&clipped_vertex_count);
// Did we have any vertices left? // Draw the lines directly.
if (clipped_vertex_count) sceGumDrawArray(
{ GU_LINE_STRIP,
// Copy the vertices to the display list. GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
const std::size_t buffer_size = clipped_vertex_count * sizeof(glvert_t); poly->numclippedverts, 0, poly->display_list_verts);
glvert_t* const display_list_vertices = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
memcpy(display_list_vertices, clipped_vertices, buffer_size);
// Draw the clipped vertices. sceGuEnable(GU_TEXTURE_2D);
sceGuDrawArray( sceGuEnable(GU_BLEND);
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
clipped_vertex_count, 0, display_list_vertices);
}
}
else
{
// Draw the poly directly.
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
unclipped_vertex_count, 0, unclipped_vertices);
}
}
static inline void DrawGLPoly (glpoly_t *p)
{
// Does this poly need clipped?
const int unclipped_vertex_count = p->numverts;
const glvert_t* const unclipped_vertices = p->verts;
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);
// Draw the clipped vertices.
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
clipped_vertex_count, 0, display_list_vertices);
}
} }
else else
{ {
// Draw the poly directly. // Draw the poly directly.
sceGuDrawArray( sceGuDrawArray(
GU_TRIANGLE_FAN, GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF, GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
unclipped_vertex_count, 0, unclipped_vertices); poly->numclippedverts, 0, poly->display_list_verts);
} }
} }
static inline void DrawGLPoly (glpoly_t * poly)
{
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
poly->numclippedverts, 0, poly->display_list_verts);
}
static inline void DrawTrisPoly (glpoly_t *p) //Crow_bar static inline void DrawTrisPoly (glpoly_t *p) //Crow_bar
{ {
sceGuDisable(GU_TEXTURE_2D); sceGuDisable(GU_TEXTURE_2D);
@ -815,7 +769,6 @@ R_BlendLightmaps
static void R_BlendLightmaps (void) static void R_BlendLightmaps (void)
{ {
int i; int i;
glpoly_t *p;
if (r_fullbright.value) if (r_fullbright.value)
return; return;
@ -830,10 +783,11 @@ static void R_BlendLightmaps (void)
if (r_lightmap.value) if (r_lightmap.value)
sceGuDisable(GU_BLEND); sceGuDisable(GU_BLEND);
lightmap_face_t * lmface;
for (i=0 ; i<MAX_LIGHTMAPS ; i++) for (i=0 ; i<MAX_LIGHTMAPS ; i++)
{ {
p = lightmap_polys[i]; lmface = lightmap_chains[i];
if (!p) if (!lmface)
continue; continue;
char lm_name[16]; char lm_name[16];
@ -845,32 +799,83 @@ static void R_BlendLightmaps (void)
lightmap_rectchange[i].w = 0; lightmap_rectchange[i].w = 0;
lightmap_rectchange[i].h = 0; lightmap_rectchange[i].h = 0;
sprintf(lm_name,"lightmap%d",i); snprintf(lm_name, sizeof(lm_name), "lightmap%d",i);
lightmap_index[i] = GL_LoadTextureLM (lm_name, BLOCK_WIDTH, BLOCK_HEIGHT, lightmaps+(i*BLOCK_WIDTH*BLOCK_HEIGHT*LIGHTMAP_BYTES), LIGHTMAP_BYTES, GU_LINEAR, qtrue, qfalse); lightmap_index[i] = GL_LoadTextureLM (lm_name, BLOCK_WIDTH, BLOCK_HEIGHT, lightmaps+(i*BLOCK_WIDTH*BLOCK_HEIGHT*LIGHTMAP_BYTES), LIGHTMAP_BYTES, GU_LINEAR, qtrue, qfalse);
} }
GL_BindLM (lightmap_index[i]); GL_BindLM (lightmap_index[i]);
for ( ; p ; p=p->chain) for (; lmface; lmface = lmface->next) {
{ msurface_t * face = lmface->face;
if (p->flags & SURF_UNDERWATER) float scale = 0.0625f;
{ float tscale = face->texinfo->texture->width / (BLOCK_WIDTH * 16.f);
DrawGLPolyLM(p); float sscale = face->texinfo->texture->height / (BLOCK_HEIGHT * 16.f);
//DrawGLWaterPolyLM(p);
}
else
DrawGLPolyLM(p);
sceGuTexScale(tscale, sscale);
sceGuTexOffset(
tscale * (float)(-1.f * face->texturemins[0] + face->light_s * 16 + 8) / (float)(face->texinfo->texture->width),
sscale * (float)(-1.f * face->texturemins[1] + face->light_t * 16 + 8) / (float)(face->texinfo->texture->height)
);
DrawGLPolyLM(face->polys);
} }
} }
if(LIGHTMAP_BYTES == 1) if(LIGHTMAP_BYTES == 1)
VID_SetPaletteTX(); VID_SetPaletteTX();
sceGuTexOffset(0, 0);
sceGuTexScale(1, 1);
sceGuDisable(GU_BLEND); sceGuDisable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
sceGuDepthMask (GU_FALSE); sceGuDepthMask (GU_FALSE);
sceGuEnable(GU_DEPTH_TEST); // dr_mabuse1981: fix sceGuEnable(GU_DEPTH_TEST); // dr_mabuse1981: fix
} }
int ClipFace (msurface_t * fa)
{
// shpuld: moved clipping here to have it in one place only
int verts_total = 0;
glpoly_t* poly = fa->polys;
const int unclipped_vertex_count = poly->numverts;
const glvert_t* const unclipped_vertices = poly->verts;
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
);
verts_total += clipped_vertex_count;
// Did we have any vertices left?
if (!clipped_vertex_count)
{
poly->numclippedverts = 0;
return verts_total;
}
const std::size_t buffer_size = clipped_vertex_count * sizeof(glvert_t);
poly->display_list_verts = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
memcpy(poly->display_list_verts, clipped_vertices, buffer_size);
poly->numclippedverts = clipped_vertex_count;
} else {
verts_total += unclipped_vertex_count;
const std::size_t buffer_size = unclipped_vertex_count * sizeof(glvert_t);
poly->display_list_verts = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
memcpy(poly->display_list_verts, unclipped_vertices, buffer_size);
poly->numclippedverts = unclipped_vertex_count;
}
return verts_total;
}
/* /*
================ ================
R_RenderBrushPoly R_RenderBrushPoly
@ -887,17 +892,12 @@ void R_RenderBrushPoly (msurface_t *fa)
c_brush_polys++; c_brush_polys++;
/*if(r_showtris.value) //Crow_bar // sky and water use multiple polys per surface,
{ // this makes clipping more tricky, but they don't have LMs so no prob.
sceGuDepthMask (GU_TRUE);
DrawTrisPoly (fa->polys);
sceGuDepthMask (GU_FALSE);
}*/
if (fa->flags & SURF_DRAWSKY) if (fa->flags & SURF_DRAWSKY)
{ // warp texture, no lightmaps {
// warp texture, no lightmaps
// shpuld: replace with scissor pass and then sky, maybe faster?
EmitBothSkyLayers (fa); EmitBothSkyLayers (fa);
return; return;
} }
@ -911,6 +911,12 @@ void R_RenderBrushPoly (msurface_t *fa)
return; return;
} }
// Everything from here only uses 1 poly from fa->polys
int verts_count = ClipFace(fa);
if (verts_count <= 0)
return;
sceGuEnable(GU_ALPHA_TEST); sceGuEnable(GU_ALPHA_TEST);
sceGuAlphaFunc(GU_GREATER, 0xaa, 0xff); sceGuAlphaFunc(GU_GREATER, 0xaa, 0xff);
sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
@ -931,10 +937,14 @@ void R_RenderBrushPoly (msurface_t *fa)
} }
// motolegacy -- end texflags // motolegacy -- end texflags
// add the poly to the proper lightmap chain // Manage lightmap chain
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; if (num_lightmapped_faces < MAX_VISIBLE_LIGHTMAPPED_FACES)
lightmap_polys[fa->lightmaptexturenum] = fa->polys; {
lightmap_faces[num_lightmapped_faces].face = fa;
lightmap_faces[num_lightmapped_faces].next = lightmap_chains[fa->lightmaptexturenum];
lightmap_chains[fa->lightmaptexturenum] = &lightmap_faces[num_lightmapped_faces];
num_lightmapped_faces++;
}
// check for lightmap modification // check for lightmap modification
for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; maps++) for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; maps++)
@ -976,64 +986,6 @@ dynamic:
sceGuDisable(GU_ALPHA_TEST); sceGuDisable(GU_ALPHA_TEST);
} }
/*
================
R_RenderDynamicLightmaps
Multitexture
================
*/
void R_RenderDynamicLightmaps (msurface_t *fa)
{
byte *base;
int maps;
glRect_t *theRect;
int smax, tmax;
c_brush_polys++;
if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
return;
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
lightmap_polys[fa->lightmaptexturenum] = fa->polys;
// check for lightmap modification
for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
maps++)
if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
goto dynamic;
if (fa->dlightframe == r_framecount // dynamic this frame
|| fa->cached_dlight) // dynamic previously
{
dynamic:
if (r_dynamic.value)
{
lightmap_modified[fa->lightmaptexturenum] = qtrue;
theRect = &lightmap_rectchange[fa->lightmaptexturenum];
if (fa->light_t < theRect->t) {
if (theRect->h)
theRect->h += theRect->t - fa->light_t;
theRect->t = fa->light_t;
}
if (fa->light_s < theRect->l) {
if (theRect->w)
theRect->w += theRect->l - fa->light_s;
theRect->l = fa->light_s;
}
smax = (fa->extents[0]>>4)+1;
tmax = (fa->extents[1]>>4)+1;
if ((theRect->w + theRect->l) < (fa->light_s + smax))
theRect->w = (fa->light_s-theRect->l)+smax;
if ((theRect->h + theRect->t) < (fa->light_t + tmax))
theRect->h = (fa->light_t-theRect->t)+tmax;
base = lightmaps + fa->lightmaptexturenum*LIGHTMAP_BYTES*BLOCK_WIDTH*BLOCK_HEIGHT;
base += fa->light_t * BLOCK_WIDTH * LIGHTMAP_BYTES + fa->light_s * LIGHTMAP_BYTES;
R_BuildLightMap (fa, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
}
}
}
/* /*
================ ================
R_MirrorChain R_MirrorChain
@ -1227,7 +1179,8 @@ void R_DrawBrushModel (entity_t *e)
} }
memset (lightmap_polys, 0, sizeof(lightmap_polys)); memset (lightmap_chains, 0, sizeof(lightmap_chains));
num_lightmapped_faces = 0;
VectorSubtract (r_refdef.vieworg, e->origin, modelorg); VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
if (rotated) if (rotated)
@ -1526,7 +1479,8 @@ void R_DrawWorld (void)
currenttexture = -1; currenttexture = -1;
/*glColor3f (1,1,1);*/ /*glColor3f (1,1,1);*/
memset (lightmap_polys, 0, sizeof(lightmap_polys)); memset (lightmap_chains, 0, sizeof(lightmap_chains));
num_lightmapped_faces = 0;
R_ClearSkyBox (); R_ClearSkyBox ();
@ -1673,7 +1627,7 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
// //
// draw texture // draw texture
// //
poly = static_cast<glpoly_t*>(Hunk_Alloc (sizeof(glpoly_t) + (lnumverts * 2 - 1) * sizeof(glvert_t))); poly = static_cast<glpoly_t*>(Hunk_Alloc (sizeof(glpoly_t) + (lnumverts - 1) * sizeof(glvert_t)));
poly->next = fa->polys; poly->next = fa->polys;
poly->flags = fa->flags; poly->flags = fa->flags;
fa->polys = poly; fa->polys = poly;
@ -1702,25 +1656,6 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
VectorCopy(vec, poly->verts[i].xyz); VectorCopy(vec, poly->verts[i].xyz);
poly->verts[i].st[0] = s; poly->verts[i].st[0] = s;
poly->verts[i].st[1] = t; poly->verts[i].st[1] = t;
//
// lightmap texture coordinates
//
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s*16;
s += 8;
s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t*16;
t += 8;
t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
VectorCopy(vec, poly->verts[i + lnumverts].xyz);
poly->verts[i + lnumverts].st[0] = s;
poly->verts[i + lnumverts].st[1] = t;
} }
// //
@ -1760,7 +1695,6 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
for (j = i + 1; j < lnumverts; j = j + 1) for (j = i + 1; j < lnumverts; j = j + 1)
{ {
poly->verts[j - 1] = poly->verts[j]; poly->verts[j - 1] = poly->verts[j];
poly->verts[poly->numverts + j - 1] = poly->verts[poly->numverts+j];
} }
--lnumverts; --lnumverts;
@ -1770,12 +1704,6 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
--i; --i;
} }
} }
if (numRemoved > 0) {
for (j = poly->numverts; j < poly->numverts + lnumverts; j++) {
poly->verts[j - numRemoved] = poly->verts[j];
}
}
} }
// Colinear point removal-end // Colinear point removal-end
@ -1846,6 +1774,7 @@ void GL_BuildLightmaps (void)
currentmodel = m; currentmodel = m;
for (i=0 ; i<m->numsurfaces ; i++) for (i=0 ; i<m->numsurfaces ; i++)
{ {
// todo: investigate why this is done even for turb/sky
GL_CreateSurfaceLightmap (m->surfaces + i); GL_CreateSurfaceLightmap (m->surfaces + i);
if ( m->surfaces[i].flags & SURF_DRAWTURB ) if ( m->surfaces[i].flags & SURF_DRAWTURB )
continue; continue;