X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=0d05ac1e4544a73ed4b4fcdfb8caebca3b638f0c;hb=bbb2827707bfbc2d2a7d3304473cafadffac5da5;hp=f388ce4a0c68f1445e1127fc6ddc47c001267f79;hpb=28f64beb60928fdcf2a8932a4971ce547fd98062;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index f388ce4a..0d05ac1e 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -337,6 +337,7 @@ cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel texture cvar_t r_shadow_bouncegrid = {CVAR_SAVE, "r_shadow_bouncegrid", "0", "perform particle tracing for indirect lighting (Global Illumination / radiosity) using a 3D texture covering the scene, only active on levels with realtime lights active (r_shadow_realtime_world is usually required for these)"}; cvar_t r_shadow_bouncegrid_blur = {CVAR_SAVE, "r_shadow_bouncegrid_blur", "1", "apply a 1-radius blur on bouncegrid to denoise it and deal with boundary issues with surfaces"}; cvar_t r_shadow_bouncegrid_bounceanglediffuse = {CVAR_SAVE, "r_shadow_bouncegrid_bounceanglediffuse", "0", "use random bounce direction rather than true reflection, makes some corner areas dark"}; +cvar_t r_shadow_bouncegrid_dynamic_bounceminimumintensity = { CVAR_SAVE, "r_shadow_bouncegrid_dynamic_bounceminimumintensity", "0.01", "stop bouncing once intensity drops below this fraction of the original particle color" }; cvar_t r_shadow_bouncegrid_dynamic_culllightpaths = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_culllightpaths", "1", "skip accumulating light in the bouncegrid texture where the light paths are out of view (dynamic mode only)"}; cvar_t r_shadow_bouncegrid_dynamic_dlightparticlemultiplier = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_dlightparticlemultiplier", "1", "if set to a high value like 16 this can make dlights look great, but 0 is recommended for performance reasons"}; cvar_t r_shadow_bouncegrid_dynamic_directionalshading = {CVAR_SAVE, "r_shadow_bouncegrid_dynamic_directionalshading", "0", "use diffuse shading rather than ambient, 3D texture becomes 8x as many pixels to hold the additional data"}; @@ -358,7 +359,9 @@ cvar_t r_shadow_bouncegrid_particlebounceintensity = {CVAR_SAVE, "r_shadow_bounc cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_particleintensity", "0.25", "brightness of particles contributing to bouncegrid texture"}; cvar_t r_shadow_bouncegrid_sortlightpaths = {CVAR_SAVE, "r_shadow_bouncegrid_sortlightpaths", "1", "sort light paths before accumulating them into the bouncegrid texture, this reduces cpu cache misses"}; cvar_t r_shadow_bouncegrid_lightpathsize = {CVAR_SAVE, "r_shadow_bouncegrid_lightpathsize", "1", "width of the light path for accumulation of light in the bouncegrid texture"}; +cvar_t r_shadow_bouncegrid_normalizevectors = { CVAR_SAVE, "r_shadow_bouncegrid_normalizevectors", "1", "normalize random vectors (otherwise their length can vary, which dims the lighting further from the light)" }; cvar_t r_shadow_bouncegrid_static = {CVAR_SAVE, "r_shadow_bouncegrid_static", "1", "use static radiosity solution (high quality) rather than dynamic (splotchy)"}; +cvar_t r_shadow_bouncegrid_static_bounceminimumintensity = { CVAR_SAVE, "r_shadow_bouncegrid_static_bounceminimumintensity", "0.01", "stop bouncing once intensity drops below this fraction of the original particle color" }; cvar_t r_shadow_bouncegrid_static_directionalshading = {CVAR_SAVE, "r_shadow_bouncegrid_static_directionalshading", "1", "whether to use directionalshading when in static mode"}; cvar_t r_shadow_bouncegrid_static_energyperphoton = {CVAR_SAVE, "r_shadow_bouncegrid_static_energyperphoton", "10000", "amount of light that one photon should represent in static mode"}; cvar_t r_shadow_bouncegrid_static_lightradiusscale = {CVAR_SAVE, "r_shadow_bouncegrid_static_lightradiusscale", "10", "particles stop at this fraction of light radius (can be more than 1) when in static mode"}; @@ -551,7 +554,6 @@ static void r_shadow_start(void) { // allocate vertex processing arrays memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state)); - r_shadow_bouncegrid_state.maxsplatpaths = 16384; r_shadow_attenuationgradienttexture = NULL; r_shadow_attenuation2dtexture = NULL; r_shadow_attenuation3dtexture = NULL; @@ -653,6 +655,13 @@ static void r_shadow_shutdown(void) if (r_shadow_scenelightlist) Mem_Free(r_shadow_scenelightlist); r_shadow_scenelightlist = NULL; + r_shadow_bouncegrid_state.highpixels = NULL; + if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; + if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; + if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; + if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; + if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; + r_shadow_bouncegrid_state.maxsplatpaths = 0; memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state)); r_shadow_attenuationgradienttexture = NULL; r_shadow_attenuation2dtexture = NULL; @@ -721,6 +730,13 @@ static void r_shadow_shutdown(void) static void r_shadow_newmap(void) { + r_shadow_bouncegrid_state.highpixels = NULL; + if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; + if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; + if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; + if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; + if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; + r_shadow_bouncegrid_state.maxsplatpaths = 0; if (r_shadow_bouncegrid_state.texture) R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; if (r_shadow_lightcorona) R_SkinFrame_MarkUsed(r_shadow_lightcorona); if (r_editlights_sprcursor) R_SkinFrame_MarkUsed(r_editlights_sprcursor); @@ -789,6 +805,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_bouncegrid); Cvar_RegisterVariable(&r_shadow_bouncegrid_blur); Cvar_RegisterVariable(&r_shadow_bouncegrid_bounceanglediffuse); + Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_bounceminimumintensity); Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_culllightpaths); Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_directionalshading); Cvar_RegisterVariable(&r_shadow_bouncegrid_dynamic_dlightparticlemultiplier); @@ -807,16 +824,18 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_bouncegrid_includedirectlighting); Cvar_RegisterVariable(&r_shadow_bouncegrid_intensity); Cvar_RegisterVariable(&r_shadow_bouncegrid_lightpathsize); + Cvar_RegisterVariable(&r_shadow_bouncegrid_normalizevectors); Cvar_RegisterVariable(&r_shadow_bouncegrid_particlebounceintensity); Cvar_RegisterVariable(&r_shadow_bouncegrid_particleintensity); Cvar_RegisterVariable(&r_shadow_bouncegrid_sortlightpaths); Cvar_RegisterVariable(&r_shadow_bouncegrid_static); - Cvar_RegisterVariable(&r_shadow_bouncegrid_static_spacing); + Cvar_RegisterVariable(&r_shadow_bouncegrid_static_bounceminimumintensity); Cvar_RegisterVariable(&r_shadow_bouncegrid_static_directionalshading); + Cvar_RegisterVariable(&r_shadow_bouncegrid_static_energyperphoton); Cvar_RegisterVariable(&r_shadow_bouncegrid_static_lightradiusscale); Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxbounce); Cvar_RegisterVariable(&r_shadow_bouncegrid_static_maxphotons); - Cvar_RegisterVariable(&r_shadow_bouncegrid_static_energyperphoton); + Cvar_RegisterVariable(&r_shadow_bouncegrid_static_spacing); Cvar_RegisterVariable(&r_coronas); Cvar_RegisterVariable(&r_coronas_occlusionsizescale); Cvar_RegisterVariable(&r_coronas_occlusionquery); @@ -2464,12 +2483,10 @@ static void R_Shadow_BounceGrid_AddSplatPath(vec3_t originalstart, vec3_t origin { // double the limit, this will persist from frame to frame so we don't // make the same mistake each time - r_shadow_bouncegrid_splatpath_t *newpaths; r_shadow_bouncegrid_state.maxsplatpaths *= 2; - newpaths = (r_shadow_bouncegrid_splatpath_t *)R_FrameData_Alloc(sizeof(r_shadow_bouncegrid_splatpath_t) * r_shadow_bouncegrid_state.maxsplatpaths); - if (r_shadow_bouncegrid_state.splatpaths) - memcpy(newpaths, r_shadow_bouncegrid_state.splatpaths, r_shadow_bouncegrid_state.numsplatpaths * sizeof(r_shadow_bouncegrid_splatpath_t)); - r_shadow_bouncegrid_state.splatpaths = newpaths; + if (r_shadow_bouncegrid_state.maxsplatpaths < 16384) + r_shadow_bouncegrid_state.maxsplatpaths = 16384; + r_shadow_bouncegrid_state.splatpaths = (r_shadow_bouncegrid_splatpath_t *)Mem_Realloc(r_main_mempool, r_shadow_bouncegrid_state.splatpaths, sizeof(r_shadow_bouncegrid_splatpath_t) * r_shadow_bouncegrid_state.maxsplatpaths); } // divide a series of splats along the length using the maximum axis @@ -2536,6 +2553,7 @@ static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t { qboolean s = r_shadow_bouncegrid_static.integer != 0; float spacing = s ? r_shadow_bouncegrid_static_spacing.value : r_shadow_bouncegrid_dynamic_spacing.value; + float bounceminimumintensity = s ? r_shadow_bouncegrid_static_bounceminimumintensity.value : r_shadow_bouncegrid_dynamic_bounceminimumintensity.value; // prevent any garbage in alignment padded areas as we'll be using memcmp memset(settings, 0, sizeof(*settings)); @@ -2553,13 +2571,15 @@ static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t settings->lightradiusscale = (s ? r_shadow_bouncegrid_static_lightradiusscale.value : r_shadow_bouncegrid_dynamic_lightradiusscale.value); settings->maxbounce = (s ? r_shadow_bouncegrid_static_maxbounce.integer : r_shadow_bouncegrid_dynamic_maxbounce.integer); settings->particlebounceintensity = r_shadow_bouncegrid_particlebounceintensity.value; - settings->particleintensity = r_shadow_bouncegrid_particleintensity.value * 16384.0f * (settings->directionalshading ? 4.0f : 1.0f) / (spacing * spacing); + settings->particleintensity = r_shadow_bouncegrid_particleintensity.value * (settings->directionalshading ? 4.0f : 1.0f) * 16384 / (spacing * spacing) / 262144.0f; settings->maxphotons = s ? r_shadow_bouncegrid_static_maxphotons.integer : r_shadow_bouncegrid_dynamic_maxphotons.integer; - settings->energyperphoton = s ? r_shadow_bouncegrid_static_energyperphoton.integer : r_shadow_bouncegrid_dynamic_energyperphoton.integer; + settings->energyperphoton = s ? r_shadow_bouncegrid_static_energyperphoton.value : r_shadow_bouncegrid_dynamic_energyperphoton.value; settings->spacing[0] = spacing; settings->spacing[1] = spacing; settings->spacing[2] = spacing; - settings->stablerandom = s ? 1 : r_shadow_bouncegrid_dynamic_stablerandom.integer; + settings->stablerandom = r_shadow_bouncegrid_dynamic_stablerandom.integer; + settings->bounceminimumintensity2 = bounceminimumintensity * bounceminimumintensity; + settings->normalizevectors = r_shadow_bouncegrid_normalizevectors.integer != 0; // bound the values for sanity settings->maxphotons = bound(1, settings->maxphotons, 25000000); @@ -2568,6 +2588,13 @@ static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t settings->spacing[0] = bound(1, settings->spacing[0], 512); settings->spacing[1] = bound(1, settings->spacing[1], 512); settings->spacing[2] = bound(1, settings->spacing[2], 512); + + // check if the ram requirements for blur would be excessive and disable it (increase lightpathsize to compensate) + if (spacing < 32 && settings->blur) + { + settings->blur = false; + settings->lightpathsize += 2; + } } static void R_Shadow_BounceGrid_UpdateSpacing(void) @@ -2680,11 +2707,14 @@ static void R_Shadow_BounceGrid_UpdateSpacing(void) numpixels = r_shadow_bouncegrid_state.pixelsperband*r_shadow_bouncegrid_state.pixelbands; if (r_shadow_bouncegrid_state.numpixels != numpixels) { - if (r_shadow_bouncegrid_state.texture) - { - R_FreeTexture(r_shadow_bouncegrid_state.texture); - r_shadow_bouncegrid_state.texture = NULL; - } + if (r_shadow_bouncegrid_state.texture) R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; + r_shadow_bouncegrid_state.highpixels = NULL; + if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; + if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; + if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; + if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; + if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; + r_shadow_bouncegrid_state.maxsplatpaths = 0; r_shadow_bouncegrid_state.numpixels = numpixels; } @@ -2700,17 +2730,16 @@ static void R_Shadow_BounceGrid_UpdateSpacing(void) Matrix4x4_FromArrayFloatD3D(&r_shadow_bouncegrid_state.matrix, m); } -#define MAXBOUNCEGRIDPARTICLESPERLIGHT 1048576 - // enumerate world rtlights and sum the overall amount of light in the world, // from that we can calculate a scaling factor to fairly distribute photons // to all the lights // // this modifies rtlight->photoncolor and rtlight->photons -static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *settings, unsigned int range, unsigned int range1, unsigned int range2, int flag, float *photonscaling) +static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *settings, unsigned int range, unsigned int range1, unsigned int range2, int flag) { float normalphotonscaling; - float maxphotonscaling; + float photonscaling; + float photonintensity; float photoncount = 0.0f; float lightintensity; float radius; @@ -2721,16 +2750,20 @@ static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *se unsigned int lightindex; dlight_t *light; rtlight_t *rtlight; + normalphotonscaling = 1.0f / max(0.0001f, settings->energyperphoton); for (lightindex = 0;lightindex < range2;lightindex++) { if (lightindex < range) { - light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); if (!light) continue; rtlight = &light->rtlight; - VectorClear(rtlight->photoncolor); - rtlight->photons = 0; + VectorClear(rtlight->bouncegrid_photoncolor); + rtlight->bouncegrid_photons = 0; + rtlight->bouncegrid_hits = 0; + rtlight->bouncegrid_traces = 0; + rtlight->bouncegrid_effectiveradius = 0; if (!(light->flags & flag)) continue; if (settings->staticmode) @@ -2739,12 +2772,17 @@ static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *se if (rtlight->style > 0 && r_shadow_bouncegrid.integer != 2) continue; } + else if (r_shadow_debuglight.integer >= 0 && (int)lightindex != r_shadow_debuglight.integer) + continue; } else { rtlight = r_refdef.scene.lights[lightindex - range]; - VectorClear(rtlight->photoncolor); - rtlight->photons = 0; + VectorClear(rtlight->bouncegrid_photoncolor); + rtlight->bouncegrid_photons = 0; + rtlight->bouncegrid_hits = 0; + rtlight->bouncegrid_traces = 0; + rtlight->bouncegrid_effectiveradius = 0; } // draw only visible lights (major speedup) radius = rtlight->radius * settings->lightradiusscale; @@ -2771,9 +2809,9 @@ static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *se if (rtlight->radius == 0.0f || VectorLength2(rtlight->color) == 0.0f) continue; w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1); - VectorScale(rtlight->color, w, rtlight->photoncolor); + VectorScale(rtlight->color, w, rtlight->bouncegrid_photoncolor); // skip lights that will emit no photons - if (!VectorLength2(rtlight->photoncolor)) + if (!VectorLength2(rtlight->bouncegrid_photoncolor)) continue; // shoot particles from this light // use a calculation for the number of particles that will not @@ -2784,20 +2822,41 @@ static void R_Shadow_BounceGrid_AssignPhotons(r_shadow_bouncegrid_settings_t *se lightintensity = VectorLength(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale); if (lightindex >= range) lightintensity *= settings->dlightparticlemultiplier; - rtlight->photons = bound(0.0f, lightintensity * s * s, MAXBOUNCEGRIDPARTICLESPERLIGHT); - photoncount += rtlight->photons; + rtlight->bouncegrid_photons = lightintensity * s * s * normalphotonscaling; + photoncount += rtlight->bouncegrid_photons; + VectorScale(rtlight->bouncegrid_photoncolor, settings->particleintensity * settings->energyperphoton, rtlight->bouncegrid_photoncolor); // if the lightstyle happens to be off right now, we can skip actually // firing the photons, but we did have to count them in the total. //if (VectorLength2(rtlight->photoncolor) == 0.0f) - // rtlight->photons = 0; + // rtlight->bouncegrid_photons = 0; } // the user provided an energyperphoton value which we try to use // if that results in too many photons to shoot this frame, then we cap it // which causes photons to appear/disappear from frame to frame, so we don't // like doing that in the typical case - normalphotonscaling = 1.0f / max(0.0001f, settings->energyperphoton); - maxphotonscaling = (float)settings->maxphotons / max(1, photoncount); - *photonscaling = min(normalphotonscaling, maxphotonscaling); + photonscaling = 1.0f; + photonintensity = 1.0f; + if (photoncount > settings->maxphotons) + { + photonscaling = settings->maxphotons / photoncount; + photonintensity = 1.0f / photonscaling; + } + + // modify the lights to reflect our computed scaling + for (lightindex = 0; lightindex < range2; lightindex++) + { + if (lightindex < range) + { + light = (dlight_t *)Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; + rtlight = &light->rtlight; + } + else + rtlight = r_refdef.scene.lights[lightindex - range]; + rtlight->bouncegrid_photons *= photonscaling; + VectorScale(rtlight->bouncegrid_photoncolor, photonintensity, rtlight->bouncegrid_photoncolor); + } } static int R_Shadow_BounceGrid_SplatPathCompare(const void *pa, const void *pb) @@ -2815,7 +2874,12 @@ static int R_Shadow_BounceGrid_SplatPathCompare(const void *pa, const void *pb) static void R_Shadow_BounceGrid_ClearPixels(void) { // clear the highpixels array we'll be accumulating into - r_shadow_bouncegrid_state.highpixels = (float *)R_FrameData_Alloc(r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); + if (r_shadow_bouncegrid_state.blurpixels[0] == NULL) + r_shadow_bouncegrid_state.blurpixels[0] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); + if (r_shadow_bouncegrid_state.settings.blur && r_shadow_bouncegrid_state.blurpixels[1] == NULL) + r_shadow_bouncegrid_state.blurpixels[1] = (float *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); + r_shadow_bouncegrid_state.highpixels_index = 0; + r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index]; memset(r_shadow_bouncegrid_state.highpixels, 0, r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); } @@ -2998,22 +3062,29 @@ static void R_Shadow_BounceGrid_BlurPixelsInDirection(const float *inpixels, flo static void R_Shadow_BounceGrid_BlurPixels(void) { - float *highpixels = r_shadow_bouncegrid_state.highpixels; - float *temppixels1 = (float *)R_FrameData_Alloc(r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); - float *temppixels2 = (float *)R_FrameData_Alloc(r_shadow_bouncegrid_state.numpixels * sizeof(float[4])); + float *pixels[4]; unsigned int resolution[3]; - if (!r_shadow_bouncegrid_blur.integer) + if (!r_shadow_bouncegrid_state.settings.blur) return; VectorCopy(r_shadow_bouncegrid_state.resolution, resolution); + pixels[0] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index]; + pixels[1] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1]; + pixels[2] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index]; + pixels[3] = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index ^ 1]; + // blur on X - R_Shadow_BounceGrid_BlurPixelsInDirection(highpixels, temppixels1, 4); + R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[0], pixels[1], 4); // blur on Y - R_Shadow_BounceGrid_BlurPixelsInDirection(temppixels1, temppixels2, resolution[0] * 4); + R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[1], pixels[2], resolution[0] * 4); // blur on Z - R_Shadow_BounceGrid_BlurPixelsInDirection(temppixels2, highpixels, resolution[0] * resolution[1] * 4); + R_Shadow_BounceGrid_BlurPixelsInDirection(pixels[2], pixels[3], resolution[0] * resolution[1] * 4); + + // toggle the state, highpixels now points to pixels[3] result + r_shadow_bouncegrid_state.highpixels_index ^= 1; + r_shadow_bouncegrid_state.highpixels = r_shadow_bouncegrid_state.blurpixels[r_shadow_bouncegrid_state.highpixels_index]; } static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void) @@ -3072,7 +3143,9 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void) switch (floatcolors) { case 0: - pixelsbgra8 = (unsigned char *)R_FrameData_Alloc(r_shadow_bouncegrid_state.numpixels * sizeof(unsigned char[4])); + if (r_shadow_bouncegrid_state.u8pixels == NULL) + r_shadow_bouncegrid_state.u8pixels = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned char[4])); + pixelsbgra8 = r_shadow_bouncegrid_state.u8pixels; for (pixelband = 0;pixelband < pixelbands;pixelband++) { if (pixelband == 1) @@ -3124,7 +3197,9 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void) r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, pixelsbgra8, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL); break; case 1: - pixelsrgba16f = (unsigned short *)R_FrameData_Alloc(r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4])); + if (r_shadow_bouncegrid_state.fp16pixels == NULL) + r_shadow_bouncegrid_state.fp16pixels = (unsigned short *)Mem_Alloc(r_main_mempool, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4])); + pixelsrgba16f = r_shadow_bouncegrid_state.fp16pixels; memset(pixelsrgba16f, 0, r_shadow_bouncegrid_state.numpixels * sizeof(unsigned short[4])); for (z = 1;z < resolution[2]-1;z++) { @@ -3186,19 +3261,23 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void) r_shadow_bouncegrid_state.lastupdatetime = realtime; } -static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t settings, unsigned int range, unsigned int range1, unsigned int range2, float photonscaling, int flag) +static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t settings, unsigned int range, unsigned int range1, unsigned int range2, int flag) { + vec3_t bouncerandom[10]; dlight_t *light; int bouncecount; int hitsupercontentsmask; + int skipsupercontentsmask; int maxbounce; int shootparticles; int shotparticles; + float bounceminimumintensity2; trace_t cliptrace; //trace_t cliptrace2; //trace_t cliptrace3; unsigned int lightindex; - unsigned int seed = (unsigned int)(realtime * 1000.0f); + unsigned int seed; + randomseed_t randomseed; vec3_t shotcolor; vec3_t baseshotcolor; vec3_t surfcolor; @@ -3208,16 +3287,27 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett vec_t radius; vec_t s; rtlight_t *rtlight; + union + { + unsigned int s[4]; + double d; + } + rseed; + + // compute a seed for the unstable random modes + memset(&rseed, 0, sizeof(rseed)); + rseed.d = realtime; + Math_RandomSeed_FromInts(&randomseed, rseed.s[0], rseed.s[1], rseed.s[2], rseed.s[3]); + seed = rseed.s[0] ^ rseed.s[1] ^ rseed.s[2] ^ rseed.s[3]; - // we'll need somewhere to store these r_shadow_bouncegrid_state.numsplatpaths = 0; - r_shadow_bouncegrid_state.splatpaths = (r_shadow_bouncegrid_splatpath_t *)R_FrameData_Alloc(sizeof(r_shadow_bouncegrid_splatpath_t) * r_shadow_bouncegrid_state.maxsplatpaths); // figure out what we want to interact with if (settings.hitmodels) hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;// | SUPERCONTENTS_LIQUIDSMASK; else hitsupercontentsmask = SUPERCONTENTS_SOLID;// | SUPERCONTENTS_LIQUIDSMASK; + skipsupercontentsmask = SUPERCONTENTS_SKY; // this allows the e1m5 sky shadow to work by ignoring the sky surfaces maxbounce = settings.maxbounce; for (lightindex = 0;lightindex < range2;lightindex++) @@ -3234,40 +3324,106 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett // note that this code used to keep track of residual photons and // distribute them evenly to achieve exactly a desired photon count, // but that caused unwanted flickering in dynamic mode - shootparticles = (int)floor(rtlight->photons * photonscaling); + shootparticles = (int)floor(rtlight->bouncegrid_photons); // skip if we won't be shooting any photons if (!shootparticles) continue; radius = rtlight->radius * settings.lightradiusscale; - s = settings.particleintensity / shootparticles; - VectorScale(rtlight->photoncolor, s, baseshotcolor); + //s = settings.particleintensity / shootparticles; + //VectorScale(rtlight->bouncegrid_photoncolor, s, baseshotcolor); + VectorCopy(rtlight->bouncegrid_photoncolor, baseshotcolor); + if (VectorLength2(baseshotcolor) <= 0.0f) + continue; r_refdef.stats[r_stat_bouncegrid_lights]++; r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles; + // we stop caring about bounces once the brightness goes below this fraction of the original intensity + bounceminimumintensity2 = VectorLength(baseshotcolor) * settings.bounceminimumintensity2; + + // for stablerandom we start the RNG with the position of the light + if (settings.stablerandom > 0) + { + union + { + unsigned int i[4]; + float f[4]; + } + u; + u.f[0] = rtlight->shadoworigin[0]; + u.f[1] = rtlight->shadoworigin[1]; + u.f[2] = rtlight->shadoworigin[2]; + u.f[3] = 1; + switch (settings.stablerandom) + { + default: + break; + case 1: + seed = u.i[0] ^ u.i[1] ^ u.i[2] ^ u.i[3]; + break; + case 2: + Math_RandomSeed_FromInts(&randomseed, u.i[0], u.i[1], u.i[2], u.i[3]); + break; + } + } + for (shotparticles = 0;shotparticles < shootparticles;shotparticles++) { - if (settings.stablerandom > 0) - seed = lightindex * 11937 + shotparticles; VectorCopy(baseshotcolor, shotcolor); VectorCopy(rtlight->shadoworigin, clipstart); - if (settings.stablerandom < 0) + switch (settings.stablerandom) + { + default: + case 0: VectorRandom(clipend); - else - VectorCheeseRandom(clipend); + if (settings.bounceanglediffuse) + { + // we want random to be stable, so we still have to do all the random we would have done + for (bouncecount = 0; bouncecount < maxbounce; bouncecount++) + VectorRandom(bouncerandom[bouncecount]); + } + break; + case -1: + case 1: + VectorCheeseRandom(seed, clipend); + if (settings.bounceanglediffuse) + { + // we want random to be stable, so we still have to do all the random we would have done + for (bouncecount = 0; bouncecount < maxbounce; bouncecount++) + VectorCheeseRandom(seed, bouncerandom[bouncecount]); + } + break; + case -2: + case 2: + VectorLehmerRandom(&randomseed, clipend); + if (settings.bounceanglediffuse) + { + // we want random to be stable, so we still have to do all the random we would have done + for (bouncecount = 0; bouncecount < maxbounce; bouncecount++) + VectorLehmerRandom(&randomseed, bouncerandom[bouncecount]); + } + break; + } + + // we want a uniform distribution spherically, not merely within the sphere + if (settings.normalizevectors) + VectorNormalize(clipend); + VectorMA(clipstart, radius, clipend, clipend); for (bouncecount = 0;;bouncecount++) { r_refdef.stats[r_stat_bouncegrid_traces]++; + rtlight->bouncegrid_traces++; //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask); //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask); - if (settings.staticmode) + if (settings.staticmode || settings.stablerandom <= 0) { // static mode fires a LOT of rays but none of them are identical, so they are not cached - cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true); + // non-stable random in dynamic mode also never reuses a direction, so there's no reason to cache it + cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, skipsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true); } else { // dynamic mode fires many rays and most will match the cache from the previous frame - cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask); + cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask, skipsupercontentsmask); } if (bouncecount > 0 || settings.includedirectlighting) { @@ -3275,9 +3431,13 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett VectorCopy(cliptrace.endpos, hitpos); R_Shadow_BounceGrid_AddSplatPath(clipstart, hitpos, shotcolor); } + s = VectorDistance(rtlight->shadoworigin, cliptrace.endpos); + if (rtlight->bouncegrid_effectiveradius < s) + rtlight->bouncegrid_effectiveradius = s; if (cliptrace.fraction >= 1.0f) break; r_refdef.stats[r_stat_bouncegrid_hits]++; + rtlight->bouncegrid_hits++; if (bouncecount >= maxbounce) break; // scale down shot color by bounce intensity and texture color (or 50% if no texture reported) @@ -3291,18 +3451,14 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett surfcolor[1] = min(surfcolor[1], 1.0f); surfcolor[2] = min(surfcolor[2], 1.0f); VectorMultiply(shotcolor, surfcolor, shotcolor); - if (VectorLength2(baseshotcolor) == 0.0f) + if (VectorLength2(shotcolor) <= bounceminimumintensity2) break; r_refdef.stats[r_stat_bouncegrid_bounces]++; if (settings.bounceanglediffuse) { // random direction, primarily along plane normal s = VectorDistance(cliptrace.endpos, clipend); - if (settings.stablerandom < 0) - VectorRandom(clipend); - else - VectorCheeseRandom(clipend); - VectorMA(cliptrace.plane.normal, 0.95f, clipend, clipend); + VectorMA(cliptrace.plane.normal, 0.95f, bouncerandom[bouncecount], clipend); VectorNormalize(clipend); VectorScale(clipend, s, clipend); } @@ -3329,7 +3485,6 @@ void R_Shadow_UpdateBounceGridTexture(void) unsigned int range; // number of world lights unsigned int range1; // number of dynamic lights (or zero if disabled) unsigned int range2; // range+range1 - float photonscaling; enable = R_Shadow_BounceGrid_CheckEnable(flag); @@ -3349,6 +3504,13 @@ void R_Shadow_UpdateBounceGridTexture(void) R_FreeTexture(r_shadow_bouncegrid_state.texture); r_shadow_bouncegrid_state.texture = NULL; } + r_shadow_bouncegrid_state.highpixels = NULL; + if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; + if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; + if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; + if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; + if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; + r_shadow_bouncegrid_state.maxsplatpaths = 0; r_shadow_bouncegrid_state.numpixels = 0; r_shadow_bouncegrid_state.directional = false; @@ -3374,10 +3536,10 @@ void R_Shadow_UpdateBounceGridTexture(void) range2 = range + range1; // calculate weighting factors for distributing photons among the lights - R_Shadow_BounceGrid_AssignPhotons(&settings, range, range1, range2, flag, &photonscaling); + R_Shadow_BounceGrid_AssignPhotons(&settings, range, range1, range2, flag); // trace the photons from lights and accumulate illumination - R_Shadow_BounceGrid_TracePhotons(settings, range, range1, range2, photonscaling, flag); + R_Shadow_BounceGrid_TracePhotons(settings, range, range1, range2, flag); // clear the texture R_Shadow_BounceGrid_ClearPixels(); @@ -3390,6 +3552,18 @@ void R_Shadow_UpdateBounceGridTexture(void) // convert the pixels to lower precision and upload the texture R_Shadow_BounceGrid_ConvertPixelsAndUpload(); + + // after we compute the static lighting we don't need to keep the highpixels array around + if (settings.staticmode) + { + r_shadow_bouncegrid_state.highpixels = NULL; + if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; + if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; + if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; + if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; + if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; + r_shadow_bouncegrid_state.maxsplatpaths = 0; + } } void R_Shadow_RenderMode_VisibleShadowVolumes(void) @@ -5782,7 +5956,7 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) else { // FIXME: these traces should scan all render entities instead of cl.world - if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) + if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) return; } VectorScale(rtlight->currentcolor, cscale, color); @@ -6115,7 +6289,7 @@ static void R_Shadow_SelectLightInView(void) if (rating >= 0.95) { rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp))); - if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f) + if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f) { bestrating = rating; best = light; @@ -6565,7 +6739,7 @@ static void R_Shadow_SetCursorLocationForView(void) vec3_t dest, endpos; trace_t trace; VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest); - trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true); + trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true); if (trace.fraction < 1) { dist = trace.fraction * r_editlights_cursordistance.value; @@ -7045,9 +7219,9 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void) // draw properties on screen if (!r_editlights_drawproperties.integer) return; - x = vid_conwidth.value - 240; + x = vid_conwidth.value - 320; y = 5; - DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0); + DrawQ_Pic(x-5, y-5, NULL, 250, 243, 0, 0, 0, 0.75, 0); lightnumber = -1; lightcount = 0; range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked @@ -7080,6 +7254,17 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void) dpsnprintf(temp, sizeof(temp), "Specular : %.2f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8; dpsnprintf(temp, sizeof(temp), "NormalMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8; dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8; + y += 8; + dpsnprintf(temp, sizeof(temp), "Render stats\n"); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "Current color: %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.currentcolor[0], r_shadow_selectedlight->rtlight.currentcolor[1], r_shadow_selectedlight->rtlight.currentcolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "Shadow size : %ix%ix6\n", r_shadow_selectedlight->rtlight.shadowmapatlassidesize, r_shadow_selectedlight->rtlight.shadowmapatlassidesize); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "World surfs : %i\n", r_shadow_selectedlight->rtlight.cached_numsurfaces); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "Shadow ents : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numshadowentities, r_shadow_selectedlight->rtlight.cached_numshadowentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "Lit ents : %i + %i noself\n", r_shadow_selectedlight->rtlight.cached_numlightentities, r_shadow_selectedlight->rtlight.cached_numlightentities_noselfshadow); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "BG photons : %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photons); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "BG radius : %.0f\n", r_shadow_selectedlight->rtlight.bouncegrid_effectiveradius); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "BG color : %.3f %.3f %.3f\n", r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[0], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[1], r_shadow_selectedlight->rtlight.bouncegrid_photoncolor[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; + dpsnprintf(temp, sizeof(temp), "BG stats : %i traces %i hits\n", r_shadow_selectedlight->rtlight.bouncegrid_traces, r_shadow_selectedlight->rtlight.bouncegrid_hits); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT); y += 8; } static void R_Shadow_EditLights_ToggleShadow_f(void) @@ -7353,7 +7538,7 @@ void R_LightPoint(float *color, const vec3_t p, const int flags) if (f <= 0) continue; // todo: add to both ambient and diffuse - if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) VectorMA(color, f, light->currentcolor, color); } } @@ -7374,7 +7559,7 @@ void R_LightPoint(float *color, const vec3_t p, const int flags) if (f <= 0) continue; // todo: add to both ambient and diffuse - if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) VectorMA(color, f, light->color, color); } } @@ -7458,7 +7643,7 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value; if (intensity <= 0.0f) continue; - if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) + if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; // scale down intensity to add to both ambient and diffuse //intensity *= 0.5f; @@ -7491,7 +7676,7 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value; if (intensity <= 0.0f) continue; - if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) + if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; // scale down intensity to add to both ambient and diffuse //intensity *= 0.5f;