From 917a7a2674fe6271cb1356f2e148b8445b8d0675 Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 27 Nov 2009 10:29:15 +0000 Subject: [PATCH] more work on mod_generatelightmaps: migrated light sampling code from r_shadow.c to model_shared.c git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9521 d7cf8633-e32d-0410-b094-e92efae38249 --- model_shared.c | 130 ++++++++++++++++++++++++++++++++++++++++++++----- r_shadow.c | 81 ++++++------------------------ 2 files changed, 132 insertions(+), 79 deletions(-) diff --git a/model_shared.c b/model_shared.c index 701a560a..3c011c71 100644 --- a/model_shared.c +++ b/model_shared.c @@ -3046,20 +3046,134 @@ typedef struct lightmaptriangle_s } lightmaptriangle_t; +typedef struct lightmaplight_s +{ + float origin[3]; + float radius; + float iradius; + float radius2; + float color[3]; +} +lightmaplight_t; + lightmaptriangle_t *mod_generatelightmaps_lightmaptriangles; #define MAX_LIGHTMAPSAMPLES 64 static int mod_generatelightmaps_numoffsets[3]; static float mod_generatelightmaps_offsets[3][MAX_LIGHTMAPSAMPLES][3]; -extern void R_SampleRTLights(const float *pos, float *sample, int numoffsets, const float *offsets); +static int mod_generatelightmaps_numlights; +static lightmaplight_t *mod_generatelightmaps_lightinfo; + +extern int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color); +static void Mod_GenerateLightmaps_CreateLights(dp_model_t *model) +{ + int index; + int result; + lightmaplight_t *lightinfo; + float origin[3]; + float radius; + float color[3]; + mod_generatelightmaps_numlights = 0; + for (index = 0;;index++) + { + result = R_Shadow_GetRTLightInfo(index, origin, &radius, color); + if (result < 0) + break; + if (result > 0) + mod_generatelightmaps_numlights++; + } + if (mod_generatelightmaps_numlights > 0) + { + mod_generatelightmaps_lightinfo = Mem_Alloc(tempmempool, mod_generatelightmaps_numlights * sizeof(*mod_generatelightmaps_lightinfo)); + lightinfo = mod_generatelightmaps_lightinfo; + for (index = 0;;index++) + { + result = R_Shadow_GetRTLightInfo(index, lightinfo->origin, &lightinfo->radius, lightinfo->color); + if (result < 0) + break; + if (result > 0) + lightinfo++; + } + } + for (index = 0, lightinfo = mod_generatelightmaps_lightinfo;index < mod_generatelightmaps_numlights;index++, lightinfo++) + { + lightinfo->iradius = 1.0f / lightinfo->radius; + lightinfo->radius2 = lightinfo->radius * lightinfo->radius; + // TODO: compute svbsp + } +} +static void Mod_GenerateLightmaps_DestroyLights(dp_model_t *model) +{ + if (mod_generatelightmaps_lightinfo) + Mem_Free(mod_generatelightmaps_lightinfo); + mod_generatelightmaps_lightinfo = NULL; + mod_generatelightmaps_numlights = 0; +} + +extern cvar_t r_shadow_lightattenuationdividebias; +extern cvar_t r_shadow_lightattenuationlinearscale; static void Mod_GenerateLightmaps_SamplePoint(const float *pos, float *sample, int numoffsets, const float *offsets) { int i; + float relativepoint[3]; + float color[3]; + float offsetpos[3]; + float dist; + float dist2; + float intensity; + trace_t trace; + int offsetindex; + int hits; + int tests; + const lightmaplight_t *lightinfo; for (i = 0;i < 5*3;i++) sample[i] = 0.0f; - R_SampleRTLights(pos, sample, numoffsets, offsets); + for (i = 0, lightinfo = mod_generatelightmaps_lightinfo;i < mod_generatelightmaps_numlights;i++, lightinfo++) + { + //R_SampleRTLights(pos, sample, numoffsets, offsets); + VectorSubtract(lightinfo->origin, pos, relativepoint); + dist2 = VectorLength2(relativepoint); + if (dist2 >= lightinfo->radius2) + continue; + dist = sqrt(dist2) * lightinfo->iradius; + intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0; + if (intensity <= 0) + continue; + if (cl.worldmodel && cl.worldmodel->TraceLine && numoffsets > 0) + { + hits = 0; + tests = 0; + for (offsetindex = 0;offsetindex < numoffsets;offsetindex++) + { + // test line of sight through the collision system (slow) + VectorAdd(pos, offsets + 3*offsetindex, offsetpos); + cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, pos, offsetpos, SUPERCONTENTS_VISBLOCKERMASK); + // don't count samples that start in solid + if (trace.startsolid || trace.fraction < 1) + continue; + tests++; + cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, offsetpos, lightinfo->origin, SUPERCONTENTS_VISBLOCKERMASK); + if (trace.fraction == 1) + hits++; + } + if (!hits) + continue; + // scale intensity according to how many rays succeeded + intensity *= (float)hits / tests; + } + // scale down intensity to add to both ambient and diffuse + intensity *= 0.5f; + VectorNormalize(relativepoint); + VectorScale(lightinfo->color, intensity, color); + VectorMA(sample , 1.0f , color, sample ); + VectorMA(sample + 3, relativepoint[0], color, sample + 3); + VectorMA(sample + 6, relativepoint[1], color, sample + 6); + VectorMA(sample + 9, relativepoint[2], color, sample + 9); + intensity *= VectorLength(color); + VectorMA(sample + 12, intensity, relativepoint, sample + 12); + } } static void Mod_GenerateLightmaps_LightmapSample(const float *pos, const float *normal, unsigned char *lm_bgr, unsigned char *lm_dir) @@ -3147,14 +3261,6 @@ static void Mod_GenerateLightmaps_InitSampleOffsets(dp_model_t *model) } } -static void Mod_GenerateLightmaps_CreateLights(dp_model_t *model) -{ -} - -static void Mod_GenerateLightmaps_DestroyLights(dp_model_t *model) -{ -} - static void Mod_GenerateLightmaps_DestroyLightmaps(dp_model_t *model) { msurface_t *surface; @@ -3524,8 +3630,8 @@ static void Mod_GenerateLightmaps_CreateLightmaps(dp_model_t *model) pixeloffset = ((triangle->lightmapindex * lm_texturesize + y + triangle->lmoffset[1]) * lm_texturesize + triangle->lmoffset[0]) * 4; for (x = 0;x < triangle->lmsize[0];x++, pixeloffset += 4) { - samplecenter[axis1] = x*lmiscale[0] + triangle->lmbase[0]; - samplecenter[axis2] = y*lmiscale[1] + triangle->lmbase[1]; + samplecenter[axis1] = (x+0.5f)*lmiscale[0] + triangle->lmbase[0]; + samplecenter[axis2] = (y+0.5f)*lmiscale[1] + triangle->lmbase[1]; samplecenter[axis] = samplecenter[axis1]*slopex + samplecenter[axis2]*slopey + slopebase; VectorMA(samplecenter, 0.125f, samplenormal, samplecenter); Mod_GenerateLightmaps_LightmapSample(samplecenter, samplenormal, lightmappixels + pixeloffset, deluxemappixels + pixeloffset); diff --git a/r_shadow.c b/r_shadow.c index 341009de..d9a4933e 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -5098,77 +5098,24 @@ void R_Shadow_DrawLightSprites(void) R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); } -void R_SampleRTLights(const float *pos, float *sample, int numoffsets, const float *offsets) +int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color) { - int flag; - size_t lightindex; + unsigned int range; dlight_t *light; rtlight_t *rtlight; - size_t range; - vec3_t relativepoint; - vec3_t localpoint; - vec3_t color; - vec3_t offsetpos; - vec_t dist; - vec_t intensity; - trace_t trace; - int offsetindex; - int hits; - int tests; - flag = LIGHTFLAG_REALTIMEMODE; range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); - for (lightindex = 0;lightindex < range;lightindex++) - { - light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); - if (!light) - continue; - rtlight = &light->rtlight; - if (!(rtlight->flags & flag)) - continue; - VectorSubtract(rtlight->shadoworigin, pos, relativepoint); - // early out - if (VectorLength2(relativepoint) >= rtlight->radius*rtlight->radius) - continue; - Matrix4x4_Transform(&rtlight->matrix_worldtolight, pos, localpoint); - dist = VectorLength(localpoint); - intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0; - if (intensity <= 0) - continue; - if (cl.worldmodel && cl.worldmodel->TraceLine && numoffsets > 0) - { - hits = 0; - tests = 0; - for (offsetindex = 0;offsetindex < numoffsets;offsetindex++) - { - // test line of sight through the collision system (slow) - VectorAdd(pos, offsets + 3*offsetindex, offsetpos); - cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, pos, offsetpos, SUPERCONTENTS_VISBLOCKERMASK); - if (trace.startsolid || trace.fraction < 1) - continue; - cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, offsetpos, rtlight->shadoworigin, SUPERCONTENTS_VISBLOCKERMASK); - // don't count samples that start in solid - if (trace.startsolid) - continue; - tests++; - if (trace.fraction == 1) - hits++; - } - if (!hits) - continue; - // scale intensity according to how many rays succeeded - intensity *= (float)hits / tests; - } - // scale down intensity to add to both ambient and diffuse - intensity *= 0.5f; - VectorNormalize(relativepoint); - VectorScale(rtlight->color, intensity, color); - VectorMA(sample , 1.0f , color, sample ); - VectorMA(sample + 3, relativepoint[0], color, sample + 3); - VectorMA(sample + 6, relativepoint[1], color, sample + 6); - VectorMA(sample + 9, relativepoint[2], color, sample + 9); - intensity *= VectorLength(color); - VectorMA(sample + 12, intensity, relativepoint, sample + 12); - } + if (lightindex >= range) + return -1; + light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + return 0; + rtlight = &light->rtlight; + //if (!(rtlight->flags & flag)) + // return 0; + VectorCopy(rtlight->shadoworigin, origin); + *radius = rtlight->radius; + VectorCopy(rtlight->color, color); + return 1; } void R_Shadow_SelectLightInView(void) -- 2.39.2