From: divverent Date: Sat, 3 Dec 2011 12:06:45 +0000 (+0000) Subject: transform: make hysteresis one-sided, no behaviour change X-Git-Tag: xonotic-v0.6.0~102^2~28 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a3b143074957e3a4c4ddf46121cbd1d88acbb1d1;p=xonotic%2Fdarkplaces.git transform: make hysteresis one-sided, no behaviour change git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11591 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_screen.c b/cl_screen.c index a9a088c5..26a0d63a 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -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 60db8ba1..bd8334b6 100644 --- 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"};