Merge pull request #47 from 0lvin/rerelease

Support lightmap from Q2 ReRelease
This commit is contained in:
Denis Pauk 2023-08-22 17:08:18 +03:00 committed by GitHub
commit 5ba12c08b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 239 additions and 65 deletions

View File

@ -333,9 +333,10 @@ typedef struct m32tex_s
/* .BSP file format */
#define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I') /* little-endian "IBSP" */
#define BSPXHEADER (('X' << 24) + ('P' << 16) + ('S' << 8) + 'B') /* little-endian "BSPX" */
#define BSPVERSION 38
/* upper design bounds: leaffaces, leafbrushes, planes, and
/* upper design bounds: leaffaces, leafbrushes, planes, and
* verts are still bounded by 16 bit short limits */
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
@ -399,6 +400,17 @@ typedef struct
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct bspx_header_s {
int ident; // 'BSPX'
int numlumps;
} bspx_header_t;
typedef struct {
char lumpname[24];
int fileofs;
int filelen;
} bspx_lump_t;
typedef struct
{
float mins[3], maxs[3];
@ -493,12 +505,12 @@ typedef struct texinfo_s
{
float vecs[2][4]; /* [s/t][xyz offset] */
int flags; /* miptex flags + overrides light emission, etc */
int value;
int value;
char texture[32]; /* texture name (textures*.wal) */
int nexttexinfo; /* for animations, -1 = end of chain */
} texinfo_t;
/* note that edge 0 is never used, because negative edge
/* note that edge 0 is never used, because negative edge
nums are used for counterclockwise use of the edge in
a face */
typedef struct
@ -521,6 +533,13 @@ typedef struct
int lightofs; /* start of [numstyles*surfsize] samples */
} dface_t;
typedef struct {
unsigned short lmwidth;
unsigned short lmheight;
int lightofs;
float vecs[2][4];
} dlminfo_t;
typedef struct
{
int contents; /* OR of all brushes (not needed?) */
@ -554,8 +573,8 @@ typedef struct
#define ANGLE_UP -1
#define ANGLE_DOWN -2
/* the visibility lump consists of a header with a count, then
* byte offsets for the PVS and PHS of each cluster, then the raw
/* the visibility lump consists of a header with a count, then
* byte offsets for the PVS and PHS of each cluster, then the raw
* compressed bit vectors */
#define DVIS_PVS 0
#define DVIS_PHS 1

View File

@ -43,6 +43,7 @@ BRUSH MODELS
//
#define VERTEXSIZE 7
#define DEFAULT_LMSHIFT 4
typedef struct vkpoly_s
{
@ -66,6 +67,8 @@ typedef struct msurface_s
short texturemins[2];
short extents[2];
short lmshift;
int light_s, light_t; // gl lightmap coordinates
int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps
@ -75,7 +78,11 @@ typedef struct msurface_s
mtexinfo_t *texinfo;
// lighting info
/* decoupled lm */
float lmvecs[2][4];
float lmvlen[2];
/* lighting info */
int dlightframe;
int dlightbits;

View File

@ -215,9 +215,9 @@ RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end, vec3_t pointcolor)
}
frac = front / (front-back);
mid[0] = start[0] + (end[0] - start[0])*frac;
mid[1] = start[1] + (end[1] - start[1])*frac;
mid[2] = start[2] + (end[2] - start[2])*frac;
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = RecursiveLightPoint(node->children[side], start, mid, pointcolor);
@ -262,13 +262,13 @@ RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end, vec3_t pointcolor)
return 0;
}
ds >>= 4;
dt >>= 4;
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> 4) + 1) + ds);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
@ -276,14 +276,14 @@ RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end, vec3_t pointcolor)
for (j = 0; j < 3; j++)
{
scale[j] = r_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[j];
scale[j] = r_modulate->value * r_newrefdef.lightstyles[surf->styles[maps]].rgb[j];
}
pointcolor[0] += lightmap[0] * scale[0] * (1.0/255);
pointcolor[1] += lightmap[1] * scale[1] * (1.0/255);
pointcolor[2] += lightmap[2] * scale[2] * (1.0/255);
lightmap += 3 * ((surf->extents[0] >> 4) + 1) *
((surf->extents[1] >> 4) + 1);
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
@ -367,14 +367,12 @@ R_AddDynamicLights(msurface_t *surf)
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
dlight_t *dl;
float *plightdest;
float fsacc, ftacc;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
tex = surf->texinfo;
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
{
@ -404,23 +402,27 @@ R_AddDynamicLights(msurface_t *surf)
surf->plane->normal[i]*fdist;
}
local[0] = DotProduct(impact, tex->vecs[0]) + tex->vecs[0][3] - surf->texturemins[0];
local[1] = DotProduct(impact, tex->vecs[1]) + tex->vecs[1][3] - surf->texturemins[1];
local[0] = DotProduct (impact, surf->lmvecs[0]) + surf->lmvecs[0][3] - surf->texturemins[0];
local[1] = DotProduct (impact, surf->lmvecs[1]) + surf->lmvecs[1][3] - surf->texturemins[1];
plightdest = s_blocklights;
for (t = 0, ftacc = 0 ; t<tmax ; t++, ftacc += 16)
for (t = 0, ftacc = 0; t < tmax; t++, ftacc += (1 << surf->lmshift))
{
td = local[1] - ftacc;
if ( td < 0 )
if (td < 0)
td = -td;
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += 16, plightdest += 3)
td *= surf->lmvlen[1];
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += (1 << surf->lmshift), plightdest += 3)
{
sd = Q_ftol( local[0] - fsacc );
if ( sd < 0 )
sd = -sd;
sd *= surf->lmvlen[0];
if (sd > td)
fdist = sd + (td>>1);
else
@ -479,8 +481,8 @@ R_BuildLightMap(msurface_t *surf, byte *dest, int stride)
ri.Sys_Error (ERR_DROP, "R_BuildLightMap called for non-lit surface");
}
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
size = smax * tmax;
if (!s_blocklights || (s_blocklights + (size * 3) >= s_blocklights_max))

View File

@ -356,7 +356,8 @@ Vk_DrawAliasFrameLerpCommands (entity_t *currententity, int *order, int *order_e
}
else
{
meshUbo.textured = 1;
/* Do not apply texture for lighmap debug case */
meshUbo.textured = r_lightmap->value ? 0 : 1;
do
{
int vertIdx = vertCounts[pipelineIdx];

View File

@ -375,17 +375,154 @@ calcTexinfoAndFacesSize(const lump_t *fl, const byte *mod_base, const lump_t *tl
return ret;
}
// Extension to support lightmaps that aren't tied to texture scale.
static int
Mod_LoadDecoupledLM(const dlminfo_t* lminfos, int surfnum, msurface_t *out)
{
const dlminfo_t *lminfo;
unsigned short lmwidth, lmheight;
if (lminfos == NULL) {
return -1;
}
lminfo = lminfos + surfnum;
lmwidth = LittleShort(lminfo->lmwidth);
lmheight = LittleShort(lminfo->lmheight);
if (lmwidth <= 0 || lmheight <= 0) {
return -1;
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
out->lmvecs[i][j] = LittleFloat(lminfo->vecs[i][j]);
}
}
out->extents[0] = (short)(lmwidth - 1);
out->extents[1] = (short)(lmheight - 1);
out->lmshift = 0;
out->texturemins[0] = 0;
out->texturemins[1] = 0;
float v0 = VectorLength(out->lmvecs[0]);
out->lmvlen[0] = v0 > 0.0f ? 1.0f / v0 : 0.0f;
float v1 = VectorLength(out->lmvecs[1]);
out->lmvlen[1] = v1 > 0.0f ? 1.0f / v1 : 0.0f;
return LittleLong(lminfo->lightofs);
}
const void *
Mod_BSPX_FindLump(bspx_header_t* bspx_header, char* lumpname, int* plumpsize, const byte* mod_base)
{
int i;
bspx_lump_t* lump;
if (!bspx_header) {
return NULL;
}
lump = (bspx_lump_t*)(bspx_header + 1);
for (i = 0; i < bspx_header->numlumps; i++, lump++) {
if (!strcmp(lump->lumpname, lumpname)) {
if (plumpsize) {
*plumpsize = lump->filelen;
}
return mod_base + lump->fileofs;
}
}
return NULL;
}
bspx_header_t *
Mod_LoadBSPX(int filesize, byte* mod_base)
{
dheader_t* header;
bspx_header_t* xheader;
bspx_lump_t* lump;
int i;
int xofs;
// find end of last lump
header = (dheader_t*)mod_base;
xofs = 0;
for (i = 0; i < HEADER_LUMPS; i++) {
xofs = max(xofs,
ROUNDUP(header->lumps[i].fileofs + header->lumps[i].filelen, sizeof(int)));
}
if (xofs + sizeof(bspx_header_t) > filesize) {
return NULL;
}
xheader = (bspx_header_t*)(mod_base + xofs);
if (LittleLong(xheader->ident) != BSPXHEADER)
{
R_Printf(PRINT_ALL, "%s: Incorrect header ident.\n",
__func__, xheader->ident, BSPXHEADER);
return NULL;
}
xheader->numlumps = LittleLong(xheader->numlumps);
if (xheader->numlumps < 0 || xofs + sizeof(bspx_header_t) + xheader->numlumps * sizeof(bspx_lump_t) > filesize) {
return NULL;
}
// byte-swap and check sanity
lump = (bspx_lump_t*)(xheader + 1); // lumps immediately follow the header
for (i = 0; i < xheader->numlumps; i++, lump++) {
lump->lumpname[sizeof(lump->lumpname) - 1] = '\0'; // make sure it ends with zero
lump->fileofs = LittleLong(lump->fileofs);
lump->filelen = LittleLong(lump->filelen);
if (lump->fileofs < 0 || lump->filelen < 0 || (unsigned)(lump->fileofs + lump->filelen) >(unsigned)filesize) {
return NULL;
}
}
// success
return xheader;
}
static void
SetSurfaceLighting(model_t* loadmodel, msurface_t* out, byte* styles, int lightofs)
{
int i;
/* lighting info */
for (i = 0; i < MAXLIGHTMAPS; i++)
{
out->styles[i] = styles[i];
}
i = LittleLong(lightofs);
if (i == -1 || loadmodel->lightdata == NULL)
{
out->samples = NULL;
}
else
{
out->samples = loadmodel->lightdata + i;
}
}
/*
=================
Mod_LoadFaces
=================
*/
static void
Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
Mod_LoadFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l, bspx_header_t *bspx_header)
{
dface_t *in;
int i, count, surfnum, lminfosize, lightofs;
const dlminfo_t *lminfos;
msurface_t *out;
int i, count, surfnum;
dface_t *in;
in = (void *)(mod_base + l->fileofs);
@ -401,6 +538,13 @@ Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
lminfos = Mod_BSPX_FindLump(bspx_header, "DECOUPLED_LM", &lminfosize, mod_base);
if (lminfos != NULL && lminfosize / sizeof(dlminfo_t) != loadmodel->numsurfaces) {
R_Printf(PRINT_ALL, "%s: [%s] decoupled_lm size %ld does not match surface count %d\n",
__func__, loadmodel->name, lminfosize / sizeof(dlminfo_t), loadmodel->numsurfaces);
lminfos = NULL;
}
Vk_BeginBuildingLightmaps(loadmodel);
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
@ -444,24 +588,19 @@ Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
out->texinfo = loadmodel->texinfo + ti;
CalcSurfaceExtents(loadmodel, out);
lightofs = Mod_LoadDecoupledLM(lminfos, surfnum, out);
if (lightofs < 0) {
memcpy(out->lmvecs, out->texinfo->vecs, sizeof(out->lmvecs));
out->lmshift = DEFAULT_LMSHIFT;
out->lmvlen[0] = 1.0f;
out->lmvlen[1] = 1.0f;
/* lighting info */
for (i = 0; i < MAXLIGHTMAPS; i++)
{
out->styles[i] = in->styles[i];
CalcSurfaceExtents(loadmodel, out);
lightofs = in->lightofs;
}
i = LittleLong(in->lightofs);
if (i == -1)
{
out->samples = NULL;
}
else
{
out->samples = loadmodel->lightdata + i;
}
SetSurfaceLighting(loadmodel, out, in->styles, lightofs);
/* set the drawing flags */
if (out->texinfo->flags & SURF_WARP)
@ -635,9 +774,10 @@ Mod_LoadBrushModel
static void
Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
{
int i;
dheader_t *header;
bspx_header_t* bspx_header;
byte *mod_base;
dheader_t *header;
int i;
header = (dheader_t *)buffer;
@ -677,6 +817,10 @@ Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
mod->extradata = Hunk_Begin(hunkSize);
mod->type = mod_brush;
/* check for BSPX extensions */
bspx_header = Mod_LoadBSPX(modfilelen, (byte*)header);
/* load into heap */
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
&header->lumps[LUMP_VERTEXES], 0);
@ -685,14 +829,14 @@ Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
Mod_LoadSurfedges(mod->name, &mod->surfedges, &mod->numsurfedges,
mod_base, &header->lumps[LUMP_SURFEDGES], 0);
Mod_LoadLighting(&mod->lightdata, mod_base, &header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes (mod->name, &mod->planes, &mod->numplanes,
Mod_LoadPlanes(mod->name, &mod->planes, &mod->numplanes,
mod_base, &header->lumps[LUMP_PLANES], 0);
Mod_LoadTexinfo(mod->name, &mod->texinfo, &mod->numtexinfo,
mod_base, &header->lumps[LUMP_TEXINFO], (findimage_t)Vk_FindImage,
r_notexture, 0);
Mod_LoadFaces(mod, mod_base, &header->lumps[LUMP_FACES]);
Mod_LoadFaces(mod, mod_base, &header->lumps[LUMP_FACES], bspx_header);
Mod_LoadMarksurfaces(mod, mod_base, &header->lumps[LUMP_LEAFFACES]);
Mod_LoadVisibility (&mod->vis, mod_base, &header->lumps[LUMP_VISIBILITY]);
Mod_LoadVisibility(&mod->vis, mod_base, &header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]);
Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs,
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base,

View File

@ -303,8 +303,8 @@ static void R_RenderBrushPoly (msurface_t *fa, float *modelMatrix, float alpha,
unsigned temp[34 * 34];
int smax, tmax;
smax = (fa->extents[0] >> 4) + 1;
tmax = (fa->extents[1] >> 4) + 1;
smax = (fa->extents[0] >> fa->lmshift) + 1;
tmax = (fa->extents[1] >> fa->lmshift) + 1;
R_BuildLightMap(fa, (void *)temp, smax * 4);
R_SetCacheState(fa);
@ -477,8 +477,8 @@ static void Vk_RenderLightmappedPoly( msurface_t *surf, float *modelMatrix, floa
unsigned temp[128 * 128];
int smax, tmax;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
R_BuildLightMap(surf, (void *)temp, smax * 4);
@ -1131,10 +1131,11 @@ void Vk_BuildPolygonFromSurface(msurface_t *fa, model_t *currentmodel)
lnumverts = fa->numedges;
VectorClear (total);
//
// draw texture
//
poly = Hunk_Alloc (sizeof(vkpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
poly = Hunk_Alloc (sizeof(vkpoly_t) + (lnumverts-4) * VERTEXSIZE * sizeof(float));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
@ -1172,17 +1173,17 @@ void Vk_BuildPolygonFromSurface(msurface_t *fa, model_t *currentmodel)
//
// lightmap texture coordinates
//
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s = DotProduct(vec, fa->lmvecs[0]) + fa->lmvecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s*16;
s += 8;
s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
s += fa->light_s * (1 << fa->lmshift);
s += (1 << fa->lmshift) * 0.5;
s /= BLOCK_WIDTH * (1 << fa->lmshift);
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t = DotProduct(vec, fa->lmvecs[1]) + fa->lmvecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t*16;
t += 8;
t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
t += fa->light_t * (1 << fa->lmshift);
t += (1 << fa->lmshift) * 0.5;
t /= BLOCK_HEIGHT * (1 << fa->lmshift);
poly->verts[i][5] = s;
poly->verts[i][6] = t;
@ -1205,8 +1206,8 @@ void Vk_CreateSurfaceLightmap (msurface_t *surf)
if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
return;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
{