mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-04-16 23:45:45 +00:00
Add full support for HDR/E5BGR9 lighting.
This commit is contained in:
parent
6dd16b99e7
commit
69e7395b0d
8 changed files with 192 additions and 72 deletions
105
Quake/gl_model.c
105
Quake/gl_model.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue