mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-29 20:20:43 +00:00
Another 0.657% speedup for greyscale lighting. Unfortunately, at a price of considerable code duplication. But this is necessary for other planned changes.
This commit is contained in:
parent
6c8e2c24aa
commit
802bcc2762
1 changed files with 222 additions and 67 deletions
|
@ -111,6 +111,9 @@ msurface_t **sky_chain_tail;
|
||||||
# define CHAIN_SURF CHAIN_SURF_B2F
|
# define CHAIN_SURF CHAIN_SURF_B2F
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void (*R_AddDynamicLights) (msurface_t *surf);
|
||||||
|
void (*R_BuildLightMap) (msurface_t *surf, byte *dest, int stride);
|
||||||
|
|
||||||
|
|
||||||
// LordHavoc: place for gl_rsurf setup code
|
// LordHavoc: place for gl_rsurf setup code
|
||||||
void
|
void
|
||||||
|
@ -140,7 +143,71 @@ R_RecursiveLightUpdate (mnode_t *node)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
R_AddDynamicLights (msurface_t *surf)
|
R_AddDynamicLights_1 (msurface_t *surf)
|
||||||
|
{
|
||||||
|
float dist;
|
||||||
|
int lnum, maxdist, maxdist2, maxdist3, smax, smax_bytes, tmax,
|
||||||
|
grey;
|
||||||
|
unsigned int td, i, j, s, t;
|
||||||
|
unsigned int sdtable[18];
|
||||||
|
unsigned int *bl;
|
||||||
|
vec3_t impact, local;
|
||||||
|
|
||||||
|
smax = (surf->extents[0] >> 4) + 1;
|
||||||
|
smax_bytes = smax * gl_internalformat;
|
||||||
|
tmax = (surf->extents[1] >> 4) + 1;
|
||||||
|
|
||||||
|
for (lnum = 0; lnum < r_maxdlights; lnum++) {
|
||||||
|
if (!(surf->dlightbits & (1 << lnum)))
|
||||||
|
continue; // not lit by this light
|
||||||
|
|
||||||
|
VectorSubtract (r_dlights[lnum].origin, currententity->origin, local);
|
||||||
|
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
|
||||||
|
VectorMA (r_dlights[lnum].origin, -dist, surf->plane->normal, impact);
|
||||||
|
|
||||||
|
i = DotProduct (impact, surf->texinfo->vecs[0]) +
|
||||||
|
surf->texinfo->vecs[0][3] - surf->texturemins[0];
|
||||||
|
|
||||||
|
// reduce calculations
|
||||||
|
t = dist * dist;
|
||||||
|
for (s = 0; s < smax; s++, i -= 16)
|
||||||
|
sdtable[s] = i * i + t;
|
||||||
|
|
||||||
|
i = DotProduct (impact, surf->texinfo->vecs[1]) +
|
||||||
|
surf->texinfo->vecs[1][3] - surf->texturemins[1];
|
||||||
|
|
||||||
|
// for comparisons to minimum acceptable light
|
||||||
|
maxdist = (int) ((r_dlights[lnum].radius * r_dlights[lnum].radius) *
|
||||||
|
0.75);
|
||||||
|
|
||||||
|
// clamp radius to avoid exceeding 8192 entry division table
|
||||||
|
if (maxdist > 1048576)
|
||||||
|
maxdist = 1048576;
|
||||||
|
maxdist3 = maxdist - t;
|
||||||
|
|
||||||
|
// convert to 8.8 blocklights format
|
||||||
|
grey = (r_dlights[lnum].color[0] + r_dlights[lnum].color[1] +
|
||||||
|
r_dlights[lnum].color[2]) * maxdist / 3.0;
|
||||||
|
bl = blocklights;
|
||||||
|
for (t = 0; t < tmax; t++, i -= 16) {
|
||||||
|
td = i * i;
|
||||||
|
if (td < maxdist3) { // ensure part is visible on this line
|
||||||
|
maxdist2 = maxdist - td;
|
||||||
|
for (s = 0; s < smax; s++) {
|
||||||
|
if (sdtable[s] < maxdist2) {
|
||||||
|
j = dlightdivtable[(sdtable[s] + td) >> 7];
|
||||||
|
*bl++ += (grey * j) >> 7;
|
||||||
|
} else
|
||||||
|
bl++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
bl += smax_bytes; // skip line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
R_AddDynamicLights_3 (msurface_t *surf)
|
||||||
{
|
{
|
||||||
float dist;
|
float dist;
|
||||||
int lnum, maxdist, maxdist2, maxdist3, smax, smax_bytes, tmax,
|
int lnum, maxdist, maxdist2, maxdist3, smax, smax_bytes, tmax,
|
||||||
|
@ -183,38 +250,22 @@ R_AddDynamicLights (msurface_t *surf)
|
||||||
maxdist3 = maxdist - t;
|
maxdist3 = maxdist - t;
|
||||||
|
|
||||||
// convert to 8.8 blocklights format
|
// convert to 8.8 blocklights format
|
||||||
if (gl_internalformat > 1) {
|
red = r_dlights[lnum].color[0] * maxdist;
|
||||||
red = r_dlights[lnum].color[0] * maxdist;
|
green = r_dlights[lnum].color[1] * maxdist;
|
||||||
green = r_dlights[lnum].color[1] * maxdist;
|
blue = r_dlights[lnum].color[2] * maxdist;
|
||||||
blue = r_dlights[lnum].color[2] * maxdist;
|
|
||||||
} else {
|
|
||||||
red = (r_dlights[lnum].color[0] + r_dlights[lnum].color[1] +
|
|
||||||
r_dlights[lnum].color[2]) * maxdist / 3.0;
|
|
||||||
green = blue = 0;
|
|
||||||
}
|
|
||||||
bl = blocklights;
|
bl = blocklights;
|
||||||
for (t = 0; t < tmax; t++, i -= 16) {
|
for (t = 0; t < tmax; t++, i -= 16) {
|
||||||
td = i * i;
|
td = i * i;
|
||||||
if (td < maxdist3) { // ensure part is visible on this line
|
if (td < maxdist3) { // ensure part is visible on this line
|
||||||
maxdist2 = maxdist - td;
|
maxdist2 = maxdist - td;
|
||||||
if (gl_internalformat > 1) {
|
for (s = 0; s < smax; s++) {
|
||||||
for (s = 0; s < smax; s++) {
|
if (sdtable[s] < maxdist2) {
|
||||||
if (sdtable[s] < maxdist2) {
|
j = dlightdivtable[(sdtable[s] + td) >> 7];
|
||||||
j = dlightdivtable[(sdtable[s] + td) >> 7];
|
*bl++ += (red * j) >> 7;
|
||||||
*bl++ += (red * j) >> 7;
|
*bl++ += (green * j) >> 7;
|
||||||
*bl++ += (green * j) >> 7;
|
*bl++ += (blue * j) >> 7;
|
||||||
*bl++ += (blue * j) >> 7;
|
} else
|
||||||
} else
|
bl += 3;
|
||||||
bl += 3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (s = 0; s < smax; s++) {
|
|
||||||
if (sdtable[s] < maxdist2) {
|
|
||||||
j = dlightdivtable[(sdtable[s] + td) >> 7];
|
|
||||||
*bl++ += (red * j) >> 7;
|
|
||||||
} else
|
|
||||||
bl++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
bl += smax_bytes; // skip line
|
bl += smax_bytes; // skip line
|
||||||
|
@ -222,16 +273,8 @@ R_AddDynamicLights (msurface_t *surf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
R_BuildLightMap
|
|
||||||
|
|
||||||
Combine and scale multiple lightmaps.
|
|
||||||
After talking it over with LordHavoc, I've decided to switch to using
|
|
||||||
GL_RGB for colored lights and averaging them out for plain white
|
|
||||||
lighting if needed. Much cleaner that way. --KB
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
R_BuildLightMap (msurface_t *surf, byte * dest, int stride)
|
R_BuildLightMap_1 (msurface_t *surf, byte *dest, int stride)
|
||||||
{
|
{
|
||||||
byte *lightmap;
|
byte *lightmap;
|
||||||
int maps, shift, size, smax, tmax, i, j;
|
int maps, shift, size, smax, tmax, i, j;
|
||||||
|
@ -285,41 +328,147 @@ R_BuildLightMap (msurface_t *surf, byte * dest, int stride)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (lightmap_bytes) {
|
for (i = 0; i < tmax; i++, dest += stride) {
|
||||||
case 4:
|
for (j = 0; j < smax; j++) {
|
||||||
for (i = 0; i < tmax; i++, dest += stride) {
|
*dest++ = min (*bl >> shift, 255);
|
||||||
for (j = 0; j < smax; j++) {
|
bl++;
|
||||||
*dest++ = min (*bl >> shift, 255);
|
}
|
||||||
bl++;
|
}
|
||||||
*dest++ = min (*bl >> shift, 255);
|
}
|
||||||
bl++;
|
|
||||||
*dest++ = min (*bl >> shift, 255);
|
static void
|
||||||
bl++;
|
R_BuildLightMap_3 (msurface_t *surf, byte *dest, int stride)
|
||||||
dest++; // `*dest++ = 255;` for RGBA internal format
|
{
|
||||||
// instead of RGB
|
byte *lightmap;
|
||||||
|
int maps, shift, size, smax, tmax, i, j;
|
||||||
|
unsigned int scale;
|
||||||
|
unsigned int *bl;
|
||||||
|
|
||||||
|
surf->cached_dlight = (surf->dlightframe == r_framecount);
|
||||||
|
|
||||||
|
smax = (surf->extents[0] >> 4) + 1;
|
||||||
|
tmax = (surf->extents[1] >> 4) + 1;
|
||||||
|
size = smax * tmax;
|
||||||
|
lightmap = surf->samples;
|
||||||
|
|
||||||
|
// set to full bright if no light data
|
||||||
|
if (!r_worldentity.model->lightdata) {
|
||||||
|
memset (&blocklights[0], 0xff, gl_internalformat * size * sizeof(int));
|
||||||
|
goto store;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear to no light
|
||||||
|
memset (&blocklights[0], 0, gl_internalformat * size * sizeof(int));
|
||||||
|
|
||||||
|
// add all the lightmaps
|
||||||
|
if (lightmap) {
|
||||||
|
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
|
||||||
|
maps++) {
|
||||||
|
scale = d_lightstylevalue[surf->styles[maps]];
|
||||||
|
surf->cached_light[maps] = scale; // 8.8 fraction
|
||||||
|
bl = blocklights;
|
||||||
|
for (i = 0; i < (size * gl_internalformat); i++) {
|
||||||
|
*bl++ += *lightmap++ * scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 3:
|
// add all the dynamic lights
|
||||||
for (i = 0; i < tmax; i++, dest += stride) {
|
if (surf->dlightframe == r_framecount)
|
||||||
for (j = 0; j < smax; j++) {
|
R_AddDynamicLights (surf);
|
||||||
*dest++ = min (*bl >> shift, 255);
|
|
||||||
bl++;
|
store:
|
||||||
*dest++ = min (*bl >> shift, 255);
|
// bound and shift
|
||||||
bl++;
|
stride -= smax * lightmap_bytes;
|
||||||
*dest++ = min (*bl >> shift, 255);
|
bl = blocklights;
|
||||||
bl++;
|
|
||||||
|
#if 0
|
||||||
|
if (gl_mtex_active) {
|
||||||
|
shift = 7; // 0-1 lightmap range.
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
shift = 8; // 0-2 lightmap range.
|
||||||
|
#if 0
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < tmax; i++, dest += stride) {
|
||||||
|
for (j = 0; j < smax; j++) {
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
R_BuildLightMap_4 (msurface_t *surf, byte * dest, int stride)
|
||||||
|
{
|
||||||
|
byte *lightmap;
|
||||||
|
int maps, shift, size, smax, tmax, i, j;
|
||||||
|
unsigned int scale;
|
||||||
|
unsigned int *bl;
|
||||||
|
|
||||||
|
surf->cached_dlight = (surf->dlightframe == r_framecount);
|
||||||
|
|
||||||
|
smax = (surf->extents[0] >> 4) + 1;
|
||||||
|
tmax = (surf->extents[1] >> 4) + 1;
|
||||||
|
size = smax * tmax;
|
||||||
|
lightmap = surf->samples;
|
||||||
|
|
||||||
|
// set to full bright if no light data
|
||||||
|
if (!r_worldentity.model->lightdata) {
|
||||||
|
memset (&blocklights[0], 0xff, gl_internalformat * size * sizeof(int));
|
||||||
|
goto store;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear to no light
|
||||||
|
memset (&blocklights[0], 0, gl_internalformat * size * sizeof(int));
|
||||||
|
|
||||||
|
// add all the lightmaps
|
||||||
|
if (lightmap) {
|
||||||
|
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
|
||||||
|
maps++) {
|
||||||
|
scale = d_lightstylevalue[surf->styles[maps]];
|
||||||
|
surf->cached_light[maps] = scale; // 8.8 fraction
|
||||||
|
bl = blocklights;
|
||||||
|
for (i = 0; i < (size * gl_internalformat); i++) {
|
||||||
|
*bl++ += *lightmap++ * scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 1:
|
// add all the dynamic lights
|
||||||
for (i = 0; i < tmax; i++, dest += stride) {
|
if (surf->dlightframe == r_framecount)
|
||||||
for (j = 0; j < smax; j++) {
|
R_AddDynamicLights (surf);
|
||||||
*dest++ = min (*bl >> shift, 255);
|
|
||||||
bl++;
|
store:
|
||||||
}
|
// bound and shift
|
||||||
|
stride -= smax * lightmap_bytes;
|
||||||
|
bl = blocklights;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (gl_mtex_active) {
|
||||||
|
shift = 7; // 0-1 lightmap range.
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
shift = 8; // 0-2 lightmap range.
|
||||||
|
#if 0
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < tmax; i++, dest += stride) {
|
||||||
|
for (j = 0; j < smax; j++) {
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
*dest++ = min (*bl >> shift, 255);
|
||||||
|
bl++;
|
||||||
|
dest++; // `*dest++ = 255;` for RGBA internal format
|
||||||
|
// instead of RGB
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,17 +1255,23 @@ GL_BuildLightmaps (model_t **models, int num_models)
|
||||||
gl_internalformat = 1;
|
gl_internalformat = 1;
|
||||||
gl_lightmap_format = GL_LUMINANCE;
|
gl_lightmap_format = GL_LUMINANCE;
|
||||||
lightmap_bytes = 1;
|
lightmap_bytes = 1;
|
||||||
|
R_AddDynamicLights = R_AddDynamicLights_1;
|
||||||
|
R_BuildLightMap = R_BuildLightMap_1;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
gl_internalformat = 3;
|
gl_internalformat = 3;
|
||||||
gl_lightmap_format = GL_RGB;
|
gl_lightmap_format = GL_RGB;
|
||||||
lightmap_bytes = 3;
|
lightmap_bytes = 3;
|
||||||
|
R_AddDynamicLights = R_AddDynamicLights_3;
|
||||||
|
R_BuildLightMap = R_BuildLightMap_3;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
default:
|
default:
|
||||||
gl_internalformat = 3;
|
gl_internalformat = 3;
|
||||||
gl_lightmap_format = GL_RGBA;
|
gl_lightmap_format = GL_RGBA;
|
||||||
lightmap_bytes = 4;
|
lightmap_bytes = 4;
|
||||||
|
R_AddDynamicLights = R_AddDynamicLights_3;
|
||||||
|
R_BuildLightMap = R_BuildLightMap_4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue