From ac5533c5e5a5ad2e2edfae17c596faf29692aa06 Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 25 Jan 2008 19:47:02 +0000 Subject: [PATCH] vary r_drawparticles_drawdistance and r_drawdecals_drawdistance for quality limiting according to FPS, instead of skipping particles, this looks much better (but doesn't help FPS as much) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8011 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 4 ++-- cl_particles.c | 22 ++++++---------------- cl_screen.c | 22 +++++++++++----------- client.h | 7 ++----- host.c | 12 +++++++----- menu.c | 8 ++++---- 6 files changed, 32 insertions(+), 43 deletions(-) diff --git a/cl_main.c b/cl_main.c index 336d2883..6078183b 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1753,7 +1753,7 @@ void CL_UpdateWorld(void) r_refdef.scene.numentities = 0; r_refdef.scene.numlights = 0; r_refdef.view.matrix = identitymatrix; - r_refdef.view.qualityreduction = 0; + r_refdef.view.quality = 1; cl.num_brushmodel_entities = 0; @@ -1854,7 +1854,7 @@ static void CL_TimeRefresh_f (void) for (i = 0;i < 128;i++) { Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], 0, i / 128.0 * 360.0, 0, 1); - r_refdef.view.qualityreduction = 0; + r_refdef.view.quality = 1; CL_UpdateScreen(); } timedelta = Sys_DoubleTime() - timestart; diff --git a/cl_particles.c b/cl_particles.c index 74925fef..e9c72026 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2001,10 +2001,7 @@ void R_DrawDecals (void) decal_t *decal; float frametime; float decalfade; - // used as if (i & qualitymask) to skip some less important particles - // according to cl_minfps - int qualitymask = (1 << r_refdef.view.qualityreduction) - 1; - float drawdist2 = r_drawdecals_drawdistance.value * r_drawdecals_drawdistance.value; + float drawdist2; frametime = bound(0, cl.time - cl.decals_updatetime, 1); cl.decals_updatetime += frametime; @@ -2014,6 +2011,8 @@ void R_DrawDecals (void) return; decalfade = frametime * 256 / cl_decals_fadetime.value; + drawdist2 = r_drawdecals_drawdistance.value * r_refdef.view.quality; + drawdist2 = drawdist2*drawdist2; for (i = 0, decal = cl.decals;i < cl.num_decals;i++, decal++) { @@ -2038,10 +2037,6 @@ void R_DrawDecals (void) goto killdecal; } - // skip some of the less important decals according to cl_minfps - if (i & qualitymask) - continue; - if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size)) R_MeshQueue_AddTransparent(decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL); continue; @@ -2263,13 +2258,10 @@ void R_DrawParticles (void) float minparticledist; particle_t *p; float gravity, dvel, decalfade, frametime, f, dist, oldorg[3]; - float drawdist2 = r_drawparticles_drawdistance.value * r_drawparticles_drawdistance.value; + float drawdist2; int hitent; trace_t trace; qboolean update; - // used as if (i & qualitymask) to skip some less important particles - // according to cl_minfps - int qualitymask = (1 << r_refdef.view.qualityreduction) - 1; frametime = bound(0, cl.time - cl.particles_updatetime, 1); cl.particles_updatetime += frametime; @@ -2283,6 +2275,8 @@ void R_DrawParticles (void) dvel = 1+4*frametime; decalfade = frametime * 255 / cl_decals_fadetime.value; update = frametime > 0; + drawdist2 = r_drawparticles_drawdistance.value * r_refdef.view.quality; + drawdist2 = drawdist2*drawdist2; for (i = 0, p = cl.particles;i < cl.num_particles;i++, p++) { @@ -2420,10 +2414,6 @@ void R_DrawParticles (void) else if (p->delayedspawn) continue; - // skip some of the less important particles according to cl_minfps - if ((i & qualitymask) && p->qualityreduction) - continue; - // don't render particles too close to the view (they chew fillrate) // also don't render particles behind the view (useless) // further checks to cull to the frustum would be too slow here diff --git a/cl_screen.c b/cl_screen.c index 983b8d9c..3c4ffd56 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -698,7 +698,7 @@ void R_TimeReport_EndFrame(void) sprintf(string + strlen(string), "Location: %s\n", loc->name); sprintf(string + strlen(string), "%3i renders org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_refdef.stats.renders, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2]); sprintf(string + strlen(string), "%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n", r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles); - sprintf(string + strlen(string), "%5i leafs%5i portals%6i/%6i particles%6i/%6i decals %3i%% quality\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, cl.num_particles, r_refdef.stats.decals, cl.num_decals, 100 / (1 << r_refdef.view.qualityreduction)); + sprintf(string + strlen(string), "%5i leafs%5i portals%6i/%6i particles%6i/%6i decals %3i%% quality\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, cl.num_particles, r_refdef.stats.decals, cl.num_decals, (int)(100 * r_refdef.view.quality)); sprintf(string + strlen(string), "%7i lightmap updates (%7i pixels)\n", r_refdef.stats.lightmapupdates, r_refdef.stats.lightmapupdatepixels); sprintf(string + strlen(string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles); if (r_refdef.stats.bloom) @@ -1731,7 +1731,7 @@ static void R_Envmap_f (void) { sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name); Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1); - r_refdef.view.qualityreduction = 0; + r_refdef.view.quality = 1; r_refdef.view.clear = true; R_Mesh_Start(); R_RenderView(); @@ -2094,11 +2094,12 @@ void SCR_UpdateLoadingScreen (qboolean clear) } extern cvar_t cl_minfps; -extern cvar_t cl_minfps_logbase; extern cvar_t cl_minfps_fade; -extern cvar_t cl_minfps_maxqualityreduction; +extern cvar_t cl_minfps_qualitymax; +extern cvar_t cl_minfps_qualitymin; +extern cvar_t cl_minfps_qualityscale; static double cl_updatescreen_rendertime = 0; -static double cl_updatescreen_qualityreduction = 0; +static double cl_updatescreen_quality = 1; void CL_UpdateScreen(void) { double rendertime1; @@ -2169,7 +2170,7 @@ void CL_UpdateScreen(void) qglClearColor(0,0,0,0);CHECKGLERROR R_ClearScreen(false); r_refdef.view.clear = false; - r_refdef.view.qualityreduction = (int)floor(cl_updatescreen_qualityreduction + 0.5); + r_refdef.view.quality = bound(cl_minfps_qualitymin.value, cl_updatescreen_quality * cl_minfps_qualityscale.value, cl_minfps_qualitymax.value); if(scr_stipple.integer) { @@ -2242,12 +2243,11 @@ void CL_UpdateScreen(void) // quality adjustment according to render time qglFlush(); - cl_updatescreen_rendertime += ((Sys_DoubleTime() - rendertime1) - cl_updatescreen_rendertime) * bound(0.01, cl_minfps_fade.value, 1); - if (cl_minfps.value > 0 && !cls.timedemo && (!cls.capturevideo.active || !cls.capturevideo.realtime)) - cl_updatescreen_qualityreduction = invpow(cl_minfps_logbase.value, cl_minfps.value * cl_updatescreen_rendertime); + cl_updatescreen_rendertime += ((Sys_DoubleTime() - rendertime1) - cl_updatescreen_rendertime) * bound(0, cl_minfps_fade.value, 1); + if (cl_minfps.value > 0 && cl_updatescreen_rendertime > 0 && !cls.timedemo && (!cls.capturevideo.active || !cls.capturevideo.realtime)) + cl_updatescreen_quality = 1 / (cl_updatescreen_rendertime * cl_minfps.value); else - cl_updatescreen_qualityreduction = 0; - cl_updatescreen_qualityreduction = bound(0, cl_updatescreen_qualityreduction, bound(0, cl_minfps_maxqualityreduction.value, 30)); + cl_updatescreen_quality = 1; VID_Finish(true); } diff --git a/client.h b/client.h index 245d590e..4c44fee6 100644 --- a/client.h +++ b/client.h @@ -1410,11 +1410,8 @@ typedef struct r_refdef_view_s int cullface_front; int cullface_back; - // reduces render quality: - // 0 = full quality - // 1 = skip every other particle and some lights - // 2 = skip 75% of particles and some lights - int qualityreduction; + // render quality (0 to 1) - affects r_drawparticles_drawdistance and others + float quality; } r_refdef_view_t; diff --git a/host.c b/host.c index 6fd81f1f..5e830cac 100644 --- a/host.c +++ b/host.c @@ -60,9 +60,10 @@ cvar_t host_framerate = {0, "host_framerate","0", "locks frame timing to this va // shows time used by certain subsystems cvar_t host_speeds = {0, "host_speeds","0", "reports how much time is used in server/graphics/sound"}; cvar_t cl_minfps = {CVAR_SAVE, "cl_minfps", "40", "minimum fps target - while the rendering performance is below this, it will drift toward lower quality"}; -cvar_t cl_minfps_logbase = {CVAR_SAVE, "cl_minfps_logbase", "1.2", "base for log() function in calculating quality reduction, should be in the range 1.1 to 2.0"}; -cvar_t cl_minfps_fade = {CVAR_SAVE, "cl_minfps_fade", "0.2", "how fast the quality reduction adapts to varying framerate"}; -cvar_t cl_minfps_maxqualityreduction = {CVAR_SAVE, "cl_minfps_maxqualityreduction", "2", "how much particle quality can be reduced (as a power of 2) when framerate is staying below cl_minfps, 0 = no reduction, 1 = 50% quality, 2 = 25% quality, 3 = 12.5% quality, ..."}; +cvar_t cl_minfps_fade = {CVAR_SAVE, "cl_minfps_fade", "0.2", "how fast the quality adapts to varying framerate"}; +cvar_t cl_minfps_qualitymax = {CVAR_SAVE, "cl_minfps_qualitymax", "1", "highest allowed drawdistance multiplier"}; +cvar_t cl_minfps_qualitymin = {CVAR_SAVE, "cl_minfps_qualitymin", "0.25", "lowest allowed drawdistance multiplier"}; +cvar_t cl_minfps_qualityscale = {CVAR_SAVE, "cl_minfps_qualityscale", "0.5", "multiplier for quality"}; cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "1000000", "maximum fps cap, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"}; cvar_t cl_maxidlefps = {CVAR_SAVE, "cl_maxidlefps", "20", "maximum fps cap when the game is not the active window (makes cpu time available to other programs"}; @@ -206,9 +207,10 @@ static void Host_InitLocal (void) Cvar_RegisterVariable (&host_framerate); Cvar_RegisterVariable (&host_speeds); Cvar_RegisterVariable (&cl_minfps); - Cvar_RegisterVariable (&cl_minfps_logbase); Cvar_RegisterVariable (&cl_minfps_fade); - Cvar_RegisterVariable (&cl_minfps_maxqualityreduction); + Cvar_RegisterVariable (&cl_minfps_qualitymax); + Cvar_RegisterVariable (&cl_minfps_qualitymin); + Cvar_RegisterVariable (&cl_minfps_qualityscale); Cvar_RegisterVariable (&cl_maxfps); Cvar_RegisterVariable (&cl_maxidlefps); diff --git a/menu.c b/menu.c index a48e89aa..a4a3086b 100644 --- a/menu.c +++ b/menu.c @@ -5073,7 +5073,7 @@ void MP_Draw (void) // declarations that are needed right now extern r_refdef_scene_t menu_scene; - int oldqualityreduction; + float oldquality; static r_refdef_scene_t clientscene; clientscene = r_refdef.scene; r_refdef.scene = menu_scene; @@ -5082,8 +5082,8 @@ void MP_Draw (void) r_refdef.scene.numtempentities = 0; // menu scenes do not use reduced rendering quality - oldqualityreduction = r_refdef.view.qualityreduction; - r_refdef.view.qualityreduction = 0; + oldquality = r_refdef.view.quality; + r_refdef.view.quality = 1; PRVM_Begin; PRVM_SetProg(PRVM_MENUPROG); @@ -5094,7 +5094,7 @@ void MP_Draw (void) PRVM_End; - r_refdef.view.qualityreduction = oldqualityreduction; + r_refdef.view.quality = oldquality; menu_scene = r_refdef.scene; r_refdef.scene = clientscene; -- 2.39.2