- fixed: The frame timer for interpolating the renderer should always take its time from the actual beginning of the frame instead of checking the system timer in real time when rendering starts.

This fixes two issues:

* timer related texture animations are not being recreated multiple times if a scene renders multiple viewpoints (e.g. camera textures or portals.)
* interpolation is smoother when maps have a high think time of multiple milliseconds. A good map to see the difference would be ZDCMP2 which has a think time of 4-5 milliseconds. With the timer taken in real time after the thinkers have run and VSync on this resulted in alternating time slices of 11 and 21 ms between frame interpolations instead of an even 16 as should be done for smooth 60 fps because roughly every second frame was offset by those 5 ms.
This commit is contained in:
Christoph Oelckers 2017-07-20 14:20:50 +02:00
parent bc38f7f776
commit 03ed0656e1
7 changed files with 36 additions and 4 deletions

View file

@ -1017,7 +1017,8 @@ void D_DoomLoop ()
lasttic = gametic;
I_StartFrame ();
}
I_SetFrameTime();
// process one or more tics
if (singletics)
{

View file

@ -1948,6 +1948,7 @@ void TryRunTics (void)
C_Ticker ();
M_Ticker ();
I_GetTime (true);
I_SetFrameTime();
G_Ticker();
gametic++;

View file

@ -178,9 +178,17 @@ unsigned int I_FPSTime()
}
static uint32_t FrameTime;
void I_SetFrameTime()
{
FrameTime = I_MSTime();
}
double I_GetTimeFrac(uint32_t* ms)
{
const uint32_t now = I_MSTime();
const uint32_t now = FrameTime;
if (NULL != ms)
{

View file

@ -67,6 +67,7 @@ extern int (*I_WaitForTic) (int);
extern void (*I_FreezeTime) (bool frozen);
double I_GetTimeFrac (uint32_t *ms);
void I_SetFrameTime();
// Return a seed value for the RNG.
unsigned int I_MakeRNGSeed();

View file

@ -208,10 +208,18 @@ void I_SelectTimer()
}
}
static uint32_t FrameTime;
void I_SetFrameTime()
{
FrameTime = SDL_GetTicks();
}
// Returns the fractional amount of a tic passed since the most recent tic
double I_GetTimeFrac (uint32_t *ms)
{
uint32_t now = SDL_GetTicks ();
uint32_t now = FrameTime;
if (ms) *ms = TicStart + (1000 / TICRATE);
if (TicStart == 0)
{

View file

@ -484,10 +484,22 @@ static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw
// saved tic.
//
//==========================================================================
static uint32_t FrameTime;
void I_SetFrameTime()
{
FrameTime = timeGetTime();
}
double I_GetTimeFrac(uint32_t *ms)
{
DWORD now = timeGetTime();
//DWORD now = MAX<uint32_t>(FrameTime, TicStart);
DWORD now = FrameTime;
if (FrameTime < TicStart)
{
// Preliminary kept in to see if this can happen. Should be removed once confirmed ok.
Printf("Timer underflow!\n");
}
if (ms != NULL)
{
*ms = TicNext;

View file

@ -63,6 +63,7 @@ extern int (*I_WaitForTic) (int);
extern void (*I_FreezeTime) (bool frozen);
double I_GetTimeFrac (uint32_t *ms);
void I_SetFrameTime();
// Return a seed value for the RNG.
unsigned int I_MakeRNGSeed();