GL1 scrap/atlas configurable size

Controlled by gl1_biglightmaps cvar, works like new lightmaps.
Max size is 384x384; a bigger size is not justified.
Added a transparent border so colors from one picture don't bleed
into the next.
This commit is contained in:
Jaime Moreira 2024-05-11 18:20:13 -04:00
parent 81fd2c1027
commit 0f307cc9c1
5 changed files with 78 additions and 14 deletions

View file

@ -460,7 +460,7 @@ Set `0` by default.
## Graphics (OpenGL 1.4 only)
* **gl1_biglightmaps**: Enables lightmaps to use a bigger
* **gl1_biglightmaps**: Enables lightmaps and scrap to use a bigger
texture size, which means fewer texture switches, improving
performance. Default is `1` (enabled). Requires a `vid_restart`.

View file

@ -31,7 +31,7 @@ int numgltextures;
static int image_max = 0;
int base_textureid; /* gltextures[i] = base_textureid+i */
extern qboolean scrap_dirty;
extern byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT];
extern byte *scrap_texels[MAX_SCRAPS];
static byte intensitytable[256];
static unsigned char gammatable[256];
@ -1040,17 +1040,17 @@ R_LoadPic(const char *name, byte *pic, int width, int realwidth,
{
for (j = 0; j < image->width; j++, k++)
{
scrap_texels[texnum][(y + i) * BLOCK_WIDTH + x + j] = pic[k];
scrap_texels[texnum][(y + i) * gl_state.scrap_width + x + j] = pic[k];
}
}
image->texnum = TEXNUM_SCRAPS + texnum;
image->scrap = true;
image->has_alpha = true;
image->sl = (x + 0.01) / (float)BLOCK_WIDTH;
image->sh = (x + image->width - 0.01) / (float)BLOCK_WIDTH;
image->tl = (y + 0.01) / (float)BLOCK_WIDTH;
image->th = (y + image->height - 0.01) / (float)BLOCK_WIDTH;
image->sl = (float)x / gl_state.scrap_width;
image->sh = (float)(x + image->width) / gl_state.scrap_width;
image->tl = (float)y / gl_state.scrap_height;
image->th = (float)(y + image->height) / gl_state.scrap_height;
}
else
{

View file

@ -146,6 +146,8 @@ cvar_t *gl1_stereo_convergence;
refimport_t ri;
void LM_FreeLightmapBuffers(void);
void Scrap_Free(void);
void Scrap_Init(void);
void
R_RotateForEntity(entity_t *e)
@ -1647,6 +1649,8 @@ RI_Init(void)
gl_state.block_width = BLOCK_WIDTH;
gl_state.block_height = BLOCK_HEIGHT;
gl_state.max_lightmaps = MAX_LIGHTMAPS;
gl_state.scrap_width = BLOCK_WIDTH;
gl_state.scrap_height = BLOCK_HEIGHT;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_size);
if (max_tex_size > BLOCK_WIDTH)
{
@ -1655,6 +1659,8 @@ RI_Init(void)
gl_state.block_width = gl_state.block_height = Q_min(max_tex_size, 512);
gl_state.max_lightmaps = (BLOCK_WIDTH * BLOCK_HEIGHT * MAX_LIGHTMAPS)
/ (gl_state.block_width * gl_state.block_height);
gl_state.scrap_width = gl_state.scrap_height =
(gl_config.npottextures)? Q_min(max_tex_size, 384) : Q_min(max_tex_size, 256);
R_Printf(PRINT_ALL, "Okay\n");
}
else
@ -1671,6 +1677,7 @@ RI_Init(void)
R_SetDefaultState();
Scrap_Init();
R_InitImages();
Mod_Init();
R_InitParticleTexture();
@ -1688,6 +1695,7 @@ RI_Shutdown(void)
ri.Cmd_RemoveCommand("gl_strings");
LM_FreeLightmapBuffers();
Scrap_Free();
Mod_FreeAll();
R_ShutdownImages();

View file

@ -27,8 +27,8 @@
#include "header/local.h"
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT];
int *scrap_allocated[MAX_SCRAPS];
byte *scrap_texels[MAX_SCRAPS];
qboolean scrap_dirty;
qboolean R_Upload8(byte *data,
@ -44,12 +44,14 @@ Scrap_AllocBlock(int w, int h, int *x, int *y)
int i, j;
int best, best2;
int texnum;
w += 2; // add an empty border to all sides
h += 2;
for (texnum = 0; texnum < MAX_SCRAPS; texnum++)
{
best = BLOCK_HEIGHT;
best = gl_state.scrap_height;
for (i = 0; i < BLOCK_WIDTH - w; i++)
for (i = 0; i < gl_state.scrap_width - w; i++)
{
best2 = 0;
@ -73,7 +75,7 @@ Scrap_AllocBlock(int w, int h, int *x, int *y)
}
}
if (best + h > BLOCK_HEIGHT)
if (best + h > gl_state.scrap_height)
{
continue;
}
@ -82,6 +84,8 @@ Scrap_AllocBlock(int w, int h, int *x, int *y)
{
scrap_allocated[texnum][*x + i] = best + h;
}
(*x)++; // jump the border
(*y)++;
return texnum;
}
@ -93,7 +97,57 @@ void
Scrap_Upload(void)
{
R_Bind(TEXNUM_SCRAPS);
R_Upload8(scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, false);
R_Upload8(scrap_texels[0], gl_state.scrap_width,
gl_state.scrap_height, false, false);
scrap_dirty = false;
}
void
Scrap_Free(void)
{
for (int i = 0; i < MAX_SCRAPS; i++)
{
if (scrap_allocated[i])
{
free(scrap_allocated[i]);
}
scrap_allocated[i] = NULL;
if (scrap_texels[i])
{
free(scrap_texels[i]);
}
scrap_texels[i] = NULL;
}
}
void
Scrap_Init(void)
{
const unsigned int allocd_size = gl_state.scrap_width * sizeof(int);
const unsigned int texels_size = gl_state.scrap_width
* gl_state.scrap_height * sizeof(byte);
int i;
Scrap_Free();
for (i = 0; i < MAX_SCRAPS; i++)
{
if (!scrap_allocated[i])
{
scrap_allocated[i] = malloc (allocd_size) ;
}
if (!scrap_texels[i])
{
scrap_texels[i] = malloc (texels_size) ;
}
if (!scrap_allocated[i] || !scrap_texels[i])
{
ri.Sys_Error(ERR_FATAL, "Could not allocate scrap memory.\n");
}
memset (scrap_allocated[i], 0, allocd_size); // empty
memset (scrap_texels[i], 255, texels_size); // transparent
}
}

View file

@ -394,7 +394,9 @@ typedef struct
int block_width, // replaces BLOCK_WIDTH
block_height, // replaces BLOCK_HEIGHT
max_lightmaps; // the larger the lightmaps, the fewer the max lightmaps
max_lightmaps, // the larger the lightmaps, the fewer the max lightmaps
scrap_width, // size for scrap (atlas of 2D elements)
scrap_height;
} glstate_t;
typedef struct