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,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
|
||||
|
|
|
@ -78,6 +78,10 @@ typedef struct msurface_s
|
|||
|
||||
mtexinfo_t *texinfo;
|
||||
|
||||
/* decoupled lm */
|
||||
float lmvecs[2][4];
|
||||
float lmvlen[2];
|
||||
|
||||
/* lighting info */
|
||||
int dlightframe;
|
||||
int dlightbits;
|
||||
|
|
|
@ -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] >> surf->lmshift) + 1;
|
||||
tmax = (surf->extents[1] >> surf->lmshift) + 1;
|
||||
tex = surf->texinfo;
|
||||
|
||||
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
|
||||
{
|
||||
|
@ -404,16 +402,18 @@ 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 += (1 << surf->lmshift))
|
||||
{
|
||||
td = local[1] - ftacc;
|
||||
if ( td < 0 )
|
||||
if (td < 0)
|
||||
td = -td;
|
||||
|
||||
td *= surf->lmvlen[1];
|
||||
|
||||
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += (1 << surf->lmshift), plightdest += 3)
|
||||
{
|
||||
sd = Q_ftol( local[0] - fsacc );
|
||||
|
@ -421,6 +421,8 @@ R_AddDynamicLights(msurface_t *surf)
|
|||
if ( sd < 0 )
|
||||
sd = -sd;
|
||||
|
||||
sd *= surf->lmvlen[0];
|
||||
|
||||
if (sd > td)
|
||||
fdist = sd + (td>>1);
|
||||
else
|
||||
|
|
|
@ -375,17 +375,151 @@ 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, 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
|
||||
=================
|
||||
*/
|
||||
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 +535,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++)
|
||||
|
@ -443,26 +584,20 @@ Mod_LoadFaces (model_t *loadmodel, const byte *mod_base, const lump_t *l)
|
|||
}
|
||||
|
||||
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 */
|
||||
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)
|
||||
|
@ -636,9 +771,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;
|
||||
|
||||
|
@ -678,6 +814,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);
|
||||
|
@ -686,14 +826,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,
|
||||
|
|
|
@ -1172,13 +1172,13 @@ 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 * (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 * (1 << fa->lmshift);
|
||||
t += (1 << fa->lmshift) * 0.5;
|
||||
|
|
Loading…
Reference in a new issue