X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=r_light.c;h=c393f558e3a248c81e1a9a517853a912c14d8ab9;hb=1ff5a7ef75a7cc595f527a10b766a6c6020ac4c0;hp=0a3e27ff03eced79d4f817b43c99ed3f31905aad;hpb=7e5eece842864c299b83206699693913cb5ca0b7;p=xonotic%2Fdarkplaces.git diff --git a/r_light.c b/r_light.c index 0a3e27ff..c393f558 100644 --- a/r_light.c +++ b/r_light.c @@ -151,7 +151,7 @@ void R_DrawCoronas(void) { rd = r_dlight + i; dist = (DotProduct(rd->origin, vpn) - viewdist); - if (dist >= 24.0f && CL_TraceLine(rd->origin, r_origin, NULL, NULL, 0, true, NULL) == 1) + if (dist >= 24.0f && CL_TraceLine(rd->origin, r_origin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1) { cscale = (1.0f / 131072.0f); scale = rd->cullradius * 0.25f; @@ -173,255 +173,110 @@ DYNAMIC LIGHTS ============================================================================= */ +static int lightpvsbytes; +static qbyte lightpvs[(MAX_MAP_LEAFS+7)>>3]; + /* ============= R_MarkLights ============= */ -static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node) +static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node, qbyte *pvs, int pvsbits) { - float ndist, maxdist; - msurface_t *surf; - int i, *surfacepvsframes; - int d, impacts, impactt; - float dist, dist2, impact[3]; - - if (!r_dynamic.integer) - return; + int i; + mleaf_t *leaf; + float dist; // for comparisons to minimum acceptable light - maxdist = rd->cullradius2; - - surfacepvsframes = ent->model->brushq1.surfacepvsframes; -loc0: - if (node->contents < 0) - return; - - ndist = PlaneDiff(lightorigin, node->plane); - - if (ndist > rd->cullradius) - { - node = node->children[0]; - goto loc0; - } - if (ndist < -rd->cullradius) + while(node->contents >= 0) { - node = node->children[1]; - goto loc0; - } - -// mark the polygons - surf = ent->model->brushq1.surfaces + node->firstsurface; - for (i = 0;i < node->numsurfaces;i++, surf++) - { - if (surfacepvsframes[surf->number] != ent->model->brushq1.pvsframecount) - continue; - dist = ndist; - if (surf->flags & SURF_PLANEBACK) - dist = -dist; - - if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES)) - continue; - - dist2 = dist * dist; - if (dist2 >= maxdist) - continue; - - if (node->plane->type < 3) - { - VectorCopy(lightorigin, impact); - impact[node->plane->type] -= dist; - } + dist = PlaneDiff(lightorigin, node->plane); + if (dist > rd->cullradius) + node = node->children[0]; else { - impact[0] = lightorigin[0] - surf->plane->normal[0] * dist; - impact[1] = lightorigin[1] - surf->plane->normal[1] * dist; - impact[2] = lightorigin[2] - surf->plane->normal[2] * dist; - } - - 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; - if (dist2 > maxdist) - continue; - - impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; - - d = bound(0, impactt, surf->extents[1] + 16) - impactt; - 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; - if (r_dlightmap.integer) - surf->cached_dlight = true; + if (dist >= -rd->cullradius) + R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, node->children[0], pvs, pvsbits); + node = node->children[1]; } - surf->dlightbits[bitindex] |= bit; } - if (node->children[0]->contents >= 0) + // check if leaf is visible according to pvs + leaf = (mleaf_t *)node; + i = (leaf - ent->model->brushq1.leafs) - 1; + if (leaf->nummarksurfaces && (i >= pvsbits || pvs[i >> 3] & (1 << (i & 7)))) { - if (node->children[1]->contents >= 0) - { - R_OldMarkLights (ent, lightorigin, rd, bit, bitindex, node->children[0]); - node = node->children[1]; - goto loc0; - } - else + int *surfacepvsframes, d, impacts, impactt; + float sdist, maxdist, dist2, impact[3]; + msurface_t *surf; + // mark the polygons + maxdist = rd->cullradius2; + surfacepvsframes = ent->model->brushq1.surfacepvsframes; + for (i = 0;i < leaf->nummarksurfaces;i++) { - node = node->children[0]; - goto loc0; - } - } - else if (node->children[1]->contents >= 0) - { - node = node->children[1]; - goto loc0; - } -} + if (surfacepvsframes[leaf->firstmarksurface[i]] != ent->model->brushq1.pvsframecount) + continue; + surf = ent->model->brushq1.surfaces + leaf->firstmarksurface[i]; + dist = sdist = PlaneDiff(lightorigin, surf->plane); + if (surf->flags & SURF_PLANEBACK) + dist = -dist; + if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES)) + continue; -static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int bitindex) -{ - static int lightframe = 0; - mleaf_t *pvsleaf; - vec3_t lightorigin; - model_t *model; - int i, k, m, c, leafnum, *surfacepvsframes, *mark; - msurface_t *surf; - mleaf_t *leaf; - qbyte *in; - int row; - float low[3], high[3], dist, maxdist; + dist2 = dist * dist; + if (dist2 >= maxdist) + continue; - if (!r_dynamic.integer || !ent->model) - return; - - Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin); - - model = ent->model; - pvsleaf = model->brushq1.PointInLeaf(model, lightorigin); - if (pvsleaf == NULL) - return; - - in = pvsleaf->compressed_vis; - if (!r_vismarklights.integer || !in) - { - // told not to use pvs, or there's no pvs to use - R_OldMarkLights(ent, lightorigin, rd, bit, bitindex, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode); - return; - } + VectorCopy(lightorigin, impact); + if (surf->plane->type >= 3) + VectorMA(impact, -sdist, surf->plane->normal, impact); + else + impact[surf->plane->type] -= sdist; - lightframe++; + impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; - low[0] = lightorigin[0] - rd->cullradius;low[1] = lightorigin[1] - rd->cullradius;low[2] = lightorigin[2] - rd->cullradius; - high[0] = lightorigin[0] + rd->cullradius;high[1] = lightorigin[1] + rd->cullradius;high[2] = lightorigin[2] + rd->cullradius; + d = bound(0, impacts, surf->extents[0] + 16) - impacts; + dist2 += d * d; + if (dist2 > maxdist) + continue; - // for comparisons to minimum acceptable light - maxdist = rd->cullradius2; + impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; - row = (model->brushq1.numleafs+7)>>3; - surfacepvsframes = model->brushq1.surfacepvsframes; + d = bound(0, impactt, surf->extents[1] + 16) - impactt; + dist2 += d * d; + if (dist2 > maxdist) + continue; - k = 0; - while (k < row) - { - c = *in++; - if (c) - { - for (i = 0;i < 8;i++) + if (surf->dlightframe != r_framecount) // not dynamic until now { - if (c & (1< model->brushq1.numleafs) - return; - leaf = &model->brushq1.leafs[leafnum]; - if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0] - || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1] - || leaf->mins[2] > high[2] || leaf->maxs[2] < low[2]) - continue; - if ((m = leaf->nummarksurfaces)) - { - mark = leaf->firstmarksurface; - do - { - surf = model->brushq1.surfaces + *mark++; - // if not visible in current frame, or already marked because it was in another leaf we passed, skip - if (surf->lightframe == lightframe) - continue; - surf->lightframe = lightframe; - if (surfacepvsframes[surf->number] != model->brushq1.pvsframecount) - continue; - dist = PlaneDiff(lightorigin, surf->plane); - if (surf->flags & SURF_PLANEBACK) - dist = -dist; - // LordHavoc: make sure it is infront of the surface and not too far away - if (dist < rd->cullradius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -rd->cullradius))) - { - int d; - int impacts, impactt; - float dist2, impact[3]; - - dist2 = dist * dist; - - if (surf->plane->type < 3) - { - VectorCopy(lightorigin, impact); - impact[surf->plane->type] -= dist; - } - else - { - impact[0] = lightorigin[0] - surf->plane->normal[0] * dist; - impact[1] = lightorigin[1] - surf->plane->normal[1] * dist; - impact[2] = lightorigin[2] - surf->plane->normal[2] * dist; - } - - 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; - if (dist2 > maxdist) - continue; - - impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; - d = bound(0, impactt, surf->extents[1] + 16) - impactt; - 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; - if (r_dlightmap.integer) - surf->cached_dlight = true; - } - surf->dlightbits[bitindex] |= bit; - } - } - while (--m); - } - } + 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->cached_dlight = true; } - k++; - continue; + surf->dlightbits[bitindex] |= bit; } - - k += *in++; } } void R_MarkLights(entity_render_t *ent) { - int i; - if (!gl_flashblend.integer) - for (i = 0;i < r_numdlights;i++) - R_VisMarkLights (ent, r_dlight + i, 1 << (i & 31), i >> 5); + int i, bit, bitindex; + rdlight_t *rd; + vec3_t lightorigin; + if (!gl_flashblend.integer && r_dynamic.integer && ent->model && ent->model->brushq1.numleafs) + { + for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++) + { + bit = 1 << (i & 31); + bitindex = i >> 5; + Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin); + lightpvsbytes = 0; + if (r_vismarklights.integer && ent->model->brush.FatPVS) + lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs)); + R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.visleafs)); + } + } } /* @@ -445,16 +300,6 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu else VectorSet(ambientcolor, 1, 1, 1); - /* - if (leaf == NULL && cl.worldmodel != NULL) - leaf = cl.worldmodel->brushq1.PointInLeaf(cl.worldmodel, p); - if (!leaf || leaf->contents == CONTENTS_SOLID || !cl.worldmodel->brushq1.lightdata) - { - VectorSet(ambientcolor, 1, 1, 1); - return; - } - */ - // FIXME: this .lights related stuff needs to be ported into the Mod_Q1BSP code if (cl.worldmodel->brushq1.numlights) { @@ -469,7 +314,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu { 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, NULL) == 1) + if (f > 0 && CL_TraceLine(p, sl->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) == 1) { f *= d_lightstylevalue[sl->style] * (1.0f / 65536.0f); VectorMA(ambientcolor, f, sl->light, ambientcolor); @@ -489,7 +334,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu rd = r_dlight + i; VectorSubtract(p, rd->origin, v); f = DotProduct(v, v); - if (f < rd->cullradius2 && CL_TraceLine(p, rd->origin, NULL, NULL, 0, false, NULL) == 1) + if (f < rd->cullradius2 && CL_TraceLine(p, rd->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) == 1) { f = (1.0f / (f + LIGHTOFFSET)) - rd->subtract; VectorMA(ambientcolor, f, rd->light, ambientcolor); @@ -519,7 +364,7 @@ static nearlight_t nearlight[MAX_DLIGHTS]; int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, const entity_render_t *ent, float colorr, float colorg, float colorb, float colora, int worldcoords) { int i, j, maxnearlights; - float v[3], f, mscale, stylescale, intensity, ambientcolor[3]; + float v[3], f, mscale, stylescale, intensity, ambientcolor[3], tempdiffusenormal[3]; nearlight_t *nl; mlight_t *sl; rdlight_t *rd; @@ -540,7 +385,11 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co else { if (cl.worldmodel && cl.worldmodel->brush.LightPoint) - cl.worldmodel->brush.LightPoint(cl.worldmodel, ent->origin, ambient4f, diffusecolor, diffusenormal); + { + cl.worldmodel->brush.LightPoint(cl.worldmodel, ent->origin, ambient4f, diffusecolor, tempdiffusenormal); + Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, diffusenormal); + VectorNormalize(diffusenormal); + } else VectorSet(ambient4f, 1, 1, 1); } @@ -612,7 +461,7 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co VectorSubtract (v, rd->origin, v); if (DotProduct(v, v) < rd->cullradius2) { - if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, 0, false, NULL) != 1) + if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) != 1) continue; VectorSubtract (ent->origin, rd->origin, v); f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract); @@ -690,7 +539,9 @@ void R_LightModel_CalcVertexColors(const float *ambientcolor4f, const float *dif float color[4], v[3], dot, dist2, f, dnormal[3]; nearlight_t *nl; usediffuse = DotProduct(diffusecolor, diffusecolor) > 0; - VectorCopy(diffusenormal, dnormal); + // negate the diffuse normal to avoid the need to negate the + // dotproduct on each vertex + VectorNegate(diffusenormal, dnormal); if (usediffuse) VectorNormalize(dnormal); // directional shading code here @@ -749,7 +600,7 @@ void R_UpdateEntLights(entity_render_t *ent) ent->numentlights = 0; if (cl.worldmodel) for (i = 0, sl = cl.worldmodel->brushq1.lights;i < cl.worldmodel->brushq1.numlights && ent->numentlights < MAXENTLIGHTS;i++, sl++) - if (CL_TraceLine(ent->origin, sl->origin, NULL, NULL, 0, false, NULL) == 1) + if (CL_TraceLine(ent->origin, sl->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) == 1) ent->entlights[ent->numentlights++] = i; } ent->entlightsframe = r_framecount;