vary r_drawparticles_drawdistance and r_drawdecals_drawdistance for
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 25 Jan 2008 19:47:02 +0000 (19:47 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 25 Jan 2008 19:47:02 +0000 (19:47 +0000)
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
cl_particles.c
cl_screen.c
client.h
host.c
menu.c

index 336d288..6078183 100644 (file)
--- 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;
index 74925fe..e9c7202 100644 (file)
@@ -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
index 983b8d9..3c4ffd5 100644 (file)
@@ -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);
 }
index 245d590..4c44fee 100644 (file)
--- 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 6fd81f1..5e830ca 100644 (file)
--- 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 a48e89a..a4a3086 100644 (file)
--- 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;