Skip to content

Commit

Permalink
- fixed: The frame timer for interpolating the renderer should always…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
coelckers committed Jul 20, 2017
1 parent bc38f7f commit 03ed065
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/d_main.cpp
Expand Up @@ -1017,7 +1017,8 @@ void D_DoomLoop ()
lasttic = gametic;
I_StartFrame ();
}

I_SetFrameTime();

// process one or more tics
if (singletics)
{
Expand Down
1 change: 1 addition & 0 deletions src/d_net.cpp
Expand Up @@ -1948,6 +1948,7 @@ void TryRunTics (void)
C_Ticker ();
M_Ticker ();
I_GetTime (true);
I_SetFrameTime();
G_Ticker();
gametic++;

Expand Down
10 changes: 9 additions & 1 deletion src/posix/cocoa/i_timer.cpp
Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/posix/i_system.h
Expand Up @@ -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();
Expand Down
10 changes: 9 additions & 1 deletion src/posix/sdl/i_timer.cpp
Expand Up @@ -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)
{
Expand Down
14 changes: 13 additions & 1 deletion src/win32/i_system.cpp
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/win32/i_system.h
Expand Up @@ -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();
Expand Down

0 comments on commit 03ed065

Please sign in to comment.