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 ();
}
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

Binary file not shown.

View file

@ -153,15 +153,11 @@ typedef struct glpoly_s
struct glpoly_s *caustics_chain; // next caustic poly in chain
vec3_t midpoint;//MHQuake
float fxofs; //MHQuake
// This is a variable sized array, and hence must be the last element in
// this structure.
//
// The array is (numverts * 2) in size. The first half are regular
// vertices, and the second half have copies of the first half's XYZs but
// 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!
// shpuld: for display list allocated temporary memory for psp rendering
int numclippedverts;
glvert_t * display_list_verts;
// Variable size array, has to be the last element of the struct. actual size is numverts
glvert_t verts[2];
} glpoly_t;
@ -197,6 +193,11 @@ typedef struct msurface_s
byte *samples; // [numstyles*surfsize]
} msurface_t;
typedef struct lightmap_face_s {
msurface_t *face;
struct lightmap_face_s *next;
} lightmap_face_t;
typedef struct mnode_s
{
// common with leaf

View file

@ -60,10 +60,20 @@ typedef struct glRect_s
//////////////////////////////////////////////////////////////////////////////
//For none .lit maps./////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
glpoly_t *lightmap_polys[MAX_LIGHTMAPS];
qboolean lightmap_modified[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];
// the lightmap texture data needs to be kept in
@ -77,8 +87,6 @@ msurface_t *waterchain = NULL;
glpoly_t *caustics_polys = NULL;
glpoly_t *detail_polys = NULL;
void R_RenderDynamicLightmaps (msurface_t *fa);
void VID_SetPaletteLM();
// switch palette for lightmaps
@ -404,95 +412,41 @@ extern int solidskytexture;
extern int alphaskytexture;
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?
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))
if (r_showtris.value)
{
// 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);
sceGuDisable(GU_TEXTURE_2D);
sceGuDisable(GU_BLEND);
// 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 lines directly.
sceGumDrawArray(
GU_LINE_STRIP,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
poly->numclippedverts, 0, poly->display_list_verts);
// Draw the clipped vertices.
sceGuDrawArray(
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);
}
}
sceGuEnable(GU_TEXTURE_2D);
sceGuEnable(GU_BLEND);
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
{
// Draw the poly directly.
sceGuDrawArray(
GU_TRIANGLE_FAN,
GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
unclipped_vertex_count, 0, unclipped_vertices);
GU_TEXTURE_32BITF | GU_VERTEX_32BITF ,
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
{
sceGuDisable(GU_TEXTURE_2D);
@ -815,7 +769,6 @@ R_BlendLightmaps
static void R_BlendLightmaps (void)
{
int i;
glpoly_t *p;
if (r_fullbright.value)
return;
@ -830,10 +783,11 @@ static void R_BlendLightmaps (void)
if (r_lightmap.value)
sceGuDisable(GU_BLEND);
lightmap_face_t * lmface;
for (i=0 ; i<MAX_LIGHTMAPS ; i++)
{
p = lightmap_polys[i];
if (!p)
lmface = lightmap_chains[i];
if (!lmface)
continue;
char lm_name[16];
@ -845,32 +799,83 @@ static void R_BlendLightmaps (void)
lightmap_rectchange[i].w = 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);
}
GL_BindLM (lightmap_index[i]);
for ( ; p ; p=p->chain)
{
if (p->flags & SURF_UNDERWATER)
{
DrawGLPolyLM(p);
//DrawGLWaterPolyLM(p);
}
else
DrawGLPolyLM(p);
for (; lmface; lmface = lmface->next) {
msurface_t * face = lmface->face;
float scale = 0.0625f;
float tscale = face->texinfo->texture->width / (BLOCK_WIDTH * 16.f);
float sscale = face->texinfo->texture->height / (BLOCK_HEIGHT * 16.f);
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)
VID_SetPaletteTX();
sceGuTexOffset(0, 0);
sceGuTexScale(1, 1);
sceGuDisable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
sceGuDepthMask (GU_FALSE);
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
@ -887,17 +892,12 @@ void R_RenderBrushPoly (msurface_t *fa)
c_brush_polys++;
/*if(r_showtris.value) //Crow_bar
{
sceGuDepthMask (GU_TRUE);
DrawTrisPoly (fa->polys);
sceGuDepthMask (GU_FALSE);
}*/
// sky and water use multiple polys per surface,
// this makes clipping more tricky, but they don't have LMs so no prob.
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);
return;
}
@ -911,6 +911,12 @@ void R_RenderBrushPoly (msurface_t *fa)
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);
sceGuAlphaFunc(GU_GREATER, 0xaa, 0xff);
sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
@ -931,10 +937,14 @@ void R_RenderBrushPoly (msurface_t *fa)
}
// motolegacy -- end texflags
// add the poly to the proper lightmap chain
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
lightmap_polys[fa->lightmaptexturenum] = fa->polys;
// Manage lightmap chain
if (num_lightmapped_faces < MAX_VISIBLE_LIGHTMAPPED_FACES)
{
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
for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; maps++)
@ -976,64 +986,6 @@ dynamic:
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
@ -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);
if (rotated)
@ -1526,7 +1479,8 @@ void R_DrawWorld (void)
currenttexture = -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 ();
@ -1673,7 +1627,7 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
//
// 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->flags = fa->flags;
fa->polys = poly;
@ -1702,25 +1656,6 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
VectorCopy(vec, poly->verts[i].xyz);
poly->verts[i].st[0] = s;
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)
{
poly->verts[j - 1] = poly->verts[j];
poly->verts[poly->numverts + j - 1] = poly->verts[poly->numverts+j];
}
--lnumverts;
@ -1770,12 +1704,6 @@ static void BuildSurfaceDisplayList (msurface_t *fa)
--i;
}
}
if (numRemoved > 0) {
for (j = poly->numverts; j < poly->numverts + lnumverts; j++) {
poly->verts[j - numRemoved] = poly->verts[j];
}
}
}
// Colinear point removal-end
@ -1846,6 +1774,7 @@ void GL_BuildLightmaps (void)
currentmodel = m;
for (i=0 ; i<m->numsurfaces ; i++)
{
// todo: investigate why this is done even for turb/sky
GL_CreateSurfaceLightmap (m->surfaces + i);
if ( m->surfaces[i].flags & SURF_DRAWTURB )
continue;