mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +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
|
@ -1050,6 +1050,7 @@ static void Mod_LoadLighting (lump_t *l)
|
||||||
unsigned int path_id;
|
unsigned int path_id;
|
||||||
int bspxsize;
|
int bspxsize;
|
||||||
|
|
||||||
|
loadmodel->flags &= ~MOD_HDRLIGHTING; //just in case.
|
||||||
loadmodel->lightdata = NULL;
|
loadmodel->lightdata = NULL;
|
||||||
// LordHavoc: check for a .lit file
|
// LordHavoc: check for a .lit file
|
||||||
q_strlcpy(litfilename, loadmodel->name, sizeof(litfilename));
|
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)
|
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->lightdata = data + 8;
|
||||||
|
loadmodel->lightdatasamples = l->filelen;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Hunk_FreeToLowMark(mark);
|
Hunk_FreeToLowMark(mark);
|
||||||
Con_Printf("Outdated .lit file (%s should be %u bytes, not %u)\n", litfilename, 8+l->filelen*3, (unsigned)com_filesize);
|
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
|
else
|
||||||
{
|
{
|
||||||
Hunk_FreeToLowMark(mark);
|
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
|
// LordHavoc: no .lit found, expand the white lighting data to color
|
||||||
if (!l->filelen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Quake64 bsp lighmap data
|
// Quake64 bsp lighmap data
|
||||||
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
|
if (loadmodel->bspversion == BSPVERSION_QUAKE64 && l->filelen)
|
||||||
{
|
{
|
||||||
// RGB lightmap samples are packed in 16bits.
|
// RGB lightmap samples are packed in 16bits.
|
||||||
// RRRRR GGGGG BBBBBB
|
// RRRRR GGGGG BBBBBB
|
||||||
|
|
||||||
loadmodel->lightdata = (byte *) Hunk_AllocName ( (l->filelen / 2)*3, litfilename);
|
loadmodel->lightdata = (byte *) Hunk_AllocName ( (l->filelen / 2)*3, litfilename);
|
||||||
|
loadmodel->lightdatasamples = (l->filelen / 2);
|
||||||
in = mod_base + l->fileofs;
|
in = mod_base + l->fileofs;
|
||||||
out = loadmodel->lightdata;
|
out = loadmodel->lightdata;
|
||||||
|
|
||||||
|
@ -1119,41 +1135,31 @@ static void Mod_LoadLighting (lump_t *l)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
in = Q1BSPX_FindLump("RGBLIGHTING", &bspxsize);
|
|
||||||
if (loadmodel->lightdata && bspxsize == l->filelen*3)
|
|
||||||
{
|
|
||||||
loadmodel->lightdata = out = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
|
|
||||||
memcpy(out, in, l->filelen*3);
|
|
||||||
Con_DPrintf("bspx lighting loaded\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
in = Q1BSPX_FindLump("LIGHTING_E5BGR9", &bspxsize);
|
in = Q1BSPX_FindLump("LIGHTING_E5BGR9", &bspxsize);
|
||||||
if (in && bspxsize == l->filelen*4)
|
if (in && (!l->filelen || (bspxsize && 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
|
loadmodel->lightdata = (byte *) Hunk_AllocName ( bspxsize, litfilename);
|
||||||
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
|
loadmodel->lightdatasamples = bspxsize/4;
|
||||||
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),
|
memcpy(loadmodel->lightdata, in, bspxsize);
|
||||||
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),
|
loadmodel->flags |= MOD_HDRLIGHTING;
|
||||||
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),
|
Con_DPrintf("bspx hdr lighting loaded\n");
|
||||||
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),
|
for (i = 0; i < loadmodel->lightdatasamples; i++) //native endian...
|
||||||
};
|
((int*)loadmodel->lightdata)[i] = LittleLong(((int*)loadmodel->lightdata)[i]);
|
||||||
unsigned int e5bgr9 = *(unsigned int*)in;
|
return;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
in = Q1BSPX_FindLump("RGBLIGHTING", &bspxsize);
|
||||||
|
if (in && (!l->filelen || (bspxsize && bspxsize == l->filelen*3)))
|
||||||
|
{
|
||||||
|
loadmodel->lightdata = (byte *) Hunk_AllocName ( bspxsize, litfilename);
|
||||||
|
loadmodel->lightdatasamples = bspxsize/3;
|
||||||
|
memcpy(loadmodel->lightdata, in, bspxsize);
|
||||||
|
Con_DPrintf("bspx ldr lighting loaded\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
if (l->filelen)
|
||||||
{
|
{
|
||||||
loadmodel->lightdata = (byte *) Hunk_AllocName ( l->filelen*3, litfilename);
|
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
|
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;
|
out = loadmodel->lightdata;
|
||||||
memcpy (in, mod_base + l->fileofs, l->filelen);
|
memcpy (in, mod_base + l->fileofs, l->filelen);
|
||||||
|
@ -1164,7 +1170,7 @@ static void Mod_LoadLighting (lump_t *l)
|
||||||
*out++ = d;
|
*out++ = d;
|
||||||
*out++ = d;
|
*out++ = d;
|
||||||
}
|
}
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1557,6 +1563,7 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2)
|
||||||
unsigned short *lmstyle16 = NULL;
|
unsigned short *lmstyle16 = NULL;
|
||||||
int lumpsize;
|
int lumpsize;
|
||||||
char scalebuf[16];
|
char scalebuf[16];
|
||||||
|
int facestyles;
|
||||||
|
|
||||||
if (bsp2)
|
if (bsp2)
|
||||||
{
|
{
|
||||||
|
@ -1674,8 +1681,14 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2)
|
||||||
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
|
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
|
||||||
lofs /= 2; // Q64 samples are 16bits instead 8 in normal Quake
|
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)
|
if (lofs == -1)
|
||||||
out->samples = NULL;
|
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
|
else
|
||||||
out->samples = loadmodel->lightdata + (lofs * 3); //johnfitz -- lit support via lordhavoc (was "+ i")
|
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)
|
if (!mod)
|
||||||
return;
|
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)
|
if (mod->type == mod_alias)
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,7 +161,7 @@ typedef struct msurface_s
|
||||||
unsigned short styles[MAXLIGHTMAPS];
|
unsigned short styles[MAXLIGHTMAPS];
|
||||||
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
|
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
|
||||||
qboolean cached_dlight; // true if dynamic light in cache
|
qboolean cached_dlight; // true if dynamic light in cache
|
||||||
byte *samples; // [numstyles*surfsize]
|
void *samples; // [numstyles*surfsize]
|
||||||
} msurface_t;
|
} msurface_t;
|
||||||
|
|
||||||
typedef struct mnode_s
|
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_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.
|
#define MOD_EMITFORWARDS 4096 //particle effect is emitted forwards, rather than downwards. why down? good question.
|
||||||
//spike
|
//spike
|
||||||
|
#define MOD_HDRLIGHTING (1u<<13) //spike -- light samples are in e5bgr9 format. int aligned.
|
||||||
|
|
||||||
typedef struct qmodel_s
|
typedef struct qmodel_s
|
||||||
{
|
{
|
||||||
|
@ -526,6 +527,7 @@ typedef struct qmodel_s
|
||||||
|
|
||||||
byte *visdata;
|
byte *visdata;
|
||||||
byte *lightdata;
|
byte *lightdata;
|
||||||
|
size_t lightdatasamples;
|
||||||
char *entities;
|
char *entities;
|
||||||
|
|
||||||
qboolean viswarn; // for Mod_DecompressVis()
|
qboolean viswarn; // for Mod_DecompressVis()
|
||||||
|
|
|
@ -400,13 +400,34 @@ loc0:
|
||||||
if (dist < *maxdist)
|
if (dist < *maxdist)
|
||||||
{
|
{
|
||||||
// LordHavoc: enhanced to interpolate lighting
|
// 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;
|
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;
|
float scale, e;
|
||||||
|
|
||||||
|
if (cl.worldmodel->flags & MOD_HDRLIGHTING)
|
||||||
|
{
|
||||||
|
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;
|
line3 = ((surf->extents[0]>>surf->lmshift)+1)*3;
|
||||||
|
|
||||||
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++)
|
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE;maps++)
|
||||||
{
|
{
|
||||||
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
|
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
|
||||||
|
@ -416,6 +437,7 @@ loc0:
|
||||||
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * 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
|
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)));
|
color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));
|
||||||
color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
|
color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
|
||||||
|
|
|
@ -76,7 +76,7 @@ static struct
|
||||||
{"RGBA4444", "4444", GL_RGBA4,GL_RGBA,GL_UNSIGNED_SHORT_4_4_4_4, 2, 1, 1, NULL},
|
{"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},
|
{"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},
|
{"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)
|
#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},
|
{"BC1_RGBA", "BC1", GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,0,0, 8, 4, 4, &gl_texture_s3tc},
|
||||||
#endif
|
#endif
|
||||||
|
@ -1469,6 +1469,9 @@ static void TexMgr_LoadLightmap (gltexture_t *glt, byte *data)
|
||||||
{
|
{
|
||||||
// upload it
|
// upload it
|
||||||
GL_Bind (glt);
|
GL_Bind (glt);
|
||||||
|
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);
|
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, glt->width, glt->height, 0, gl_lightmap_format, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
// set filter modes
|
// set filter modes
|
||||||
|
|
|
@ -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).
|
#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};
|
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;
|
typedef uintptr_t src_offset_t;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ static int gl_version_major;
|
||||||
static int gl_version_minor;
|
static int gl_version_minor;
|
||||||
static const char *gl_extensions;
|
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 vmode_t modelist[MAX_MODE_LIST];
|
||||||
static int nummodes;
|
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_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_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_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
|
// GLSL
|
||||||
//
|
//
|
||||||
|
|
|
@ -955,10 +955,16 @@ void GL_BuildLightmaps (void)
|
||||||
last_lightmap_allocated = 0;
|
last_lightmap_allocated = 0;
|
||||||
lightmap_count = 0;
|
lightmap_count = 0;
|
||||||
|
|
||||||
|
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!
|
gl_lightmap_format = GL_RGBA;//FIXME: hardcoded for now!
|
||||||
|
|
||||||
switch (gl_lightmap_format)
|
switch (gl_lightmap_format)
|
||||||
{
|
{
|
||||||
|
case GL_RGB9_E5:
|
||||||
|
lightmap_bytes = 4;
|
||||||
|
break;
|
||||||
case GL_RGBA:
|
case GL_RGBA:
|
||||||
lightmap_bytes = 4;
|
lightmap_bytes = 4;
|
||||||
break;
|
break;
|
||||||
|
@ -1224,7 +1230,6 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
|
||||||
int smax, tmax;
|
int smax, tmax;
|
||||||
int r,g,b;
|
int r,g,b;
|
||||||
int i, j, size;
|
int i, j, size;
|
||||||
byte *lightmap;
|
|
||||||
unsigned scale;
|
unsigned scale;
|
||||||
int maps;
|
int maps;
|
||||||
unsigned *bl;
|
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;
|
smax = (surf->extents[0]>>surf->lmshift)+1;
|
||||||
tmax = (surf->extents[1]>>surf->lmshift)+1;
|
tmax = (surf->extents[1]>>surf->lmshift)+1;
|
||||||
size = smax*tmax;
|
size = smax*tmax;
|
||||||
lightmap = surf->samples;
|
|
||||||
|
|
||||||
if (model->lightdata)
|
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
|
memset (&blocklights[0], 0, size * 3 * sizeof (unsigned int)); //johnfitz -- lit support via lordhavoc
|
||||||
|
|
||||||
// add all the lightmaps
|
// 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 ;
|
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ;
|
||||||
maps++)
|
maps++)
|
||||||
{
|
{
|
||||||
|
@ -1275,6 +1308,41 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
|
||||||
// store:
|
// store:
|
||||||
switch (gl_lightmap_format)
|
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:
|
case GL_RGBA:
|
||||||
stride -= smax * 4;
|
stride -= smax * 4;
|
||||||
bl = blocklights;
|
bl = blocklights;
|
||||||
|
@ -1348,6 +1416,10 @@ static void R_UploadLightmap(int lmap)
|
||||||
|
|
||||||
lm->modified = false;
|
lm->modified = false;
|
||||||
|
|
||||||
|
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,
|
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);
|
GL_UNSIGNED_BYTE, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
|
||||||
lm->rectchange.l = LMBLOCK_WIDTH;
|
lm->rectchange.l = LMBLOCK_WIDTH;
|
||||||
|
@ -1439,6 +1511,10 @@ void R_RebuildAllLightmaps (void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL_Bind (lightmaps[i].texture);
|
GL_Bind (lightmaps[i].texture);
|
||||||
|
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,
|
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format,
|
||||||
GL_UNSIGNED_BYTE, lightmaps[i].data);
|
GL_UNSIGNED_BYTE, lightmaps[i].data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,9 @@ QuakeSpasm-Spiked
|
||||||
"emiteffect" field - to specify a constantly emitting effect.
|
"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
|
4. Todo
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue