mirror of
https://github.com/yquake2/ref_vk.git
synced 2025-02-28 06:12:36 +00:00
LIGHTMAPS: Add support for DECOUPLEDLM.
Decouples texture coordinates from lightmap coordinates to allow for higher resolution lightmaps, and also avoids lightmap misalignment when shadows span surfaces with differing texture scale.
This commit is contained in:
parent
366c0efc0f
commit
8a0797e484
5 changed files with 201 additions and 36 deletions
|
@ -333,6 +333,7 @@ typedef struct m32tex_s
|
||||||
/* .BSP file format */
|
/* .BSP file format */
|
||||||
|
|
||||||
#define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I') /* little-endian "IBSP" */
|
#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
|
#define BSPVERSION 38
|
||||||
|
|
||||||
/* upper design bounds: leaffaces, leafbrushes, planes, and
|
/* upper design bounds: leaffaces, leafbrushes, planes, and
|
||||||
|
@ -399,6 +400,17 @@ typedef struct
|
||||||
lump_t lumps[HEADER_LUMPS];
|
lump_t lumps[HEADER_LUMPS];
|
||||||
} dheader_t;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
float mins[3], maxs[3];
|
float mins[3], maxs[3];
|
||||||
|
@ -521,6 +533,13 @@ typedef struct
|
||||||
int lightofs; /* start of [numstyles*surfsize] samples */
|
int lightofs; /* start of [numstyles*surfsize] samples */
|
||||||
} dface_t;
|
} dface_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short lmwidth;
|
||||||
|
unsigned short lmheight;
|
||||||
|
int lightofs;
|
||||||
|
float vecs[2][4];
|
||||||
|
} dlminfo_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int contents; /* OR of all brushes (not needed?) */
|
int contents; /* OR of all brushes (not needed?) */
|
||||||
|
|
|
@ -78,6 +78,10 @@ typedef struct msurface_s
|
||||||
|
|
||||||
mtexinfo_t *texinfo;
|
mtexinfo_t *texinfo;
|
||||||
|
|
||||||
|
/* decoupled lm */
|
||||||
|
float lmvecs[2][4];
|
||||||
|
float lmvlen[2];
|
||||||
|
|
||||||
/* lighting info */
|
/* lighting info */
|
||||||
int dlightframe;
|
int dlightframe;
|
||||||
int dlightbits;
|
int dlightbits;
|
||||||
|
|
|
@ -367,14 +367,12 @@ R_AddDynamicLights(msurface_t *surf)
|
||||||
int s, t;
|
int s, t;
|
||||||
int i;
|
int i;
|
||||||
int smax, tmax;
|
int smax, tmax;
|
||||||
mtexinfo_t *tex;
|
|
||||||
dlight_t *dl;
|
dlight_t *dl;
|
||||||
float *plightdest;
|
float *plightdest;
|
||||||
float fsacc, ftacc;
|
float fsacc, ftacc;
|
||||||
|
|
||||||
smax = (surf->extents[0] >> surf->lmshift) + 1;
|
smax = (surf->extents[0] >> surf->lmshift) + 1;
|
||||||
tmax = (surf->extents[1] >> surf->lmshift) + 1;
|
tmax = (surf->extents[1] >> surf->lmshift) + 1;
|
||||||
tex = surf->texinfo;
|
|
||||||
|
|
||||||
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
|
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
|
||||||
{
|
{
|
||||||
|
@ -404,16 +402,18 @@ R_AddDynamicLights(msurface_t *surf)
|
||||||
surf->plane->normal[i]*fdist;
|
surf->plane->normal[i]*fdist;
|
||||||
}
|
}
|
||||||
|
|
||||||
local[0] = DotProduct(impact, tex->vecs[0]) + tex->vecs[0][3] - surf->texturemins[0];
|
local[0] = DotProduct (impact, surf->lmvecs[0]) + surf->lmvecs[0][3] - surf->texturemins[0];
|
||||||
local[1] = DotProduct(impact, tex->vecs[1]) + tex->vecs[1][3] - surf->texturemins[1];
|
local[1] = DotProduct (impact, surf->lmvecs[1]) + surf->lmvecs[1][3] - surf->texturemins[1];
|
||||||
|
|
||||||
plightdest = s_blocklights;
|
plightdest = s_blocklights;
|
||||||
for (t = 0, ftacc = 0; t < tmax; t++, ftacc += (1 << surf->lmshift))
|
for (t = 0, ftacc = 0; t < tmax; t++, ftacc += (1 << surf->lmshift))
|
||||||
{
|
{
|
||||||
td = local[1] - ftacc;
|
td = local[1] - ftacc;
|
||||||
if ( td < 0 )
|
if (td < 0)
|
||||||
td = -td;
|
td = -td;
|
||||||
|
|
||||||
|
td *= surf->lmvlen[1];
|
||||||
|
|
||||||
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += (1 << surf->lmshift), plightdest += 3)
|
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += (1 << surf->lmshift), plightdest += 3)
|
||||||
{
|
{
|
||||||
sd = Q_ftol( local[0] - fsacc );
|
sd = Q_ftol( local[0] - fsacc );
|
||||||
|
@ -421,6 +421,8 @@ R_AddDynamicLights(msurface_t *surf)
|
||||||
if ( sd < 0 )
|
if ( sd < 0 )
|
||||||
sd = -sd;
|
sd = -sd;
|
||||||
|
|
||||||
|
sd *= surf->lmvlen[0];
|
||||||
|
|
||||||
if (sd > td)
|
if (sd > td)
|
||||||
fdist = sd + (td>>1);
|
fdist = sd + (td>>1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -375,17 +375,151 @@ calcTexinfoAndFacesSize(const lump_t *fl, const byte *mod_base, const lump_t *tl
|
||||||
return ret;
|
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, header->lumps[i].fileofs + header->lumps[i].filelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xofs + sizeof(bspx_header_t) > filesize) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xheader = (bspx_header_t*)(mod_base + xofs);
|
||||||
|
if (LittleLong(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
|
Mod_LoadFaces
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static void
|
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;
|
msurface_t *out;
|
||||||
int i, count, surfnum;
|
dface_t *in;
|
||||||
|
|
||||||
in = (void *)(mod_base + l->fileofs);
|
in = (void *)(mod_base + l->fileofs);
|
||||||
|
|
||||||
|
@ -401,6 +535,13 @@ Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
|
||||||
loadmodel->surfaces = out;
|
loadmodel->surfaces = out;
|
||||||
loadmodel->numsurfaces = count;
|
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);
|
Vk_BeginBuildingLightmaps(loadmodel);
|
||||||
|
|
||||||
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
|
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
|
||||||
|
@ -443,26 +584,20 @@ Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
|
||||||
}
|
}
|
||||||
|
|
||||||
out->texinfo = loadmodel->texinfo + ti;
|
out->texinfo = loadmodel->texinfo + ti;
|
||||||
out->lmshift = DEFAULT_LMSHIFT;
|
|
||||||
|
|
||||||
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 */
|
CalcSurfaceExtents(loadmodel, out);
|
||||||
for (i = 0; i < MAXLIGHTMAPS; i++)
|
|
||||||
{
|
lightofs = in->lightofs;
|
||||||
out->styles[i] = in->styles[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i = LittleLong(in->lightofs);
|
SetSurfaceLighting(loadmodel, out, in->styles, lightofs);
|
||||||
|
|
||||||
if (i == -1)
|
|
||||||
{
|
|
||||||
out->samples = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out->samples = loadmodel->lightdata + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the drawing flags */
|
/* set the drawing flags */
|
||||||
if (out->texinfo->flags & SURF_WARP)
|
if (out->texinfo->flags & SURF_WARP)
|
||||||
|
@ -636,9 +771,10 @@ Mod_LoadBrushModel
|
||||||
static void
|
static void
|
||||||
Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
|
Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
|
||||||
{
|
{
|
||||||
int i;
|
bspx_header_t* bspx_header;
|
||||||
dheader_t *header;
|
|
||||||
byte *mod_base;
|
byte *mod_base;
|
||||||
|
dheader_t *header;
|
||||||
|
int i;
|
||||||
|
|
||||||
header = (dheader_t *)buffer;
|
header = (dheader_t *)buffer;
|
||||||
|
|
||||||
|
@ -678,6 +814,10 @@ Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
|
||||||
mod->extradata = Hunk_Begin(hunkSize);
|
mod->extradata = Hunk_Begin(hunkSize);
|
||||||
mod->type = mod_brush;
|
mod->type = mod_brush;
|
||||||
|
|
||||||
|
|
||||||
|
/* check for BSPX extensions */
|
||||||
|
bspx_header = Mod_LoadBSPX(modfilelen, (byte*)header);
|
||||||
|
|
||||||
/* load into heap */
|
/* load into heap */
|
||||||
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
|
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
|
||||||
&header->lumps[LUMP_VERTEXES], 0);
|
&header->lumps[LUMP_VERTEXES], 0);
|
||||||
|
@ -686,14 +826,14 @@ Mod_LoadBrushModel (model_t *mod, const void *buffer, int modfilelen)
|
||||||
Mod_LoadSurfedges(mod->name, &mod->surfedges, &mod->numsurfedges,
|
Mod_LoadSurfedges(mod->name, &mod->surfedges, &mod->numsurfedges,
|
||||||
mod_base, &header->lumps[LUMP_SURFEDGES], 0);
|
mod_base, &header->lumps[LUMP_SURFEDGES], 0);
|
||||||
Mod_LoadLighting(&mod->lightdata, mod_base, &header->lumps[LUMP_LIGHTING]);
|
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_base, &header->lumps[LUMP_PLANES], 0);
|
||||||
Mod_LoadTexinfo(mod->name, &mod->texinfo, &mod->numtexinfo,
|
Mod_LoadTexinfo(mod->name, &mod->texinfo, &mod->numtexinfo,
|
||||||
mod_base, &header->lumps[LUMP_TEXINFO], (findimage_t)Vk_FindImage,
|
mod_base, &header->lumps[LUMP_TEXINFO], (findimage_t)Vk_FindImage,
|
||||||
r_notexture, 0);
|
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_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_LoadLeafs(mod, mod_base, &header->lumps[LUMP_LEAFS]);
|
||||||
Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs,
|
Mod_LoadNodes(mod->name, mod->planes, mod->numplanes, mod->leafs,
|
||||||
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base,
|
mod->numleafs, &mod->nodes, &mod->numnodes, mod_base,
|
||||||
|
|
|
@ -1172,13 +1172,13 @@ void Vk_BuildPolygonFromSurface(msurface_t *fa, model_t *currentmodel)
|
||||||
//
|
//
|
||||||
// lightmap texture coordinates
|
// 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->texturemins[0];
|
||||||
s += fa->light_s * (1 << fa->lmshift);
|
s += fa->light_s * (1 << fa->lmshift);
|
||||||
s += (1 << fa->lmshift) * 0.5;
|
s += (1 << fa->lmshift) * 0.5;
|
||||||
s /= BLOCK_WIDTH * (1 << fa->lmshift);
|
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->texturemins[1];
|
||||||
t += fa->light_t * (1 << fa->lmshift);
|
t += fa->light_t * (1 << fa->lmshift);
|
||||||
t += (1 << fa->lmshift) * 0.5;
|
t += (1 << fa->lmshift) * 0.5;
|
||||||
|
|
Loading…
Reference in a new issue