]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
transform: make hysteresis one-sided, no behaviour change
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 3 Dec 2011 12:06:45 +0000 (12:06 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 3 Dec 2011 12:06:45 +0000 (12:06 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11591 d7cf8633-e32d-0410-b094-e92efae38249

cl_screen.c
host.c

index a9a088c5b22e163fe9b792ccb0817ba5a7bbaa7f..26a0d63a8d2041eadb38266bf9f70a5acc38d28d 100644 (file)
@@ -2228,49 +2228,54 @@ void CL_UpdateScreen(void)
                        double adjust;
                        double f;
                        double h;
+
+                       // fade lastdrawscreentime
                        r_refdef.lastdrawscreentime += (drawscreendelta - r_refdef.lastdrawscreentime) * cl_minfps_fade.value;
+
+                       // find actual and target frame times
                        actualframetime = r_refdef.lastdrawscreentime;
                        targetframetime = (1.0 / cl_minfps.value);
 
-                       // assume render time scales linearily / cl_minfps_qualitymultiply.value with quality...
-                       f = cl_updatescreen_quality / actualframetime * cl_minfps_qualitymultiply.value;
                        // we scale hysteresis by quality
                        h = cl_updatescreen_quality * cl_minfps_qualityhysteresis.value;
 
-                       targetframetime -= h / f; // this makes sure resulting fps is > minfps despite hysteresis
-
+                       // calculate adjustment assuming linearity
+                       f = cl_updatescreen_quality / actualframetime * cl_minfps_qualitymultiply.value;
                        adjust = (targetframetime - actualframetime) * f;
-                       if(adjust > h)
-                               adjust -= h;
-                       else if(adjust > -h)
-                               adjust = 0;
-                       else
-                               adjust += h;
+
+                       // one sided hysteresis
+                       if(adjust > 0)
+                               adjust = max(0, adjust - h);
 
                        // adjust > 0 if:
                        //   (targetframetime - actualframetime) * f > h
-                       //   (targetframetime - actualframetime) * (cl_updatescreen_quality / actualframetime * qualitymultiply) > h
-                       //   (1.0 / minfps - h / (quality / actualframetime * qualitymultiply) - actualframetime) * (quality / actualframetime * qualitymultiply) > h
-                       //   (1.0 / minfps - actualframetime) * (quality / actualframetime * qualitymultiply) > 2 * h
-                       //   actualframetime < quality qualitymultiply / (minfps quality qualitymultiply + 2 minfps h)
-                       //   actualframetime < 1.0 / minfps * (quality qualitymultiply) / (quality qualitymultiply + 2 h)
-                       //   actualframetime < 1.0 / minfps / (1 + 2 h / (quality qualitymultiply))
-                       //   actualframetime < 1.0 / minfps / (1 + 2 qualityhysteresis / qualitymultiply)
+                       //   ((1.0 / cl_minfps.value) - actualframetime) * (cl_updatescreen_quality / actualframetime * cl_minfps_qualitymultiply.value) > (cl_updatescreen_quality * cl_minfps_qualityhysteresis.value)
+                       //   ((1.0 / cl_minfps.value) - actualframetime) * (cl_minfps_qualitymultiply.value / actualframetime) > cl_minfps_qualityhysteresis.value
+                       //   (1.0 / cl_minfps.value) * (cl_minfps_qualitymultiply.value / actualframetime) - cl_minfps_qualitymultiply.value > cl_minfps_qualityhysteresis.value
+                       //   (1.0 / cl_minfps.value) * (cl_minfps_qualitymultiply.value / actualframetime) > cl_minfps_qualityhysteresis.value + cl_minfps_qualitymultiply.value
+                       //   (1.0 / cl_minfps.value) / actualframetime > (cl_minfps_qualityhysteresis.value + cl_minfps_qualitymultiply.value) / cl_minfps_qualitymultiply.value
+                       //   (1.0 / cl_minfps.value) / actualframetime > 1.0 + cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value
+                       //   cl_minfps.value * actualframetime < 1.0 / (1.0 + cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value)
+                       //   actualframetime < 1.0 / cl_minfps.value / (1.0 + cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value)
+                       //   actualfps > cl_minfps.value * (1.0 + cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value)
 
                        // adjust < 0 if:
-                       //   (targetframetime - actualframetime) * f < -h
-                       //   (targetframetime - actualframetime) * (cl_updatescreen_quality / actualframetime * qualitymultiply) < -h
-                       //   (1.0 / minfps - h / (quality / actualframetime * qualitymultiply) - actualframetime) * (quality / actualframetime * qualitymultiply) < -h
-                       //   (1.0 / minfps - actualframetime) * (quality / actualframetime * qualitymultiply) < 0
-                       //   actualframetime > 1.0 / minfps
+                       //   (targetframetime - actualframetime) * f < 0
+                       //   ((1.0 / cl_minfps.value) - actualframetime) * (cl_updatescreen_quality / actualframetime * cl_minfps_qualitymultiply.value) < 0
+                       //   ((1.0 / cl_minfps.value) - actualframetime) < 0
+                       //   -actualframetime) < -(1.0 / cl_minfps.value)
+                       //   actualfps < cl_minfps.value
 
                        /*
                        Con_Printf("adjust UP if fps > %f, adjust DOWN if fps < %f\n",
-                                       cl_minfps.value * (1.0 + 2.0 * cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value),
+                                       cl_minfps.value * (1.0 + cl_minfps_qualityhysteresis.value / cl_minfps_qualitymultiply.value),
                                        cl_minfps.value);
                        */
 
+                       // don't adjust too much at once
                        adjust = bound(-cl_minfps_qualitystepmax.value, adjust, cl_minfps_qualitystepmax.value);
+
+                       // adjust!
                        cl_updatescreen_quality += adjust;
                        cl_updatescreen_quality = bound(max(0.01, cl_minfps_qualitymin.value), cl_updatescreen_quality, cl_minfps_qualitymax.value);
                }
diff --git a/host.c b/host.c
index 60db8ba1b1fa896a144e3f4cd028430f350444a4..bd8334b612b5f5ef6899dbf314c58ae5a563f4c1 100644 (file)
--- a/host.c
+++ b/host.c
@@ -70,7 +70,7 @@ cvar_t cl_minfps_fade = {CVAR_SAVE, "cl_minfps_fade", "1", "how fast the quality
 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_qualitymultiply = {CVAR_SAVE, "cl_minfps_qualitymultiply", "0.2", "multiplier for quality changes in quality change per second render time (1 assumes linearity of quality and render time)"};
-cvar_t cl_minfps_qualityhysteresis = {CVAR_SAVE, "cl_minfps_qualityhysteresis", "0.025", "reduce all quality changes by this to reduce flickering"};
+cvar_t cl_minfps_qualityhysteresis = {CVAR_SAVE, "cl_minfps_qualityhysteresis", "0.05", "reduce all quality increments by this to reduce flickering"};
 cvar_t cl_minfps_qualitystepmax = {CVAR_SAVE, "cl_minfps_qualitystepmax", "0.1", "maximum quality change in a single frame"};
 cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "0", "maximum fps cap, 0 = unlimited, 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_maxfps_alwayssleep = {0, "cl_maxfps_alwayssleep","1", "gives up some processing time to other applications each frame, value in milliseconds, disabled if cl_maxfps is 0"};