Add full support for HDR/E5BGR9 lighting.

This commit is contained in:
Shpoike 2023-06-29 16:40:18 +01:00
parent 6dd16b99e7
commit 69e7395b0d
8 changed files with 192 additions and 72 deletions

View File

@ -1050,6 +1050,7 @@ static void Mod_LoadLighting (lump_t *l)
unsigned int path_id;
int bspxsize;
loadmodel->flags &= ~MOD_HDRLIGHTING; //just in case.
loadmodel->lightdata = NULL;
// LordHavoc: check for a .lit file
q_strlcpy(litfilename, loadmodel->name, sizeof(litfilename));
@ -1074,13 +1075,29 @@ static void Mod_LoadLighting (lump_t *l)
{
if (8+l->filelen*3 == com_filesize)
{
Con_DPrintf2("%s loaded\n", litfilename);
Con_DPrintf2("%s loaded (ldr)\n", litfilename);
loadmodel->lightdata = data + 8;
loadmodel->lightdatasamples = l->filelen;
return;
}
Hunk_FreeToLowMark(mark);
Con_Printf("Outdated .lit file (%s should be %u bytes, not %u)\n", litfilename, 8+l->filelen*3, (unsigned)com_filesize);
}
else if (i == 0x10001)
{
if (8+l->filelen*4 == com_filesize)
{
Con_DPrintf2("%s loaded (hdr)\n", litfilename);
loadmodel->lightdata = data + 8;
loadmodel->lightdatasamples = l->filelen;
loadmodel->flags |= MOD_HDRLIGHTING;
for (i = 0; i < loadmodel->lightdatasamples; i++)
((int*)loadmodel->lightdata)[i] = LittleLong(((int*)loadmodel->lightdata)[i]);
return;
}
Hunk_FreeToLowMark(mark);
Con_Printf("Outdated .lit file (%s should be %u bytes, not %u)\n", litfilename, 8+l->filelen*4, (unsigned)com_filesize);
}
else
{
Hunk_FreeToLowMark(mark);
@ -1094,16 +1111,15 @@ static void Mod_LoadLighting (lump_t *l)
}
}
// LordHavoc: no .lit found, expand the white lighting data to color
if (!l->filelen)
return;
// Quake64 bsp lighmap data
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
if (loadmodel->bspversion == BSPVERSION_QUAKE64 && l->filelen)
{
// RGB lightmap samples are packed in 16bits.
// RRRRR GGGGG BBBBBB
loadmodel->lightdata = (byte *) Hunk_AllocName ( (l->filelen / 2)*3, litfilename);
loadmodel->lightdatasamples = (l->filelen / 2);
in = mod_base + l->fileofs;
out = loadmodel->lightdata;
@ -1119,52 +1135,42 @@ static void Mod_LoadLighting (lump_t *l)
return;
}
in = Q1BSPX_FindLump("RGBLIGHTING", &bspxsize);
if (loadmodel->lightdata && bspxsize == l->filelen*3)
in = Q1BSPX_FindLump("LIGHTING_E5BGR9", &bspxsize);
if (in && (!l->filelen || (bspxsize && bspxsize == l->filelen*4)))
{
loadmodel->lightdata = out = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
memcpy(out, in, l->filelen*3);
Con_DPrintf("bspx lighting loaded\n");
loadmodel->lightdata = (byte *) Hunk_AllocName ( bspxsize, litfilename);
loadmodel->lightdatasamples = bspxsize/4;
memcpy(loadmodel->lightdata, in, bspxsize);
loadmodel->flags |= MOD_HDRLIGHTING;
Con_DPrintf("bspx hdr lighting loaded\n");
for (i = 0; i < loadmodel->lightdatasamples; i++) //native endian...
((int*)loadmodel->lightdata)[i] = LittleLong(((int*)loadmodel->lightdata)[i]);
return;
}
else
in = Q1BSPX_FindLump("RGBLIGHTING", &bspxsize);
if (in && (!l->filelen || (bspxsize && bspxsize == l->filelen*3)))
{
in = Q1BSPX_FindLump("LIGHTING_E5BGR9", &bspxsize);
if (in && bspxsize == l->filelen*4)
{ //we don't really support hdr lighting, but we downgrade it to ldr whenever there's no rgb data.
//FIXME: don't convert this stuff here. upload the data to the gpu with GL_EXT_shared_exponent (core in gl3)
loadmodel->lightdata = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
out = loadmodel->lightdata;
Con_DPrintf("bspx hdr->ldr lighting loaded\n");
for (i = 0;i < l->filelen;i++, in+=4)
{
static const float rgb9e5tab[32] = { //multipliers for the 9-bit mantissa, according to the biased mantissa
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
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),
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),
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),
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),
};
unsigned int e5bgr9 = *(unsigned int*)in;
float e = rgb9e5tab[e5bgr9>>27] * (1<<7); //we're converting to a scale that holds overbrights, so 1->128, its 2->255ish
*out++ = q_min(255, e*((e5bgr9>> 0)&0x1ff)); //red
*out++ = q_min(255, e*((e5bgr9>> 9)&0x1ff)); //green
*out++ = q_min(255, e*((e5bgr9>>18)&0x1ff)); //blue
}
}
else
loadmodel->lightdata = (byte *) Hunk_AllocName ( bspxsize, litfilename);
loadmodel->lightdatasamples = bspxsize/3;
memcpy(loadmodel->lightdata, in, bspxsize);
Con_DPrintf("bspx ldr lighting loaded\n");
return;
}
if (l->filelen)
{
loadmodel->lightdata = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
loadmodel->lightdatasamples = l->filelen;
in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
out = loadmodel->lightdata;
memcpy (in, mod_base + l->fileofs, l->filelen);
for (i = 0;i < l->filelen;i++)
{
loadmodel->lightdata = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
out = loadmodel->lightdata;
memcpy (in, mod_base + l->fileofs, l->filelen);
for (i = 0;i < l->filelen;i++)
{
d = *in++;
*out++ = d;
*out++ = d;
*out++ = d;
}
d = *in++;
*out++ = d;
*out++ = d;
*out++ = d;
}
return;
}
}
@ -1557,6 +1563,7 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2)
unsigned short *lmstyle16 = NULL;
int lumpsize;
char scalebuf[16];
int facestyles;
if (bsp2)
{
@ -1674,8 +1681,14 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2)
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
lofs /= 2; // Q64 samples are 16bits instead 8 in normal Quake
for (facestyles = 0 ; facestyles<MAXLIGHTMAPS && out->styles[facestyles] != INVALID_LIGHTSTYLE ; facestyles++)
; //count the styles so we can bound-check properly.
if (lofs == -1)
out->samples = NULL;
else if (lofs+facestyles*((out->extents[0]>>out->lmshift)+1)*((out->extents[1]>>out->lmshift)+1) > loadmodel->lightdatasamples)
out->samples = NULL; //corrupt...
else if (loadmodel->flags & MOD_HDRLIGHTING)
out->samples = loadmodel->lightdata + (lofs * 4); //spike -- hdr lighting data is 4-aligned
else
out->samples = loadmodel->lightdata + (lofs * 3); //johnfitz -- lit support via lordhavoc (was "+ i")
@ -3370,7 +3383,7 @@ void Mod_SetExtraFlags (qmodel_t *mod)
if (!mod)
return;
mod->flags &= (0xFF | MF_HOLEY); //only preserve first byte, plus MF_HOLEY
mod->flags &= (0xFF | MF_HOLEY | MOD_HDRLIGHTING); //only preserve first byte, plus MF_HOLEY
if (mod->type == mod_alias)
{

View File

@ -161,7 +161,7 @@ typedef struct msurface_s
unsigned short styles[MAXLIGHTMAPS];
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
qboolean cached_dlight; // true if dynamic light in cache
byte *samples; // [numstyles*surfsize]
void *samples; // [numstyles*surfsize]
} msurface_t;
typedef struct mnode_s
@ -446,6 +446,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias, mod_ext_invalid} modtype_t;
#define MOD_EMITREPLACE 2048 //particle effect completely replaces the model (for flames or whatever).
#define MOD_EMITFORWARDS 4096 //particle effect is emitted forwards, rather than downwards. why down? good question.
//spike
#define MOD_HDRLIGHTING (1u<<13) //spike -- light samples are in e5bgr9 format. int aligned.
typedef struct qmodel_s
{
@ -526,6 +527,7 @@ typedef struct qmodel_s
byte *visdata;
byte *lightdata;
size_t lightdatasamples;
char *entities;
qboolean viswarn; // for Mod_DecompressVis()

View File

@ -400,21 +400,43 @@ loc0:
if (dist < *maxdist)
{
// LordHavoc: enhanced to interpolate lighting
byte *lightmap;
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;
float scale;
line3 = ((surf->extents[0]>>surf->lmshift)+1)*3;
float scale, e;
lightmap = surf->samples + ((dt>>surf->lmshift) * ((surf->extents[0]>>surf->lmshift)+1) + (ds>>surf->lmshift))*3; // LordHavoc: *3 for color
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE;maps++)
if (cl.worldmodel->flags & MOD_HDRLIGHTING)
{
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale;
r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale;
r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1)*3; // LordHavoc: *3 for colored lighting
static const float rgb9e5tab[32] = { //multipliers for the 9-bit mantissa, according to the biased mantissa
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
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),
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),
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),
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),
};
uint32_t *lightmap = (uint32_t*)surf->samples + ((dt>>surf->lmshift) * ((surf->extents[0]>>surf->lmshift)+1) + (ds>>surf->lmshift));
line3 = ((surf->extents[0]>>surf->lmshift)+1);
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE;maps++)
{
scale = (1<<7) * (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
e = rgb9e5tab[lightmap[ 0]>>27] * scale;r00 += ((lightmap[ 0]>> 0)&0x1ff) * e;g00 += (float) ((lightmap[ 0]>> 9)&0x1ff) * e;b00 += (float) ((lightmap[ 0]>> 9)&0x1ff) * e;
e = rgb9e5tab[lightmap[ 1]>>27] * scale;r01 += ((lightmap[ 1]>> 0)&0x1ff) * e;g01 += (float) ((lightmap[ 1]>> 9)&0x1ff) * e;b01 += (float) ((lightmap[ 1]>> 9)&0x1ff) * e;
e = rgb9e5tab[lightmap[line3+0]>>27] * scale;r10 += ((lightmap[line3+0]>> 0)&0x1ff) * e;g10 += (float) ((lightmap[line3+0]>> 9)&0x1ff) * e;b10 += (float) ((lightmap[line3+0]>> 9)&0x1ff) * e;
e = rgb9e5tab[lightmap[line3+1]>>27] * scale;r11 += ((lightmap[line3+1]>> 0)&0x1ff) * e;g11 += (float) ((lightmap[line3+1]>> 9)&0x1ff) * e;b11 += (float) ((lightmap[line3+1]>> 9)&0x1ff) * e;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1);
}
}
else
{
byte *lightmap = surf->samples + ((dt>>surf->lmshift) * ((surf->extents[0]>>surf->lmshift)+1) + (ds>>surf->lmshift))*3; // LordHavoc: *3 for color
line3 = ((surf->extents[0]>>surf->lmshift)+1)*3;
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE;maps++)
{
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale;
r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale;
r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1)*3; // LordHavoc: *3 for colored lighting
}
}
color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));

View File

@ -76,7 +76,7 @@ static struct
{"RGBA4444", "4444", GL_RGBA4,GL_RGBA,GL_UNSIGNED_SHORT_4_4_4_4, 2, 1, 1, NULL},
{"RGBA5551", "5551", GL_RGB5_A1,GL_RGBA,GL_UNSIGNED_SHORT_5_5_5_1, 2, 1, 1, NULL},
{"L8", "LUM8", GL_LUMINANCE8,GL_LUMINANCE,GL_UNSIGNED_BYTE, 1, 1, 1, NULL},
{"E5BGR9", "EXP5", GL_RGB9_E5,GL_RGB,GL_UNSIGNED_INT_5_9_9_9_REV, 4, 1, 1, &gl_texture_rgtc/*gl3*/},
{"E5BGR9", "EXP5", GL_RGB9_E5,GL_RGB,GL_UNSIGNED_INT_5_9_9_9_REV, 4, 1, 1, &gl_texture_e5bgr9},
#if defined(GL_EXT_texture_compression_s3tc) || defined(GL_EXT_texture_compression_dxt1)
{"BC1_RGBA", "BC1", GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,0,0, 8, 4, 4, &gl_texture_s3tc},
#endif
@ -1469,7 +1469,10 @@ static void TexMgr_LoadLightmap (gltexture_t *glt, byte *data)
{
// upload it
GL_Bind (glt);
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, glt->width, glt->height, 0, gl_lightmap_format, GL_UNSIGNED_BYTE, data);
if (gl_lightmap_format == GL_RGB9_E5)
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB9_E5, glt->width, glt->height, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data);
else
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, glt->width, glt->height, 0, gl_lightmap_format, GL_UNSIGNED_BYTE, data);
// set filter modes
TexMgr_SetFilterModes (glt);

View File

@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TEXPREF_ALLOWMISSING 0x2000 // TexMgr_LoadImage should return NULL if anything goes wrong (for use with SRC_EXTERNAL).
enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA, SRC_EXTERNAL, SRC_FIRSTCOMPRESSED};
extern qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc;
extern qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc, gl_texture_e5bgr9;
typedef uintptr_t src_offset_t;

View File

@ -67,7 +67,7 @@ static int gl_version_major;
static int gl_version_minor;
static const char *gl_extensions;
qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc;
qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc, gl_texture_e5bgr9;
static vmode_t modelist[MAX_MODE_LIST];
static int nummodes;
@ -1168,6 +1168,7 @@ static void GL_CheckExtensions (void)
gl_texture_bptc = GL_CompressedTexImage2D && (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 2) || GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_compression_bptc"));
gl_texture_etc2 = GL_CompressedTexImage2D && (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 3) || GL_ParseExtensionList(gl_extensions, "GL_ARB_ES3_compatibility"));
gl_texture_astc = GL_CompressedTexImage2D && ( GL_ParseExtensionList(gl_extensions, "GL_ARB_ES3_2_compatibility") || GL_ParseExtensionList(gl_extensions, "GL_KHR_texture_compression_astc_ldr"));
gl_texture_e5bgr9 = gl_version_major >= 3;
// GLSL
//

View File

@ -955,10 +955,16 @@ void GL_BuildLightmaps (void)
last_lightmap_allocated = 0;
lightmap_count = 0;
gl_lightmap_format = GL_RGBA;//FIXME: hardcoded for now!
if (gl_texture_e5bgr9)// && cl.worldmodel && (cl.worldmodel->flags&MOD_HDRLIGHTING))
gl_lightmap_format = GL_RGB9_E5; //requires gl3, allowing for hdr lighting.
else
gl_lightmap_format = GL_RGBA;//FIXME: hardcoded for now!
switch (gl_lightmap_format)
{
case GL_RGB9_E5:
lightmap_bytes = 4;
break;
case GL_RGBA:
lightmap_bytes = 4;
break;
@ -1224,7 +1230,6 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
int smax, tmax;
int r,g,b;
int i, j, size;
byte *lightmap;
unsigned scale;
int maps;
unsigned *bl;
@ -1234,7 +1239,6 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
smax = (surf->extents[0]>>surf->lmshift)+1;
tmax = (surf->extents[1]>>surf->lmshift)+1;
size = smax*tmax;
lightmap = surf->samples;
if (model->lightdata)
{
@ -1242,8 +1246,37 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
memset (&blocklights[0], 0, size * 3 * sizeof (unsigned int)); //johnfitz -- lit support via lordhavoc
// add all the lightmaps
if (lightmap)
if (!surf->samples)
; //unlit surfaces are black... FIXME: unless lit water (could be new-qbsp + old-light)...
else if (model->flags & MOD_HDRLIGHTING)
{
uint32_t *lightmap = surf->samples;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction
bl = blocklights; //it sucks that blocklights is an int array. we can still massively overbright though, just not underbright quite as accurately (still quite a bit more than rgb8 precision there).
for (i=0 ; i<size ; i++)
{
static const float rgb9e5tab[32] = { //multipliers for the 9-bit mantissa, according to the biased mantissa
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
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),
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),
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),
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),
};
uint32_t e5bgr9 = *lightmap++;
float e = rgb9e5tab[e5bgr9>>27] * (1<<7) * scale; //we're converting to a scale that holds overbrights, so 1->128, its 2->255ish
*bl++ += e*((e5bgr9>> 0)&0x1ff); //red
*bl++ += e*((e5bgr9>> 9)&0x1ff); //green
*bl++ += e*((e5bgr9>>18)&0x1ff); //blue
}
}
}
else
{
byte *lightmap = surf->samples;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ;
maps++)
{
@ -1275,6 +1308,41 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
// store:
switch (gl_lightmap_format)
{
case GL_RGB9_E5:
{
int e;
float m;
float scale, identity = 1u<<((gl_overbright.value?8:7)+8); //overbright is redundant with this, but its easier to leave it than conditionally block it.
stride -= smax * 4;
bl = blocklights;
for (i=0 ; i<tmax ; i++, dest += stride)
{
for (j=0 ; j<smax ; j++)
{
e = 0;
m = q_max(q_max(bl[0], bl[1]), bl[2])/identity;
if (m >= 0.5)
{ //positive exponent
while (m >= (1<<(e)) && e < 30-15) //don't do nans.
e++;
}
else
{ //negative exponent...
while (m < 1/(1<<-e) && e > -15) //don't do denormals.
e--;
}
scale = pow(2, e-9);
scale *= identity;
*(unsigned int *)dest = ((e+15)<<27) |
CLAMP(0, (int)(bl[0]/scale + 0.5), 0x1ff)<<0 |
CLAMP(0, (int)(bl[1]/scale + 0.5), 0x1ff)<<9 |
CLAMP(0, (int)(bl[2]/scale + 0.5), 0x1ff)<<18;
bl += 3;
dest += 4;
}
}
}
break;
case GL_RGBA:
stride -= smax * 4;
bl = blocklights;
@ -1348,8 +1416,12 @@ static void R_UploadLightmap(int lmap)
lm->modified = false;
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, gl_lightmap_format,
GL_UNSIGNED_BYTE, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, gl_lightmap_format,
GL_UNSIGNED_BYTE, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
lm->rectchange.l = LMBLOCK_WIDTH;
lm->rectchange.t = LMBLOCK_HEIGHT;
lm->rectchange.h = 0;
@ -1439,8 +1511,12 @@ void R_RebuildAllLightmaps (void)
else
{
GL_Bind (lightmaps[i].texture);
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format,
GL_UNSIGNED_BYTE, lightmaps[i].data);
if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lightmaps[i].data);
else
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format,
GL_UNSIGNED_BYTE, lightmaps[i].data);
}
lightmaps[i].modified = false;

View File

@ -193,7 +193,10 @@ QuakeSpasm-Spiked
o Special fields that can be used on any entity without QC changes:
"emiteffect" field - to specify a constantly emitting effect.
"traileffect" field - for particles any time the entity moves.
"traileffect" field - for particles any time the entity moves.
o Optional HDR lighting (via LIGHTING_E5BGR9 bspx lump), allowing for much
greater overbrights without stacking styles (to compensate for overly dark textures).
--------
4. Todo