X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_light.c;h=5f9ef7f8f4c871c67e6c9cd47a87832e8bd9055f;hp=aa35da8ef81bab35d205918b4bc6f54889303df0;hb=9085903141b6ca8abcf0f518908d770e0107d378;hpb=c4ee1bbcc6b2f917465f07269ad09942bbf40849 diff --git a/r_light.c b/r_light.c index aa35da8e..5f9ef7f8 100644 --- a/r_light.c +++ b/r_light.c @@ -20,13 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // r_light.c #include "quakedef.h" +#include "cl_collision.h" rdlight_t r_dlight[MAX_DLIGHTS]; int r_numdlights = 0; -cvar_t r_lightmodels = {CVAR_SAVE, "r_lightmodels", "1"}; +cvar_t r_modellights = {CVAR_SAVE, "r_modellights", "4"}; cvar_t r_vismarklights = {0, "r_vismarklights", "1"}; -cvar_t r_lightmodelhardness = {CVAR_SAVE, "r_lightmodelhardness", "0.9"}; static rtexture_t *lightcorona; static rtexturepool_t *lighttexturepool; @@ -43,7 +43,7 @@ void r_light_start(void) for (x = 0;x < 32;x++) { dx = (x - 15.5f) * (1.0f / 16.0f); - a = ((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 64.0f / (1.0f / (1.0f + 0.2)); + a = ((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)); a = bound(0, a, 255); pixels[y][x][0] = 255; pixels[y][x][1] = 255; @@ -66,8 +66,7 @@ void r_light_newmap(void) void R_Light_Init(void) { - Cvar_RegisterVariable(&r_lightmodels); - Cvar_RegisterVariable(&r_lightmodelhardness); + Cvar_RegisterVariable(&r_modellights); Cvar_RegisterVariable(&r_vismarklights); R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap); } @@ -102,9 +101,9 @@ void R_AnimateLight (void) void R_BuildLightList(void) { - int i; - dlight_t *cd; - rdlight_t *rd; + int i; + dlight_t *cd; + rdlight_t *rd; r_numdlights = 0; c_dlights = 0; @@ -119,14 +118,14 @@ void R_BuildLightList(void) continue; rd = &r_dlight[r_numdlights++]; VectorCopy(cd->origin, rd->origin); - VectorScale(cd->color, cd->radius * 128.0f, rd->light); - rd->cullradius = (1.0f / 128.0f) * sqrt(DotProduct(rd->light, rd->light)); + VectorScale(cd->color, cd->radius * 64.0f, rd->light); + rd->cullradius2 = DotProduct(rd->light, rd->light) * (0.25f / (64.0f * 64.0f)) + 4096.0f; // clamp radius to avoid overflowing division table in lightmap code - if (rd->cullradius > 2048.0f) - rd->cullradius = 2048.0f; - rd->cullradius2 = rd->cullradius * rd->cullradius; - rd->lightsubtract = 1.0f / rd->cullradius2; - rd->ent = cd->ent; + if (rd->cullradius2 > (2048.0f * 2048.0f)) + rd->cullradius2 = (2048.0f * 2048.0f); + rd->cullradius = sqrt(rd->cullradius2); + rd->subtract = 1.0f / rd->cullradius2; + //rd->ent = cd->ent; r_numdlights++; c_dlights++; // count every dlight in use } @@ -170,10 +169,9 @@ void R_DrawCoronas(void) { // trace to a point just barely closer to the eye VectorSubtract(rd->origin, vpn, diff); - if (TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1) + if (CL_TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1) { - scale = 1.0f / 262144.0f; - //scale = 64.0f / (DotProduct(diff,diff) + 1024.0f); + scale = 1.0f / 131072.0f; m.cr = rd->light[0] * scale; m.cg = rd->light[1] * scale; m.cb = rd->light[2] * scale; @@ -217,10 +215,10 @@ R_MarkLights */ static void R_OldMarkLights (vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node) { - float ndist, maxdist; - msurface_t *surf; - mleaf_t *leaf; - int i; + float ndist, maxdist; + msurface_t *surf; + mleaf_t *leaf; + int i; if (!r_dynamic.integer) return; @@ -276,9 +274,17 @@ loc0: if (dist2 >= maxdist) continue; - impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; - impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; - impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; + if (node->plane->type < 3) + { + VectorCopy(rd->origin, impact); + impact[node->plane->type] -= dist; + } + else + { + impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; + impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; + impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; + } impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; @@ -294,65 +300,12 @@ loc0: if (dist2 > maxdist) continue; - - /* - d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; - - if (d < 0) - { - dist2 += d * d; - if (dist2 >= maxdist) - continue; - } - else - { - d -= surf->extents[0] + 16; - if (d > 0) - { - dist2 += d * d; - if (dist2 >= maxdist) - continue; - } - } - - d = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; - - if (d < 0) - { - dist2 += d * d; - if (dist2 >= maxdist) - continue; - } - else - { - d -= surf->extents[1] + 16; - if (d > 0) - { - dist2 += d * d; - if (dist2 >= maxdist) - continue; - } - } - */ - if (surf->dlightframe != r_framecount) // not dynamic until now { surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; surf->dlightframe = r_framecount; } surf->dlightbits[bitindex] |= bit; - - /* - if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist)) - { - if (surf->dlightframe != r_framecount) // not dynamic until now - { - surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; - surf->dlightframe = r_framecount; - } - surf->dlightbits[bitindex] |= bit; - } - */ } if (node->children[0]->contents >= 0) @@ -376,15 +329,6 @@ loc0: } } -/* -static void R_NoVisMarkLights (rdlight_t *rd, int bit, int bitindex) -{ - vec3_t lightorigin; - softwareuntransform(rd->origin, lightorigin); - - R_OldMarkLights(lightorigin, rd, bit, bitindex, currentrenderentity->model->nodes + currentrenderentity->model->hulls[0].firstclipnode); -} -*/ static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex) { @@ -392,12 +336,12 @@ static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex) mleaf_t *pvsleaf; vec3_t lightorigin; model_t *model; - int i, k, m, c, leafnum; + int i, k, m, c, leafnum; msurface_t *surf, **mark; mleaf_t *leaf; - qbyte *in; - int row; - float low[3], high[3], dist, maxdist; + qbyte *in; + int row; + float low[3], high[3], dist, maxdist; if (!r_dynamic.integer) return; @@ -489,49 +433,18 @@ static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex) dist2 = dist * dist; - impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; - impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; - impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; - -#if 0 - d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; - if (d < 0) + if (surf->plane->type < 3) { - dist2 += d * d; - if (dist2 > maxdist) - continue; + VectorCopy(rd->origin, impact); + impact[surf->plane->type] -= dist; } else { - d -= surf->extents[0]; - if (d < 0) - { - dist2 += d * d; - if (dist2 > maxdist) - continue; - } + impact[0] = rd->origin[0] - surf->plane->normal[0] * dist; + impact[1] = rd->origin[1] - surf->plane->normal[1] * dist; + impact[2] = rd->origin[2] - surf->plane->normal[2] * dist; } - d = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; - if (d < 0) - { - dist2 += d * d; - if (dist2 > maxdist) - continue; - } - else - { - d -= surf->extents[1]; - if (d < 0) - { - dist2 += d * d; - if (dist2 > maxdist) - continue; - } - } - -#else - impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; d = bound(0, impacts, surf->extents[0] + 16) - impacts; dist2 += d * d; @@ -544,8 +457,6 @@ static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex) if (dist2 > maxdist) continue; -#endif - if (surf->dlightframe != r_framecount) // not dynamic until now { surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; @@ -583,9 +494,9 @@ LIGHT SAMPLING static int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz) { - int side, distz = endz - startz; - float front, back; - float mid; + int side, distz = endz - startz; + float front, back; + float mid; loc0: if (node->contents < 0) @@ -607,11 +518,6 @@ loc0: goto loc0; } // found an intersection -// mid = startz + (endz - startz) * (startz - node->plane->dist) / (startz - endz); -// mid = startz + distz * (startz - node->plane->dist) / (-distz); -// mid = startz + (-(startz - node->plane->dist)); -// mid = startz - (startz - node->plane->dist); -// mid = startz + node->plane->dist - startz; mid = node->plane->dist; break; default: @@ -625,8 +531,6 @@ loc0: goto loc0; } // found an intersection -// mid = startz + (endz - startz) * ((front - node->plane->dist) / ((front - node->plane->dist) - (back - node->plane->dist))); -// mid = startz + (endz - startz) * ((front - node->plane->dist) / (front - back)); mid = startz + distz * (front - node->plane->dist) / (front - back); break; } @@ -679,33 +583,38 @@ loc0: lightmap += size3; } - /* - // LordHavoc: here's the readable version of the interpolation - // code, not quite as easy for the compiler to optimize... - - // dsfrac is the X position in the lightmap pixel, * 16 - // dtfrac is the Y position in the lightmap pixel, * 16 - // r00 is top left corner, r01 is top right corner - // r10 is bottom left corner, r11 is bottom right corner - // g and b are the same layout. - // r0 and r1 are the top and bottom intermediate results - - // first we interpolate the top two points, to get the top - // edge sample - r0 = (((r01-r00) * dsfrac) >> 4) + r00; - g0 = (((g01-g00) * dsfrac) >> 4) + g00; - b0 = (((b01-b00) * dsfrac) >> 4) + b00; - // then we interpolate the bottom two points, to get the - // bottom edge sample - r1 = (((r11-r10) * dsfrac) >> 4) + r10; - g1 = (((g11-g10) * dsfrac) >> 4) + g10; - b1 = (((b11-b10) * dsfrac) >> 4) + b10; - // then we interpolate the top and bottom samples to get the - // middle sample (the one which was requested) - r = (((r1-r0) * dtfrac) >> 4) + r0; - g = (((g1-g0) * dtfrac) >> 4) + g0; - b = (((b1-b0) * dtfrac) >> 4) + b0; - */ +/* +LordHavoc: here's the readable version of the interpolation +code, not quite as easy for the compiler to optimize... + +dsfrac is the X position in the lightmap pixel, * 16 +dtfrac is the Y position in the lightmap pixel, * 16 +r00 is top left corner, r01 is top right corner +r10 is bottom left corner, r11 is bottom right corner +g and b are the same layout. +r0 and r1 are the top and bottom intermediate results + +first we interpolate the top two points, to get the top +edge sample + + r0 = (((r01-r00) * dsfrac) >> 4) + r00; + g0 = (((g01-g00) * dsfrac) >> 4) + g00; + b0 = (((b01-b00) * dsfrac) >> 4) + b00; + +then we interpolate the bottom two points, to get the +bottom edge sample + + r1 = (((r11-r10) * dsfrac) >> 4) + r10; + g1 = (((g11-g10) * dsfrac) >> 4) + g10; + b1 = (((b11-b10) * dsfrac) >> 4) + b10; + +then we interpolate the top and bottom samples to get the +middle sample (the one which was requested) + + r = (((r1-r0) * dtfrac) >> 4) + r0; + g = (((g1-g0) * dtfrac) >> 4) + g0; + b = (((b1-b0) * dtfrac) >> 4) + b0; +*/ color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 32768.0f); color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 32768.0f); @@ -720,16 +629,16 @@ loc0: startz = mid; distz = endz - startz; goto loc0; -// return RecursiveLightPoint (color, node->children[side ^ 1], x, y, mid, endz); } } void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) { - int i, *dlightbits; - vec3_t dist; + int i, *dlightbits; + vec3_t v; float f; rdlight_t *rd; + mlight_t *sl; if (leaf == NULL) leaf = Mod_PointInLeaf(p, cl.worldmodel); @@ -746,7 +655,25 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) } color[0] = color[1] = color[2] = r_ambient.value * (2.0f / 128.0f); - RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); + if (cl.worldmodel->numlights) + { + for (i = 0;i < cl.worldmodel->numlights;i++) + { + sl = cl.worldmodel->lights + i; + if (d_lightstylevalue[sl->style] > 0) + { + VectorSubtract (p, sl->origin, v); + f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract); + if (f > 0 && CL_TraceLine(p, sl->origin, NULL, NULL, 0, false) == 1) + { + f *= d_lightstylevalue[sl->style] * (1.0f / 65536.0f); + VectorMA(color, f, sl->light, color); + } + } + } + } + else + RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); if (dynamic && leaf->dlightframe == r_framecount) { @@ -756,13 +683,12 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) if (!(dlightbits[i >> 5] & (1 << (i & 31)))) continue; rd = r_dlight + i; - VectorSubtract (p, rd->origin, dist); - f = DotProduct(dist, dist) + LIGHTOFFSET; + VectorSubtract (p, rd->origin, v); + f = DotProduct(v, v); if (f < rd->cullradius2) { - f = (1.0f / f) - rd->lightsubtract; - if (f > 0) - VectorMA(color, f, rd->light, color); + f = (1.0f / (f + LIGHTOFFSET)) - rd->subtract; + VectorMA(color, f, rd->light, color); } } } @@ -779,7 +705,7 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) return; } - if (r_fullbright.integer || !cl.worldmodel->lightdata) + if (r_fullbright.integer || !cl.worldmodel->lightdata || currentrenderentity->effects & EF_FULLBRIGHT) { color[0] = color[1] = color[2] = 2; dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; @@ -787,7 +713,8 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) } color[0] = color[1] = color[2] = r_ambient.value * (2.0f / 128.0f); - RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); + if (!cl.worldmodel->numlights) + RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); if (leaf->dlightframe == r_framecount) { @@ -804,113 +731,193 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; } -void R_LightModel(int numverts) +void R_LightModel(int numverts, float colorr, float colorg, float colorb, int worldcoords) { - int i, j, nearlights = 0; - float color[3], basecolor[3], v[3], t, *av, *avn, *avc, a, number, f, hardness, hardnessoffset, dist2; + int i, j, nearlights = 0, maxnearlights = r_modellights.integer; + float color[3], basecolor[3], v[3], t, *av, *avn, *avc, a, f, dist2, mscale, dot, stylescale, intensity, ambientcolor[3]; struct { vec3_t origin; - vec_t cullradius2; + //vec_t cullradius2; vec3_t light; - vec_t lightsubtract; + // how much this light would contribute to ambient if replaced + vec3_t ambientlight; + vec_t subtract; + vec_t falloff; + vec_t offset; + // used for choosing only the brightest lights + vec_t intensity; } nearlight[MAX_DLIGHTS], *nl; int modeldlightbits[8]; - //staticlight_t *sl; + mlight_t *sl; + rdlight_t *rd; a = currentrenderentity->alpha; - if (currentrenderentity->effects & EF_FULLBRIGHT) - basecolor[0] = basecolor[1] = basecolor[2] = 1; - else + // scale of the model's coordinate space, to alter light attenuation to match + // make the mscale squared so it can scale the squared distance results + mscale = currentrenderentity->scale * currentrenderentity->scale; + if ((maxnearlights != 0) && !r_fullbright.integer && !(currentrenderentity->effects & EF_FULLBRIGHT)) { - if (r_lightmodels.integer) - { - R_ModelLightPoint(basecolor, currentrenderentity->origin, modeldlightbits); + R_ModelLightPoint(basecolor, currentrenderentity->origin, modeldlightbits); - nl = &nearlight[0]; - /* - // this code is unused for now - for (i = 0, sl = staticlight;i < staticlights && nearlights < MAX_DLIGHTS;i++, sl++) + nl = &nearlight[0]; + VectorSubtract(currentrenderentity->origin, currentrenderentity->entlightsorigin, v); + if ((realtime > currentrenderentity->entlightstime && DotProduct(v,v) >= 1.0f)) + { + currentrenderentity->numentlights = 0; + currentrenderentity->entlightstime = realtime + 0.2; + VectorCopy(currentrenderentity->origin, currentrenderentity->entlightsorigin); + for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && currentrenderentity->numentlights < MAXENTLIGHTS;i++, sl++) + if (CL_TraceLine(currentrenderentity->origin, sl->origin, NULL, NULL, 0, false) == 1) + currentrenderentity->entlights[currentrenderentity->numentlights++] = i; + } + for (i = 0;i < currentrenderentity->numentlights;i++) + { + sl = cl.worldmodel->lights + currentrenderentity->entlights[i]; + stylescale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f); + VectorSubtract (currentrenderentity->origin, sl->origin, v); + f = ((1.0f / (DotProduct(v, v) * sl->falloff + sl->distbias)) - sl->subtract) * stylescale; + VectorScale(sl->light, f, ambientcolor); + intensity = DotProduct(ambientcolor, ambientcolor); + if (f < 0) + intensity *= -1.0f; + if (nearlights < maxnearlights) + j = nearlights++; + else { - if (TraceLine(currentrenderentity->origin, sl->origin, NULL, NULL, 0) == 1) + for (j = 0;j < maxnearlights;j++) { - nl->fadetype = sl->fadetype; - nl->distancescale = sl->distancescale; - nl->radius = sl->radius; - VectorCopy(sl->origin, nl->origin); - VectorCopy(sl->color, nl->light); - nl->cullradius2 = 99999999; - nl->lightsubtract = 0; - nl++; - nearlights++; + if (nearlight[j].intensity < intensity) + { + if (nearlight[j].intensity > 0) + VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); + break; + } } } - */ - for (i = 0;i < r_numdlights && nearlights < MAX_DLIGHTS;i++) + if (j >= maxnearlights) { - if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) - continue; - if (currentrenderentity == r_dlight[i].ent) - { - f = (1.0f / LIGHTOFFSET) - nl->lightsubtract; - if (f > 0) - VectorMA(basecolor, f, r_dlight[i].light, basecolor); - } + // this light is less significant than all others, + // add it to ambient + if (intensity > 0) + VectorAdd(basecolor, ambientcolor, basecolor); + } + else + { + nl = nearlight + j; + nl->intensity = intensity; + // transform the light into the model's coordinate system + if (worldcoords) + VectorCopy(sl->origin, nl->origin); else + softwareuntransform(sl->origin, nl->origin); + // integrate mscale into falloff, for maximum speed + nl->falloff = sl->falloff * mscale; + VectorCopy(ambientcolor, nl->ambientlight); + nl->light[0] = sl->light[0] * stylescale * colorr * 4.0f; + nl->light[1] = sl->light[1] * stylescale * colorg * 4.0f; + nl->light[2] = sl->light[2] * stylescale * colorb * 4.0f; + nl->subtract = sl->subtract; + nl->offset = sl->distbias; + } + } + for (i = 0;i < r_numdlights;i++) + { + if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) + continue; + rd = r_dlight + i; + VectorSubtract (currentrenderentity->origin, rd->origin, v); + f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); + VectorScale(rd->light, f, ambientcolor); + intensity = DotProduct(ambientcolor, ambientcolor); + if (f < 0) + intensity *= -1.0f; + if (nearlights < maxnearlights) + j = nearlights++; + else + { + for (j = 0;j < maxnearlights;j++) { - // convert 0-255 radius coloring to 0-1, while also amplifying the brightness by 16 - //if (TraceLine(currentrenderentity->origin, r_dlight[i].origin, NULL, NULL, 0) == 1) + if (nearlight[j].intensity < intensity) { - // transform the light into the model's coordinate system - //if (gl_transform.integer) - // softwareuntransform(r_dlight[i].origin, nl->origin); - //else - VectorCopy(r_dlight[i].origin, nl->origin); - nl->cullradius2 = r_dlight[i].cullradius2; - VectorCopy(r_dlight[i].light, nl->light); - nl->lightsubtract = r_dlight[i].lightsubtract; - nl++; - nearlights++; + if (nearlight[j].intensity > 0) + VectorAdd(basecolor, nearlight[j].ambientlight, basecolor); + break; } } } + if (j >= maxnearlights) + { + // this light is less significant than all others, + // add it to ambient + if (intensity > 0) + VectorAdd(basecolor, ambientcolor, basecolor); + } + else + { + nl = nearlight + j; + nl->intensity = intensity; + // transform the light into the model's coordinate system + if (worldcoords) + VectorCopy(rd->origin, nl->origin); + else + softwareuntransform(rd->origin, nl->origin); + // integrate mscale into falloff, for maximum speed + nl->falloff = mscale; + VectorCopy(ambientcolor, nl->ambientlight); + nl->light[0] = rd->light[0] * colorr * 4.0f; + nl->light[1] = rd->light[1] * colorg * 4.0f; + nl->light[2] = rd->light[2] * colorb * 4.0f; + nl->subtract = rd->subtract; + nl->offset = LIGHTOFFSET; + } } - else - R_CompleteLightPoint (basecolor, currentrenderentity->origin, true, NULL); } + else + { + R_CompleteLightPoint (basecolor, currentrenderentity->origin, true, NULL); + } + basecolor[0] *= colorr; + basecolor[1] *= colorg; + basecolor[2] *= colorb; avc = aliasvertcolor; if (nearlights) { av = aliasvert; avn = aliasvertnorm; - hardness = r_lightmodelhardness.value; - hardnessoffset = (1.0f - hardness); for (i = 0;i < numverts;i++) { VectorCopy(basecolor, color); for (j = 0, nl = &nearlight[0];j < nearlights;j++, nl++) { - // distance attenuation VectorSubtract(nl->origin, av, v); - dist2 = DotProduct(v,v); - if (dist2 < nl->cullradius2) + // directional shading + dot = DotProduct(avn,v); + if (dot > 0) { - f = (1.0f / (dist2 + LIGHTOFFSET)) - nl->lightsubtract; + // the vertex normal faces the light + + // do the distance attenuation + dist2 = DotProduct(v,v); + f = (1.0f / (dist2 * nl->falloff + nl->offset)) - nl->subtract; if (f > 0) { - // directional shading #if SLOWMATH t = 1.0f / sqrt(dist2); #else - number = DotProduct(v, v); - *((long *)&t) = 0x5f3759df - ((* (long *) &number) >> 1); - t = t * (1.5f - (number * 0.5f * t * t)); + *((int *)&t) = 0x5f3759df - ((* (int *) &dist2) >> 1); + t = t * (1.5f - (dist2 * 0.5f * t * t)); #endif - // DotProduct(avn,v) * t is dotproduct with a normalized v, + + // dot * t is dotproduct with a normalized v. + // (the result would be -1 to +1, but we already + // eliminated the <= 0 case, so it is 0 to 1) + // the hardness variables are for backlighting/shinyness - f *= DotProduct(avn,v) * t * hardness + hardnessoffset; - if (f > 0) - VectorMA(color, f, nl->light, color); + // these have been hardwired at * 0.5 + 0.5 to match + // the quake map lighting utility's equations + f *= dot * t;// * 0.5f + 0.5f;// * hardness + hardnessoffset; + VectorMA(color, f, nl->light, color); } } } @@ -932,3 +939,4 @@ void R_LightModel(int numverts) } } } +