Page 1 of 1

Framerate-independent stair-step smoothing

Posted: Fri Feb 22, 2013 10:02 pm
by mh
Here's another one. The problem with stair-step smoothing is that it accumulates lots of tiny floats; run fast enough and precision errors build up. Here's a stab at fixing it. all changes to view.c, so declare these at the top:

Code: Select all

float	v_oldz, v_stepz;
float	v_steptime;
Now find the "smooth out stair step ups" block and replace with:

Code: Select all

	// smooth out stair step ups
	if (cl.onground && ent->origin[2] - v_stepz > 0)
	{
		v_stepz = v_oldz + (cl.time - v_steptime) * 80; // BJP Quake used 160 here

		if (v_stepz > ent->origin[2])
		{
			v_steptime = cl.time;
			v_stepz = v_oldz = ent->origin[2];
		}

		if (ent->origin[2] - v_stepz > 12)
		{
			v_steptime = cl.time;
			v_stepz = v_oldz = ent->origin[2] - 12;
		}

		r_refdef.vieworigin[2] += v_stepz - ent->origin[2];
		view->origin[2] += v_stepz - ent->origin[2];
	}
	else
	{
		v_oldz = v_stepz = ent->origin[2];
		v_steptime = cl.time;
	}
Finally add the following function and call it from somewhere in R_NewMap:

Code: Select all

void V_NewMap (void)
{
	v_oldz = v_stepz = 0;
	v_steptime = 0;
}
So, instead of accumulating lots of tiny deltas we're working off absolute differences with far lower precision loss.

Re: Framerate-independent stair-step smoothing

Posted: Wed Feb 27, 2013 5:38 am
by taniwha
v_stepz = v_oldz + (cl.time - v_steptime) * 80;
You might like to take a look at this article ("Stable algorithms also matter" section). It presents an alternate calculation for blend functions that guarantees the blend factor will never escape the 0..1 range, no matter how crappy time's precision has become. As far as I can tell, it just gracefully degrades to such that blend is always 1.

I've already implemented his int-time (64 bits, microseconds) and 4Gs offset suggestions (found an issue in the timedemo code: start time was stored as a float: ouch). I've only just pushed the changes because I had found a nasty bug with 128 dlight support while testing the time changes, then forgot about them.