Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Kaiser

Implementation of uncapped framerates

Recommended Posts

I was reviewing code from several source ports and I wanted to learn about the approaches and tricks used to implement uncapped frame rates (60fps) in Doom. I looked at Prboom+ but I never fully understood how this feature is implemented due to lack of comments. So has there been any technical documentation or article that discusses this feature?

Also this would be a good topic to add on to the Doom wiki if it doesn't exist yet.

Share this post


Link to post

I am also very interested in this. The closest port to us is PrBoom-Plus, but its main loops are so radically different that I would never walk away with an understanding of what changes are necessary to just get uncapped framerate support without necessarily adapting everything else along with it.

Share this post


Link to post

The TryRunTics() function is where it waits for the current tic to be finished, e.g. from chocolate doom:

    while (!PlayersInGame() || lowtic < gametic/ticdup + counts)        
    {
        NetUpdate ();   

        lowtic = GetLowTic();
        
        if (lowtic < gametic/ticdup)
            I_Error ("TryRunTics: lowtic < gametic");
    
        // Don't stay in this loop forever.  The menu is still running,
        // so return to update the screen

        if (I_GetTime() / ticdup - entertic > 0)
        {
            return;
        } 

        I_Sleep(1);
    }
I think the most basic way to "uncap" the framerate is to simply return here instead of busy waiting. You'd need to return a result that tells the caller not to run the physics. Note that it will still seem like 35fps because nothing changes in between game tics.

Another important thing to do is player prediction, predict where the player would be "in the middle" of a game tic. More precisely: you are always rendering a frame at some point inside a tic, so you need to know the correct viewpoint / viewangle for that time point. This makes the uncapped framerate actually useful and feel right.

Secondary to all that is predicting other stuff, like where projectiles and lifts/doors will be at a partial game tic, which helps make everything look smoother. Lifts are perhaps more important since the player could be standing on one, and that affects the player prediction.

Disclaimer: I haven't actually done all this myself, there may be other issues that crop up. Personally I can't quite get my head around whether the renderer is always ahead of the physics (hence predicting) or some fraction of a tic behind the physics (hence interpolating).

Share this post


Link to post
andrewj said:

Secondary to all that is predicting other stuff,


Prediction is probably not the right term here.
To render this properly all the actual positions need to be interpolated, not predicted. However, this code is pretty much self-contained in both PrBoom+ and ZDoom. The much bigger issue is to get the main game loop working first. After that the rest will most likely easily fall together.

Share this post


Link to post
Graf Zahl said:

Prediction is probably not the right term here.
To render this properly all the actual positions need to be interpolated, not predicted. However, this code is pretty much self-contained in both PrBoom+ and ZDoom. The much bigger issue is to get the main game loop working first. After that the rest will most likely easily fall together.

Yeah, I'm aware of the need for interpolation. I'm still stuck on the loop stuff though. EE's loops are so different from any other port's :( EE is already capable of drawing the screen as fast as possible, and in fact was doing this unconditionally up until a couple weeks ago when fraggle did a tweak for us to add support for locking the refresh rate to 35 Hz (unfortunately this seems to have some REALLY bad problems when running windowed mode under Windows 7, which I suspect must have something to do with GDI being piped into Direct3D for Aero...).

Given that we can already do that, I suppose the problem is knowing when and by how much to interpolate :) EE has the added issue of dynasegs, which I know you referred to as being a problem for ZDoom's interpolation system.

Share this post


Link to post

I always thought about setting the GAMETIC to 60 or something instead of 35 and then find a way to lower the thing's state tics and sector movement speeds to match what the tic speed would be if the game was at 35hz. But I figured that wouldn't work quite as well...

Share this post


Link to post
Kaiser said:

I always thought about setting the GAMETIC to 60 or something instead of 35 and then find a way to lower the thing's state tics and sector movement speeds to match what the tic speed would be if the game was at 35hz. But I figured that wouldn't work quite as well...

No, especially since 60 is not divisible by 35. You'd need to go 70 Hz I think if you wanted to take an approach of simply doubling the refresh rate. Then you would increment gametic only once for every two main loop iterations, and run game logic only when framecount & 1 is 0 (I think? :P)

I think it's better to go the general route and allow as many FPS to render as the computer can support.

Share this post


Link to post
Kaiser said:

I always thought about setting the GAMETIC to 60 or something instead of 35 and then find a way to lower the thing's state tics and sector movement speeds to match what the tic speed would be if the game was at 35hz. But I figured that wouldn't work quite as well...


That will never work with Doom's game physics. Frame interpolation is the only way that keeps the game true to itself.

Share this post


Link to post

Is there any article that covers general frame interpolation? I am not exactly too familiar with that and it would be something that I would like to learn more about.

Share this post


Link to post

There are several ways to approach this and it depends on your overall architecture. Are you going for full MVC separation or something that is more of a natural extension of the DOOM main loop (remove the fixed interval controlling the main loop, call the game logic at fixed intervals within the new uncapped main but otherwise do everything else; input, render, etc)?

Frame interpolation is relatively straight forward. As the game logic is updating in fixed intervals you need to decide whether to extrapolate or interpolate (depending on whether a whole tic of latency is Ok for whatever it is you are smoothing). In general I would suggest you interpolate the visual/audio representations (stuff like sector plane heights and mobj positions/angles) in separate buffers which track/follow the "sharp" values set on each fixed tic of the game logic. Naturally you will need bounds on the interpolatable range (e.g., you would not want to smooth a mobj teleporting from one side of the map to the other between fixed tics).

Although it would be possible to raise GAMETIC and then alter all the game logic respectively, I urge you not to ;)

Say you double it up to 70hz. How do you then handle the situation of say a 60hz refresh rate? Without you split the game logic into another process and/or go the whole MVC route, I will be very tricky to ensure you sync up and most likely you will drop frames continuously.

Share this post


Link to post

Well I was considering adding this feature for Doom64ex and since its based directly on top of the original doom2 source, I would want to be able to implement this without having to do serious changes to the loop code.

Share this post


Link to post

Quasar said:

Kaiser said:

I always thought about setting the GAMETIC to 60 or something instead of 35 and then find a way to lower the thing's state tics and sector movement speeds to match what the tic speed would be if the game was at 35hz. But I figured that wouldn't work quite as well...


No, especially since 60 is not divisible by 35.

I believe Kaiser is interested in this specifically for DOOM64ex. Being as DOOM64 was originally made for the N64 they had to sync to both PAL and NTSC. However I recall reading that they had to drop the resolution of GAMETIC to 30.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×