diff options
-rw-r--r-- | inc/refresh/refresh.h | 2 | ||||
-rw-r--r-- | src/client/view.c | 17 | ||||
-rw-r--r-- | src/refresh/gl/gl.h | 2 | ||||
-rw-r--r-- | src/refresh/sw/alias.c | 9 | ||||
-rw-r--r-- | src/refresh/sw/bsp.c | 2 | ||||
-rw-r--r-- | src/refresh/sw/light.c | 338 | ||||
-rw-r--r-- | src/refresh/sw/main.c | 4 | ||||
-rw-r--r-- | src/refresh/sw/surf.c | 8 | ||||
-rw-r--r-- | src/refresh/sw/sw.h | 3 |
9 files changed, 206 insertions, 179 deletions
diff --git a/inc/refresh/refresh.h b/inc/refresh/refresh.h index 6e79691..3edcc18 100644 --- a/inc/refresh/refresh.h +++ b/inc/refresh/refresh.h @@ -51,6 +51,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define RF_SHELL_MASK (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | \ RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) +#define DLIGHT_CUTOFF 64 + typedef struct entity_s { qhandle_t model; // opaque type outside refresh vec3_t angles; diff --git a/src/client/view.c b/src/client/view.c index ed5b840..808505e 100644 --- a/src/client/view.c +++ b/src/client/view.c @@ -123,16 +123,6 @@ void V_AddLight(vec3_t org, float intensity, float r, float g, float b) return; dl = &r_dlights[r_numdlights++]; VectorCopy(org, dl->origin); -#if USE_REF == REF_SOFT - // negative light in softwaref. only black allowed - if (r < 0 || g < 0 || b < 0) { - dl->intensity = -intensity; - dl->color[0] = 1; - dl->color[1] = 1; - dl->color[2] = 1; - return; - } -#endif dl->intensity = intensity; dl->color[0] = r; dl->color[1] = g; @@ -239,12 +229,15 @@ static void V_TestLights(void) float f, r; dlight_t *dl; - if (cl_testlights->integer == 2) { + if (cl_testlights->integer != 1) { dl = &r_dlights[0]; r_numdlights = 1; VectorMA(cl.refdef.vieworg, 256, cl.v_forward, dl->origin); - VectorSet(dl->color, 1, 1, 1); + if (cl_testlights->integer == -1) + VectorSet(dl->color, -1, -1, -1); + else + VectorSet(dl->color, 1, 1, 1); dl->intensity = 256; return; } diff --git a/src/refresh/gl/gl.h b/src/refresh/gl/gl.h index 0ccc586..3064967 100644 --- a/src/refresh/gl/gl.h +++ b/src/refresh/gl/gl.h @@ -232,8 +232,6 @@ typedef struct maliasmesh_s { * gl_surf.c * */ -#define DLIGHT_CUTOFF 64 - #define LIGHT_STYLE(surf, i) \ &glr.fd.lightstyles[gl_static.lightstylemap[(surf)->styles[i]]] diff --git a/src/refresh/sw/alias.c b/src/refresh/sw/alias.c index 0970f6d..dad1748 100644 --- a/src/refresh/sw/alias.c +++ b/src/refresh/sw/alias.c @@ -472,8 +472,6 @@ static void R_AliasSetupSkin(void) /* ================ R_AliasSetupLighting - - FIXME: put lighting into tables ================ */ static void R_AliasSetupLighting(void) @@ -484,13 +482,11 @@ static void R_AliasSetupLighting(void) // all components of light should be identical in software if (currententity->flags & RF_FULLBRIGHT) { - for (i = 0; i < 3; i++) - light[i] = 1.0; + VectorSet(light, 1, 1, 1); } else { R_LightPoint(currententity->origin, light); } - if (currententity->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) if (light[i] < 0.1) @@ -511,6 +507,9 @@ static void R_AliasSetupLighting(void) } } + for (i = 0; i < 3; i++) + clamp(light[i], 0, 1); + j = LUMINANCE(light[0], light[1], light[2]) * 256; r_ambientlight = 0; diff --git a/src/refresh/sw/bsp.c b/src/refresh/sw/bsp.c index d7430de..cde3410 100644 --- a/src/refresh/sw/bsp.c +++ b/src/refresh/sw/bsp.c @@ -29,7 +29,7 @@ vec3_t modelorg; // modelorg is the viewpoint reletive to vec3_t r_entorigin; // the currently rendering entity in world // coordinates -static float entity_rotation[3][3]; +vec3_t entity_rotation[3]; int r_currentbkey; diff --git a/src/refresh/sw/light.c b/src/refresh/sw/light.c index 78f3556..20d494a 100644 --- a/src/refresh/sw/light.c +++ b/src/refresh/sw/light.c @@ -32,67 +32,69 @@ DYNAMIC LIGHTS /* ============= -R_MarkLights +R_MarkLights_r ============= */ -static void R_MarkLights(dlight_t *light, int bit, mnode_t *node) +static void R_MarkLights_r(mnode_t *node, dlight_t *light, + vec3_t transformed, int bit) { - cplane_t *splitplane; float dist; mface_t *surf; int i; - if (!node->plane) - return; - - splitplane = node->plane; - dist = DotProduct(light->origin, splitplane->normal) - splitplane->dist; - - i = light->intensity; - if (i < 0) - i = -i; - - if (dist > i) { - R_MarkLights(light, bit, node->children[0]); - return; - } - if (dist < -i) { - R_MarkLights(light, bit, node->children[1]); - return; - } + while (node->plane) { + dist = PlaneDiffFast(transformed, node->plane); + if (dist > light->intensity - DLIGHT_CUTOFF) { + node = node->children[0]; + continue; + } + if (dist < -light->intensity + DLIGHT_CUTOFF) { + node = node->children[1]; + continue; + } -// mark the polygons - surf = node->firstface; - for (i = 0; i < node->numfaces; i++, surf++) { - if (surf->dlightframe != r_dlightframecount) { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; + // mark the polygons + surf = node->firstface; + for (i = 0; i < node->numfaces; i++, surf++) { + if (surf->dlightframe != r_dlightframecount) { + surf->dlightbits = 0; + surf->dlightframe = r_dlightframecount; + } + surf->dlightbits |= bit; } - surf->dlightbits |= bit; - } - R_MarkLights(light, bit, node->children[0]); - R_MarkLights(light, bit, node->children[1]); + R_MarkLights_r(node->children[0], light, transformed, bit); + node = node->children[1]; + } } - /* ============= -R_PushDlights +R_MarkLights ============= */ -void R_PushDlights(mnode_t *headnode) +void R_MarkLights(mnode_t *headnode) { - int i; - dlight_t *l; + dlight_t *light; + vec3_t transformed; + int i; r_dlightframecount = r_framecount; - for (i = 0, l = r_newrefdef.dlights; i < r_newrefdef.num_dlights; i++, l++) { - R_MarkLights(l, 1 << i, headnode); + for (i = 0, light = r_newrefdef.dlights; i < r_newrefdef.num_dlights; i++, light++) { + if (insubmodel) { + vec3_t temp; + + VectorSubtract(light->origin, currententity->origin, temp); + transformed[0] = DotProduct(temp, entity_rotation[0]); + transformed[1] = DotProduct(temp, entity_rotation[1]); + transformed[2] = DotProduct(temp, entity_rotation[2]); + } else { + VectorCopy(light->origin, transformed); + } + R_MarkLights_r(headnode, light, transformed, 1 << i); } } - /* ============================================================================= @@ -101,14 +103,17 @@ LIGHT SAMPLING ============================================================================= */ -static qboolean RecursiveLightPoint(vec3_t start, vec3_t color) +static qboolean _R_LightPoint(vec3_t start, vec3_t color) { mface_t *surf; - int smax, tmax, size; - int ds, dt; + int s, t, maps; byte *lightmap; - float *scales; - int maps; + byte *b1, *b2, *b3, *b4; + int fracu, fracv; + int w1, w2, w3, w4; + byte temp[3]; + int smax, tmax, size; + float scale; vec3_t end; lightpoint_t lightpoint; @@ -122,21 +127,39 @@ static qboolean RecursiveLightPoint(vec3_t start, vec3_t color) if (!surf) return qfalse; - ds = lightpoint.s >> 4; - dt = lightpoint.t >> 4; + fracu = lightpoint.s & 15; + fracv = lightpoint.t & 15; + + // compute weights of lightmap blocks + w1 = (16 - fracu) * (16 - fracv); + w2 = fracu * (16 - fracv); + w3 = fracu * fracv; + w4 = (16 - fracu) * fracv; + + s = lightpoint.s >> 4; + t = lightpoint.t >> 4; smax = S_MAX(surf); tmax = T_MAX(surf); size = smax * tmax * LIGHTMAP_BYTES; + // add all the lightmaps with bilinear filtering lightmap = surf->lightmap; - lightmap += dt * smax * LIGHTMAP_BYTES + ds * LIGHTMAP_BYTES; - for (maps = 0; maps < surf->numstyles; maps++) { - scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb; - color[0] += lightmap[0] * scales[0] * (1.0f / 255); - color[1] += lightmap[1] * scales[1] * (1.0f / 255); - color[2] += lightmap[2] * scales[2] * (1.0f / 255); + b1 = &lightmap[LIGHTMAP_BYTES * ((t + 0) * smax + (s + 0))]; + b2 = &lightmap[LIGHTMAP_BYTES * ((t + 0) * smax + (s + 1))]; + b3 = &lightmap[LIGHTMAP_BYTES * ((t + 1) * smax + (s + 1))]; + b4 = &lightmap[LIGHTMAP_BYTES * ((t + 1) * smax + (s + 0))]; + + temp[0] = (w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0]) >> 8; + temp[1] = (w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1]) >> 8; + temp[2] = (w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2]) >> 8; + + scale = r_newrefdef.lightstyles[surf->styles[maps]].white * (1.0f / 255); + color[0] += temp[0] * scale; + color[1] += temp[1] * scale; + color[2] += temp[2] * scale; + lightmap += size; } @@ -148,21 +171,20 @@ static qboolean RecursiveLightPoint(vec3_t start, vec3_t color) R_LightPoint =============== */ -void R_LightPoint(vec3_t p, vec3_t color) +void R_LightPoint(vec3_t point, vec3_t color) { int lnum; dlight_t *dl; - vec3_t dist; float add; - if (!r_worldmodel || !r_worldmodel->lightmap || !r_newrefdef.lightstyles) { + if (!r_worldmodel || !r_worldmodel->lightmap || r_fullbright->integer) { VectorSet(color, 1, 1, 1); return; } VectorClear(color); - if (!RecursiveLightPoint(p, color)) + if (!_R_LightPoint(point, color)) VectorSet(color, 1, 1, 1); // @@ -170,12 +192,9 @@ void R_LightPoint(vec3_t p, vec3_t color) // for (lnum = 0; lnum < r_newrefdef.num_dlights; lnum++) { dl = &r_newrefdef.dlights[lnum]; - VectorSubtract(p, - dl->origin, - dist); - add = dl->intensity - VectorLength(dist); - add *= (1.0 / 256); + add = dl->intensity - DLIGHT_CUTOFF - Distance(point, dl->origin); if (add > 0) { + add *= (1.0f / 255); VectorMA(color, add, dl->color, color); } } @@ -194,47 +213,45 @@ R_AddDynamicLights */ static void R_AddDynamicLights(void) { - mface_t *surf; - int lnum; - int sd, td; - float dist, rad, minlight; - vec3_t impact, local; - int s, t; - int i; - int smax, tmax; - mtexinfo_t *tex; - dlight_t *dl; - int negativeLight; - blocklight_t *block; + mface_t *surf; + dlight_t *light; + mtexinfo_t *tex; + vec3_t transformed, impact; + int local[2]; + vec_t dist, rad, minlight, scale, frac; + blocklight_t *block; + int i, smax, tmax, s, t, sd, td; surf = r_drawsurf.surf; smax = S_MAX(surf); tmax = T_MAX(surf); tex = surf->texinfo; - for (lnum = 0; lnum < r_newrefdef.num_dlights; lnum++) { - if (!(surf->dlightbits & (1 << lnum))) - continue; // not lit by this light + for (i = 0; i < r_newrefdef.num_dlights; i++) { + if (!(surf->dlightbits & (1 << i))) + continue; - dl = &r_newrefdef.dlights[lnum]; - rad = dl->intensity; + light = &r_newrefdef.dlights[i]; + + if (currententity && currententity != &r_worldentity) { + vec3_t temp; - negativeLight = 0; - if (rad < 0) { - negativeLight = 1; - rad = -rad; + VectorSubtract(light->origin, currententity->origin, temp); + transformed[0] = DotProduct(temp, entity_rotation[0]); + transformed[1] = DotProduct(temp, entity_rotation[1]); + transformed[2] = DotProduct(temp, entity_rotation[2]); + } else { + VectorCopy(light->origin, transformed); } - dist = PlaneDiffFast(dl->origin, surf->plane); - rad -= fabs(dist); - minlight = 32; // dl->minlight; - if (rad < minlight) + dist = PlaneDiffFast(transformed, surf->plane); + rad = light->intensity - fabs(dist); + if (rad < DLIGHT_CUTOFF) continue; - minlight = rad - minlight; + minlight = rad - DLIGHT_CUTOFF * 0.8f; + scale = rad / minlight; - for (i = 0; i < 3; i++) { - impact[i] = dl->origin[i] - surf->plane->normal[i] * dist; - } + VectorMA(transformed, -dist, surf->plane->normal, impact); local[0] = DotProduct(impact, tex->axis[0]) + tex->offset[0]; local[1] = DotProduct(impact, tex->axis[1]) + tex->offset[1]; @@ -242,48 +259,27 @@ static void R_AddDynamicLights(void) local[0] -= surf->texturemins[0]; local[1] -= surf->texturemins[1]; + block = blocklights; for (t = 0; t < tmax; t++) { - td = local[1] - t * 16; - if (td < 0) - td = -td; + td = abs(local[1] - (t << 4)); for (s = 0; s < smax; s++) { - sd = local[0] - s * 16; - if (sd < 0) - sd = -sd; - /*if (sd > td) - dist = sd + (td>>1); + sd = abs(local[0] - (s << 4)); + if (sd > td) + dist = sd + (td >> 1); else - dist = td + (sd>>1);*/ - dist = sqrt(sd * sd + td * td); - block = blocklights + t * smax * LIGHTMAP_BYTES + s * LIGHTMAP_BYTES; - if (!negativeLight) { - if (dist < minlight) { - block[0] += (rad - dist) * dl->color[0] * 256; - block[1] += (rad - dist) * dl->color[1] * 256; - block[2] += (rad - dist) * dl->color[2] * 256; - } - } else { - if (dist < minlight) { - block[0] -= (rad - dist) * dl->color[0] * 256; - block[1] -= (rad - dist) * dl->color[1] * 256; - block[2] -= (rad - dist) * dl->color[2] * 256; - } - if (block[0] < minlight) { - block[0] = minlight; - } - if (block[1] < minlight) { - block[1] = minlight; - } - if (block[2] < minlight) { - block[2] = minlight; - } + dist = td + (sd >> 1); + if (dist < minlight) { + frac = (rad - dist * scale) * sw_modulate->value * 256; + block[0] += light->color[0] * frac; + block[1] += light->color[1] * frac; + block[2] += light->color[2] * frac; } + block += LIGHTMAP_BYTES; } } } } - /* =============== R_BuildLightMap @@ -293,45 +289,45 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights */ void R_BuildLightMap(void) { - int smax, tmax; - int i, size; - byte *lightmap; - int maps; - mface_t *surf; - blocklight_t *dst; + int i, maps, smax, tmax, size; + byte *lightmap; + mface_t *surf; + blocklight_t *block; surf = r_drawsurf.surf; - smax = S_MAX(surf); tmax = T_MAX(surf); size = smax * tmax; - if (size > MAX_BLOCKLIGHTS) { - Com_Error(ERR_DROP, "R_BuildLightMap: surface blocklights size %i > %i", size, MAX_BLOCKLIGHTS); - } -// clear to no light - memset(blocklights, 0, sizeof(blocklights)); + if (size > MAX_BLOCKLIGHTS) + Com_Error(ERR_DROP, "R_BuildLightMap: surface blocklights size %i > %i", size, MAX_BLOCKLIGHTS); - if (r_fullbright->integer || !r_worldmodel->lightmap) { + if (r_fullbright->integer || !surf->lightmap) { + block = blocklights; + for (i = 0; i < size; i++) { + block[0] = block[1] = block[2] = 0xffff; + block += LIGHTMAP_BYTES; + } return; } +// clear to no light + memset(blocklights, 0, sizeof(blocklights[0]) * size * LIGHTMAP_BYTES); + // add all the lightmaps lightmap = surf->lightmap; - if (lightmap) { - for (maps = 0; maps < surf->numstyles; maps++) { - fixed8_t scale; - - dst = blocklights; - scale = r_drawsurf.lightadj[maps]; // 8.8 fraction - for (i = 0; i < size; i++) { - blocklights[i * LIGHTMAP_BYTES + 0] += lightmap[0] * scale; - blocklights[i * LIGHTMAP_BYTES + 1] += lightmap[1] * scale; - blocklights[i * LIGHTMAP_BYTES + 2] += lightmap[2] * scale; - - lightmap += LIGHTMAP_BYTES; - dst += LIGHTMAP_BYTES; - } + for (maps = 0; maps < surf->numstyles; maps++) { + fixed8_t scale; + + block = blocklights; + scale = r_drawsurf.lightadj[maps]; // 8.8 fraction + for (i = 0; i < size; i++) { + block[0] += lightmap[0] * scale; + block[1] += lightmap[1] * scale; + block[2] += lightmap[2] * scale; + + lightmap += LIGHTMAP_BYTES; + block += LIGHTMAP_BYTES; } } @@ -340,7 +336,45 @@ void R_BuildLightMap(void) R_AddDynamicLights(); // bound - for (i = 0; i < size * LIGHTMAP_BYTES; i++) - clamp(blocklights[i], 255, 65535); + block = blocklights; + for (i = 0; i < size; i++) { + blocklight_t r, g, b, max; + + r = block[0]; + g = block[1]; + b = block[2]; + + // catch negative lights + if (r < 255) + r = 255; + if (g < 255) + g = 255; + if (b < 255) + b = 255; + + // determine the brightest of the three color components + max = g; + if (r > max) + max = r; + if (b > max) + max = b; + + // rescale all the color components if the intensity of the greatest + // channel exceeds 1.0 + if (max > 65535) { + float y; + + y = 65535.0f / max; + r *= y; + g *= y; + b *= y; + } + + block[0] = r; + block[1] = g; + block[2] = b; + + block += LIGHTMAP_BYTES; + } } diff --git a/src/refresh/sw/main.c b/src/refresh/sw/main.c index ea166e3..561721a 100644 --- a/src/refresh/sw/main.c +++ b/src/refresh/sw/main.c @@ -705,7 +705,7 @@ static void R_DrawBEntitiesOnList(void) R_RotateBmodel(); // calculate dynamic lighting for bmodel - R_PushDlights(model->headnode); + R_MarkLights(model->headnode); if (topnode->plane) { // not a leaf; has to be clipped to the world BSP @@ -839,7 +839,7 @@ void R_RenderFrame(refdef_t *fd) R_MarkLeaves(); // done here so we know if we're in water if (r_worldmodel) - R_PushDlights(r_worldmodel->nodes); + R_MarkLights(r_worldmodel->nodes); R_EdgeDrawing(); diff --git a/src/refresh/sw/surf.c b/src/refresh/sw/surf.c index a9200ec..653c28a 100644 --- a/src/refresh/sw/surf.c +++ b/src/refresh/sw/surf.c @@ -336,10 +336,10 @@ surfcache_t *D_CacheSurface(mface_t *surface, int miplevel) // if the surface is animating or flashing, flush the cache // r_drawsurf.image = R_TextureAnimation(surface->texinfo); - r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white * 256; - r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white * 256; - r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white * 256; - r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white * 256; + r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white * sw_modulate->value * 256; + r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white * sw_modulate->value * 256; + r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white * sw_modulate->value * 256; + r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white * sw_modulate->value * 256; // // see if the cache holds apropriate data diff --git a/src/refresh/sw/sw.h b/src/refresh/sw/sw.h index c684794..52ac965 100644 --- a/src/refresh/sw/sw.h +++ b/src/refresh/sw/sw.h @@ -444,6 +444,7 @@ extern model_t *currentmodel; extern entity_t *currententity; extern vec3_t modelorg; extern vec3_t r_entorigin; +extern vec3_t entity_rotation[3]; extern float verticalFieldOfView; extern float xOrigin, yOrigin; @@ -475,7 +476,7 @@ void R_DrawSolidClippedSubmodelPolygons(mmodel_t *pmodel, mnode_t *topnode); void R_AliasDrawModel(void); void R_BeginEdgeFrame(void); void R_ScanEdges(void); -void R_PushDlights(mnode_t *headnode); +void R_MarkLights(mnode_t *headnode); void R_RotateBmodel(void); |