From b7d92f696edebeb716e32e2179894dea483cb3ac Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 27 Nov 2016 22:20:28 +0000 Subject: [PATCH] Significant rework of bouncegrid photon distribution and coloring. r_editlights mode now shows render stats in the overlay. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12300 d7cf8633-e32d-0410-b094-e92efae38249 --- client.h | 7 +++- r_shadow.c | 118 +++++++++++++++++++++++++++++++++++++++-------------- r_shadow.h | 1 + 3 files changed, 93 insertions(+), 33 deletions(-) diff --git a/client.h b/client.h index 4230c6a8..aae1c868 100644 --- a/client.h +++ b/client.h @@ -395,8 +395,11 @@ typedef struct rtlight_s rtlight_particle_t *particlecache_particles; /// bouncegrid light info - float photoncolor[3]; - float photons; + float bouncegrid_photoncolor[3]; + float bouncegrid_photons; + int bouncegrid_hits; + int bouncegrid_traces; + float bouncegrid_effectiveradius; } rtlight_t; diff --git a/r_shadow.c b/r_shadow.c index e888fc01..caef494e 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"}; @@ -359,6 +360,7 @@ cvar_t r_shadow_bouncegrid_particleintensity = {CVAR_SAVE, "r_shadow_bouncegrid_ 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_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"}; @@ -802,6 +804,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); @@ -824,12 +827,13 @@ void R_Shadow_Init(void) 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); @@ -2547,6 +2551,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)); @@ -2564,13 +2569,14 @@ 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->bounceminimumintensity2 = bounceminimumintensity * bounceminimumintensity; // bound the values for sanity settings->maxphotons = bound(1, settings->maxphotons, 25000000); @@ -2721,17 +2727,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; @@ -2742,16 +2747,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) @@ -2760,12 +2769,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; @@ -2792,9 +2806,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 @@ -2805,20 +2819,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) @@ -3223,7 +3258,7 @@ 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; @@ -3233,6 +3268,7 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett int maxbounce; int shootparticles; int shotparticles; + float bounceminimumintensity2; trace_t cliptrace; //trace_t cliptrace2; //trace_t cliptrace3; @@ -3275,15 +3311,20 @@ 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; switch (settings.stablerandom) { default: @@ -3340,6 +3381,7 @@ static void R_Shadow_BounceGrid_TracePhotons(r_shadow_bouncegrid_settings_t sett 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 || settings.stablerandom <= 0) @@ -3359,9 +3401,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) @@ -3375,7 +3421,7 @@ 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) @@ -3409,7 +3455,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); @@ -3461,10 +3506,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(); @@ -7144,9 +7189,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 @@ -7179,6 +7224,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) diff --git a/r_shadow.h b/r_shadow.h index f59edaa7..10f8e1e0 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -57,6 +57,7 @@ typedef struct r_shadow_bouncegrid_settings_s float energyperphoton; float spacing[3]; int stablerandom; + float bounceminimumintensity2; } r_shadow_bouncegrid_settings_t; -- 2.39.2