Skip to content

Commit 5a9b59a

Browse files
authored
Merge pull request #1007 from qw-ctf/e5bgr9
LIGHTMAPS: Support for loading e5bgr9 lightmaps.
2 parents 53f6735 + 9adb697 commit 5a9b59a

File tree

5 files changed

+122
-50
lines changed

5 files changed

+122
-50
lines changed

src/gl_model.h

+3
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ typedef enum
465465
#define EF_TRACER2 64 // orange split trail + rotate
466466
#define EF_TRACER3 128 // purple trail
467467

468+
#define MOD_HDRLIGHTING (1u<<13) //spike -- light samples are in e5bgr9 format. int aligned.
469+
468470
#define MAX_SIMPLE_TEXTURES 5
469471
#define MAX_TEXTURE_ARRAYS_PER_MODEL 64
470472

@@ -542,6 +544,7 @@ typedef struct model_s {
542544
byte* visdata;
543545
int visdata_length;
544546
byte* lightdata;
547+
size_t lightdatasamplesize;
545548

546549
int bspversion;
547550
qbool isworldmodel;

src/r_brushmodel_load.c

+32-16
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ static void SetSurfaceLighting(model_t* loadmodel, msurface_t* out, byte* styles
141141
out->samples = NULL;
142142
}
143143
else {
144-
out->samples = loadmodel->lightdata + (loadmodel->bspversion == HL_BSPVERSION ? i : i * 3);
144+
out->samples = loadmodel->lightdata + (loadmodel->bspversion == HL_BSPVERSION ? i : i * loadmodel->lightdatasamplesize);
145145
}
146146
}
147147

@@ -243,24 +243,38 @@ static void Mod_LoadLighting(model_t* loadmodel, lump_t* l, byte* mod_base, bspx
243243
if (load_inline) {
244244
int threshold = (lightmode == 1 ? 255 : lightmode == 2 ? 170 : 128);
245245
int lumpsize;
246-
byte *rgb = Mod_BSPX_FindLump(bspx_header, "RGBLIGHTING", &lumpsize, mod_base);
247-
// Sanity-check size if vanilla lit exists
248-
if (rgb && lumpsize % 3 == 0 && (lumpsize == l->filelen * 3 || l->filelen <= 0)) {
249-
loadmodel->lightdata = (byte *) Hunk_AllocName(lumpsize, loadmodel->name);
246+
byte *rgb;
247+
248+
rgb = Mod_BSPX_FindLump(bspx_header, "LIGHTING_E5BGR9", &lumpsize, mod_base);
249+
if (rgb && lumpsize % 4 == 0 && (lumpsize == l->filelen * 4 || l->filelen <= 0)) {
250+
loadmodel->lightdata = (byte *) Hunk_AllocName (lumpsize, loadmodel->name);
251+
loadmodel->lightdatasamplesize = 4;
250252
memcpy(loadmodel->lightdata, rgb, lumpsize);
251-
// we trust the inline RGB data to be bug free so we don't check it against the mono lightmap
252-
// what we do though is prevent color wash-out in brightly lit areas
253-
// (one day we may do it in R_BuildLightMap instead)
254-
out = loadmodel->lightdata;
255-
for (i = 0; i < lumpsize / 3; i++, out += 3) {
256-
int m = max(out[0], max(out[1], out[2]));
257-
if (m > threshold) {
258-
out[0] = out[0] * threshold / m;
259-
out[1] = out[1] * threshold / m;
260-
out[2] = out[2] * threshold / m;
253+
loadmodel->flags |= MOD_HDRLIGHTING;
254+
for (i = 0; i < lumpsize / 4; i++) { //native endian...
255+
((int*)loadmodel->lightdata)[i] = LittleLong(((int*)loadmodel->lightdata)[i]);
256+
}
257+
} else {
258+
rgb = Mod_BSPX_FindLump(bspx_header, "RGBLIGHTING", &lumpsize, mod_base);
259+
// Sanity-check size if vanilla lit exists
260+
if (rgb && lumpsize % 3 == 0 && (lumpsize == l->filelen * 3 || l->filelen <= 0)) {
261+
loadmodel->lightdata = (byte *) Hunk_AllocName(lumpsize, loadmodel->name);
262+
loadmodel->lightdatasamplesize = 3;
263+
memcpy(loadmodel->lightdata, rgb, lumpsize);
264+
// we trust the inline RGB data to be bug free so we don't check it against the mono lightmap
265+
// what we do though is prevent color wash-out in brightly lit areas
266+
// (one day we may do it in R_BuildLightMap instead)
267+
out = loadmodel->lightdata;
268+
for (i = 0; i < lumpsize / 3; i++, out += 3) {
269+
int m = max(out[0], max(out[1], out[2]));
270+
if (m > threshold) {
271+
out[0] = out[0] * threshold / m;
272+
out[1] = out[1] * threshold / m;
273+
out[2] = out[2] * threshold / m;
274+
}
261275
}
276+
// all done, but we let them override it with a .lit
262277
}
263-
// all done, but we let them override it with a .lit
264278
}
265279
}
266280

@@ -285,6 +299,7 @@ static void Mod_LoadLighting(model_t* loadmodel, lump_t* l, byte* mod_base, bspx
285299
Com_Printf("Static coloured lighting loaded\n");
286300
}
287301
loadmodel->lightdata = data + 8;
302+
loadmodel->lightdatasamplesize = 3;
288303

289304
in = mod_base + l->fileofs;
290305
out = loadmodel->lightdata;
@@ -345,6 +360,7 @@ static void Mod_LoadLighting(model_t* loadmodel, lump_t* l, byte* mod_base, bspx
345360

346361
//no .lit found, expand the white lighting data to color
347362
loadmodel->lightdata = (byte *) Hunk_AllocName (l->filelen * 3, va("%s_@lightdata", loadmodel->name));
363+
loadmodel->lightdatasamplesize = 3;
348364
in = mod_base + l->fileofs;
349365
out = loadmodel->lightdata;
350366
for (i = 0; i < l->filelen; i++, out += 3) {

src/r_lighting.h

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ void R_RenderDlights(void);
3434
void R_LightEntity(entity_t* ent);
3535

3636
extern unsigned int d_lightstylevalue[256]; // 8.8 fraction of base light value
37+
static const float rgb9e5tab[32] = {
38+
//multipliers for the 9-bit mantissa, according to the biased mantissa
39+
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
40+
1.0/(1<<24), 1.0/(1<<23), 1.0/(1<<22), 1.0/(1<<21), 1.0/(1<<20), 1.0/(1<<19), 1.0/(1<<18), 1.0/(1<<17),
41+
1.0/(1<<16), 1.0/(1<<15), 1.0/(1<<14), 1.0/(1<<13), 1.0/(1<<12), 1.0/(1<<11), 1.0/(1<<10), 1.0/(1<<9),
42+
1.0/(1<<8), 1.0/(1<<7), 1.0/(1<<6), 1.0/(1<<5), 1.0/(1<<4), 1.0/(1<<3), 1.0/(1<<2), 1.0/(1<<1),
43+
1.0, 1.0*(1<<1), 1.0*(1<<2), 1.0*(1<<3), 1.0*(1<<4), 1.0*(1<<5), 1.0*(1<<6), 1.0*(1<<7),
44+
};
3745

3846
extern cvar_t r_dynamic;
3947
#define R_NoLighting() (r_dynamic.integer == 0)

src/r_lightmaps.c

+57-24
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,9 @@ static void R_AddDynamicLights(msurface_t *surf)
210210
}
211211

212212
//Combine and scale multiple lightmaps into the 8.8 format in blocklights
213-
static void R_BuildLightMap(msurface_t *surf, byte *dest, int stride)
213+
static void R_BuildLightMap(msurface_t *surf, byte *dest, int stride, uint32_t flags)
214214
{
215215
int smax, tmax, i, j, size, blocksize, maps;
216-
byte *lightmap;
217216
unsigned scale, *bl;
218217
qbool fullbright = false;
219218

@@ -225,7 +224,6 @@ static void R_BuildLightMap(msurface_t *surf, byte *dest, int stride)
225224
tmax = (surf->extents[1] >> surf->lmshift) + 1;
226225
size = smax * tmax;
227226
blocksize = size * 3;
228-
lightmap = surf->samples;
229227

230228
// check for full bright or no light data
231229
fullbright = (R_FullBrightAllowed() || !cl.worldmodel || !cl.worldmodel->lightdata);
@@ -241,16 +239,37 @@ static void R_BuildLightMap(msurface_t *surf, byte *dest, int stride)
241239
}
242240

243241
// add all the lightmaps
244-
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
245-
scale = d_lightstylevalue[surf->styles[maps]];
246-
surf->cached_light[maps] = scale; // 8.8 fraction
247-
248-
if (!fullbright && lightmap) {
242+
if (flags & MOD_HDRLIGHTING) {
243+
uint32_t *lightmap = (uint32_t *)surf->samples;
244+
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
245+
scale = d_lightstylevalue[surf->styles[maps]];
246+
surf->cached_light[maps] = scale; // 8.8 fraction
247+
// it sucks that blocklights is an int array. we can still massively
248+
// overbright though, just not underbright quite as accurately
249+
// (still quite a bit more than rgb8 precision there).
249250
bl = blocklights;
250-
for (i = 0; i < blocksize; i++) {
251-
*bl++ += lightmap[i] * scale;
251+
for (i=0 ; i<size ; i++) {
252+
uint32_t e5bgr9 = *lightmap++;
253+
//we're converting to a scale that holds overbrights, so 1->128, its 2->255ish
254+
float e = rgb9e5tab[e5bgr9>>27] * (1<<7) * scale;
255+
*bl++ += e*((e5bgr9>> 0)&0x1ff); //red
256+
*bl++ += e*((e5bgr9>> 9)&0x1ff); //green
257+
*bl++ += e*((e5bgr9>>18)&0x1ff); //blue
258+
}
259+
}
260+
} else {
261+
byte *lightmap = surf->samples;
262+
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
263+
scale = d_lightstylevalue[surf->styles[maps]];
264+
surf->cached_light[maps] = scale; // 8.8 fraction
265+
266+
if (!fullbright && lightmap) {
267+
bl = blocklights;
268+
for (i = 0; i < blocksize; i++) {
269+
*bl++ += lightmap[i] * scale;
270+
}
271+
lightmap += blocksize; // skip to next lightmap
252272
}
253-
lightmap += blocksize; // skip to next lightmap
254273
}
255274
}
256275

@@ -392,7 +411,7 @@ void R_RenderDynamicLightmaps(msurface_t *fa, qbool world)
392411
theRect->h = fa->light_t - theRect->t + tmax;
393412
}
394413
base = lm->rawdata + (fa->light_t * LIGHTMAP_WIDTH + fa->light_s) * 4;
395-
R_BuildLightMap (fa, base, LIGHTMAP_WIDTH * 4);
414+
R_BuildLightMap (fa, base, LIGHTMAP_WIDTH * 4, world ? cl.worldmodel->flags : 0);
396415
}
397416

398417
void R_LightmapFrameInit(void)
@@ -749,7 +768,6 @@ static void R_BuildSurfaceDisplayList(model_t* currentmodel, msurface_t *fa)
749768
static void R_BuildLightmapData(msurface_t* surf, int surfnum)
750769
{
751770
lightmap_data_t* lm = &lightmaps[surf->lightmaptexturenum];
752-
byte* lightmap = surf->samples;
753771
unsigned int smax = (surf->extents[0] >> surf->lmshift) + 1;
754772
unsigned int tmax = (surf->extents[1] >> surf->lmshift) + 1;
755773
unsigned int lightmap_flags;
@@ -775,20 +793,35 @@ static void R_BuildLightmapData(msurface_t* surf, int surfnum)
775793
source[0] = source[1] = source[2] = 0;
776794
source[3] = lightmap_flags;
777795

778-
if (lightmap) {
779-
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
780-
size_t lightmap_index = (maps * smax * tmax + t * smax + s) * 3;
781-
782-
source[0] |= ((unsigned int)lightmap[lightmap_index + 0]) << (8 * maps);
783-
source[1] |= ((unsigned int)lightmap[lightmap_index + 1]) << (8 * maps);
784-
source[2] |= ((unsigned int)lightmap[lightmap_index + 2]) << (8 * maps);
796+
if (surf->samples) {
797+
if (surfnum != -1 && cl.worldmodel->flags & MOD_HDRLIGHTING) {
798+
uint32_t* lightmap = (uint32_t *)surf->samples;
799+
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
800+
size_t lightmap_index = (maps * smax * tmax + t * smax + s);
801+
uint32_t e5bgr9 = lightmap[lightmap_index];
802+
//we're converting to a scale that holds overbrights, so 1->128, its 2->255ish
803+
float e = rgb9e5tab[e5bgr9>>27] * (1<<7);
804+
// should not clamp here, but changing the light compute shader can be done later
805+
source[0] += (unsigned int)bound(0, e*((e5bgr9>> 0)&0x1ff), 0xff) << (8 * maps);
806+
source[1] += (unsigned int)bound(0, e*((e5bgr9>> 9)&0x1ff), 0xff) << (8 * maps);
807+
source[2] += (unsigned int)bound(0, e*((e5bgr9>>18)&0x1ff), 0xff) << (8 * maps);
808+
}
809+
} else {
810+
byte* lightmap = surf->samples;
811+
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
812+
size_t lightmap_index = (maps * smax * tmax + t * smax + s) * 3;
813+
814+
source[0] |= ((unsigned int)lightmap[lightmap_index + 0]) << (8 * maps);
815+
source[1] |= ((unsigned int)lightmap[lightmap_index + 1]) << (8 * maps);
816+
source[2] |= ((unsigned int)lightmap[lightmap_index + 2]) << (8 * maps);
817+
}
785818
}
786819
}
787820
}
788821
}
789822
}
790823

791-
static void R_LightmapCreateForSurface(msurface_t *surf, int surfnum)
824+
static void R_LightmapCreateForSurface(msurface_t *surf, int surfnum, uint32_t flags)
792825
{
793826
int smax, tmax;
794827
byte *base;
@@ -811,7 +844,7 @@ static void R_LightmapCreateForSurface(msurface_t *surf, int surfnum)
811844
base = lightmaps[surf->lightmaptexturenum].rawdata + (surf->light_t * LIGHTMAP_WIDTH + surf->light_s) * 4;
812845
numdlights = 0;
813846
R_BuildLightmapData(surf, surfnum);
814-
R_BuildLightMap(surf, base, LIGHTMAP_WIDTH * 4);
847+
R_BuildLightMap(surf, base, LIGHTMAP_WIDTH * 4, flags);
815848
}
816849

817850
static int R_LightmapSurfaceSortFunction(const void* lhs_, const void* rhs_)
@@ -917,7 +950,7 @@ void R_BuildLightmaps(void)
917950
qbool isTurb = (surfaces[i]->flags & SURF_DRAWTURB);
918951

919952
if (!isTurb) {
920-
R_LightmapCreateForSurface(surfaces[i], m->isworldmodel ? surfaces[i]->surfacenum : -1);
953+
R_LightmapCreateForSurface(surfaces[i], m->isworldmodel ? surfaces[i]->surfacenum : -1, m->flags);
921954
}
922955
R_BuildSurfaceDisplayList(m, surfaces[i]);
923956
}
@@ -939,7 +972,7 @@ void R_BuildLightmaps(void)
939972
}
940973

941974
if (!isTurb || !(m->surfaces[i].texinfo->flags & TEX_SPECIAL)) {
942-
R_LightmapCreateForSurface(m->surfaces + i, m->isworldmodel ? m->surfaces[i].surfacenum : -1);
975+
R_LightmapCreateForSurface(m->surfaces + i, m->isworldmodel ? m->surfaces[i].surfacenum : -1, m->flags);
943976
}
944977
R_BuildSurfaceDisplayList(m, m->surfaces + i);
945978
}

src/r_rlight.c

+22-10
Original file line numberDiff line numberDiff line change
@@ -321,20 +321,32 @@ static void R_LightFromSurface(msurface_t* surf, int ds, int dt, vec3_t color)
321321
{
322322
if (surf->samples) {
323323
// LordHavoc: enhanced to interpolate lighting
324-
byte *lightmap;
325324
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
326325
float scale;
327326
line3 = ((surf->extents[0] >> 4) + 1) * 3;
328327

329-
lightmap = surf->samples + ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3; // LordHavoc: *3 for color
330-
331-
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
332-
scale = (float)d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
333-
r00 += (float)lightmap[0] * scale; g00 += (float)lightmap[1] * scale; b00 += (float)lightmap[2] * scale;
334-
r01 += (float)lightmap[3] * scale; g01 += (float)lightmap[4] * scale; b01 += (float)lightmap[5] * scale;
335-
r10 += (float)lightmap[line3 + 0] * scale; g10 += (float)lightmap[line3 + 1] * scale; b10 += (float)lightmap[line3 + 2] * scale;
336-
r11 += (float)lightmap[line3 + 3] * scale; g11 += (float)lightmap[line3 + 4] * scale; b11 += (float)lightmap[line3 + 5] * scale;
337-
lightmap += ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3; // LordHavoc: *3 for colored lighting
328+
if (cl.worldmodel->flags & MOD_HDRLIGHTING) {
329+
uint32_t *lightmap = (uint32_t*)surf->samples + (dt * (surf->extents[0]+1) + ds);
330+
line3 = (surf->extents[0]+1);
331+
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
332+
float e;
333+
scale = (1<<7) * (float) d_lightstylevalue[surf->styles[maps]] * 1.0f / 256.0f;
334+
e = rgb9e5tab[lightmap[ 0]>>27] * scale;r00 += ((lightmap[ 0]>> 0)&0x1ff) * e;g00 += ((lightmap[ 0]>> 9)&0x1ff) * e;b00 += ((lightmap[ 0]>> 9)&0x1ff) * e;
335+
e = rgb9e5tab[lightmap[ 1]>>27] * scale;r01 += ((lightmap[ 1]>> 0)&0x1ff) * e;g01 += ((lightmap[ 1]>> 9)&0x1ff) * e;b01 += ((lightmap[ 1]>> 9)&0x1ff) * e;
336+
e = rgb9e5tab[lightmap[line3+0]>>27] * scale;r10 += ((lightmap[line3+0]>> 0)&0x1ff) * e;g10 += ((lightmap[line3+0]>> 9)&0x1ff) * e;b10 += ((lightmap[line3+0]>> 9)&0x1ff) * e;
337+
e = rgb9e5tab[lightmap[line3+1]>>27] * scale;r11 += ((lightmap[line3+1]>> 0)&0x1ff) * e;g11 += ((lightmap[line3+1]>> 9)&0x1ff) * e;b11 += ((lightmap[line3+1]>> 9)&0x1ff) * e;
338+
lightmap += (surf->extents[0]+1) * (surf->extents[1]+1);
339+
}
340+
} else {
341+
byte *lightmap = surf->samples + ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3; // LordHavoc: *3 for color
342+
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
343+
scale = (float)d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
344+
r00 += (float)lightmap[0] * scale; g00 += (float)lightmap[1] * scale; b00 += (float)lightmap[2] * scale;
345+
r01 += (float)lightmap[3] * scale; g01 += (float)lightmap[4] * scale; b01 += (float)lightmap[5] * scale;
346+
r10 += (float)lightmap[line3 + 0] * scale; g10 += (float)lightmap[line3 + 1] * scale; b10 += (float)lightmap[line3 + 2] * scale;
347+
r11 += (float)lightmap[line3 + 3] * scale; g11 += (float)lightmap[line3 + 4] * scale; b11 += (float)lightmap[line3 + 5] * scale;
348+
lightmap += ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3; // LordHavoc: *3 for colored lighting
349+
}
338350
}
339351

340352
color[0] += (float)((int)((((((((r11 - r10) * dsfrac) >> 4) + r10) - ((((r01 - r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01 - r00) * dsfrac) >> 4) + r00)));

0 commit comments

Comments
 (0)