dhewm3
dhewm3 copied to clipboard
Smooth movement on refresh rates above 60Hz?
Recently I found a simple tool named Quake 4 Tweaker, which allows Q4 to run smoothly on monitors with refresh rate above 60. https://community.pcgamingwiki.com/files/file/1009-quake-4-tweaker/ I think it does that by hacking into the global game timing slowing it down to the selected monitor refresh rate / target FPS. The more target FPS is selected, the slower the game movement/animation is, so it simply compensates for the game speed up above 60Hz when using uncapped framerate (com_fixedTic 1). The result is perfectly smooth gameplay with correct timing on higher refresh rates. Is it possible to implement something like this into the dhewm3 code? I tried the "experimental" com_fixedTic -1 but for me it behaves the same as com_fixedTic 0, so on the higher refresh rates (100, 120, 144) the movement is just a stuttery mess capped to 63Hz.
After some source code digging I think that all it takes is a little change in UsercmdGen.h: const int USERCMD_HZ = 120; //60 Compiling the source code will produce new base.dll - replace it in the dhewm3 installation and then use autoexec.cfg with: seta com_fixedTic "1" seta r_swapInterval "1" seta r_finish "1" ;optional to reduce input lag That should lock dhewm3 movement to smooth 120FPS just like in bfg edition. Cutscenes timing will be still a little off (that would need multiples of 62.5Hz refresh rate), but thats a minor problem compared to 60FPS judder on 120Hz refresh rate. I will test it some more, but so far it seems to be working OK.
This would be amazing. Playing Doom3 at 60hz is brutal. IMO, the 120hz of the BFG edition is its only saving grace.
I really hope this gets implemented in dhewm3 :D
Could you share the dll? I'm having issues compiling the source in mysys. Is it possible to go higher? E.g. 240hz
I am not that familiar with the sources, but I think Daniel should be able to create a cvar for this. Even if it should require restart of the engine, it will be better than hardcoded value. I didn't play with this since march, but I can share the 120Hz dll here for version 1.5.0, if you want to try it. It should work with any other frequency, but I tried only 120Hz as I have currently 120Hz monitor. Just make sure your autoexec.cfg is set as above. The dll is compiled using VS2017 and latest stable version 1.5.0 of sources.
Hmm, I am definitely having some issues with this. The game speed often jumps to double the speed.
That cvar com_fixedTic "1" is a hack to remove the 62.5 framerate cap. It must be substituted using VSync. To get smooth gameplay, some criteria must be met:
- your GPU must be capable to render more than 120fps all the time
- your Display refresh rate must be set to 120Hz on desktop before launching the game
- vsync must be active using r_swapInterval "1" or forcing it in your GPU control panel I don't have any framerate jumps on my GTX1080. But this is an ancient engine after all so anything weird is possible...
Ok, just to write something here: ;)
The problem is, this kind of change is dangerous - you never know if that 60Hz assumption is hardcoded somewhere without using that USERCMD_HZ
constant, which can cause subtle bugs - and I don't own a 120Hz display myself to test it.
(and if I understand correctly, @buvk's problem is not the framerate but that the game itself, i.e. animations or shooting or whatever, runs twice as fast as it should?)
I remember going trough almost half the game before posting it here, heavy shooting included and didn't encounter any speedups or slowdowns. No problems with fast GPU, but with slower one there might be some. I know the hack does not compensate for framerates below refresh rate, so engine speed slowdowns are inevitable. But the speedups are new for me...
My monitor is 240hz, and I removed 120hz via CRU due to DSR favoring lower refresh rates in some games.
I'd be happy to help test whatever I can here. I plan to play through the entire game, so if there are issues, there's a good chance I'll spot them.
Well, that's the problem. Display refresh rate must be the same as framerate, otherwise this hack will not work. In your case VSync is trying to hold the framerate at 240, not 120, hence the 2x speedups. But sometimes it falls down do 120 and then you see normal speed. You can try 120fps framelimiter or I can try to compile 240Hz dll for you, but if your GPU is not able to hold stable 240FPS, there is really no point - you would see slowdowns instead.
I actually tried limiting framerate via rtss; was still encountering weird issues.
My rig should be able to handle 240fps no problem, so if you can compile a new dll, I can test that and let you know the outcome.
There you go: base240.zip It moves at half speed on my 120Hz display, so on 240Hz it should run at normal speed with that above mentioned autoexec.cfg settings.
Well I guess my rig isn't good enough, or else the game/engine itself has issues sustaining higher framerates. I often saw framerate drop to around 120ish. My GPU usage remained low, so I don't think it's that (I have a 2080).
I'll play around with the 120hz dll some more.
On Thu., Jun. 13, 2019, 10:44 a.m. dezo2, [email protected] wrote:
There you go: base240.zip https://github.com/dhewm/dhewm3/files/3287402/base240.zip It moves at half speed on my 120Hz display, so on 240Hz it should run at normal speed with that above mentioned autoexec.cfg settings.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dhewm/dhewm3/issues/230?email_source=notifications&email_token=AAULDRZI6AEJQCM3PJOSFGTP2KBRVA5CNFSM4G3LTU6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXUP45Q#issuecomment-501808758, or mute the thread https://github.com/notifications/unsubscribe-auth/AAULDR5FDELUAG6IUMMJNKLP2KBRVANCNFSM4G3LTU6A .
can't you run your display at 120hz somehow? like, configure the refreshrate in windows or the GPU driver to 120hz?
That sucks. It may actually be CPU this time as the engine obviously isn't created for multicores and single core processing has its limits (as in the original Crysis 1 game).
Yeah, multiple cores were not a thing in desktop PCs in 2004, so it's very single-threaded. (Some servers or workstations had multiple sockets for multiple CPUs, but that wasn't relevant in the gaming market)
Also, 240hz is just brutal: instead of 16.7ms per frame it's only 4ms per frame - that's not easy to achieve! I also seriously doubt anything beyond 120Hz really makes sense/a visible difference. (Many people say the same thing about more than 60Hz, but AFAIK most people can indeed see/feel the difference between 60 and 120)
I am glad I didn't go higher than 120Hz with my monitor, because the CPU/GPU demands are also doubled. That said, the difference between 60Hz and 100+Hz is VERY noticeable, even for an old fart like me. The smoothness reminds me of the good old CRT times, I really like it.
So, I tested this a few days ago (first time ever modifying or compiling code. yay me), some observations:
-ticrate MUST match the display refresh and you MUST use com_fixedtic 1 -120 and 144hz both present subtle issues, mostly with physics and animation -to truly be double, the game would need to run at 125hz, but since this hack relies on a fixedtic and no display (that I know of) runs at 125hz you will also have some desync issues. -a minor issue, but if you use com_fixedtic 1 and your fps falls below the ticrate, the entire game will slow (that said, always use com_fixedtic 1 on any version of doom/quake/prey if you can - it eliminates the 1 sec sync which causes a stutter and the overall feel is quite smoother).
The BFG edition manages to avoid all of this and run the game on a tic independent from the display refresh, even with com_fixedtic 1 and a display above 120hz.
EDIT: the Quake4 tweaker mentioned above WORKS LIKE A CHARM on quake4 - no issues whatsoever.
Yeah, the com_fixedTick hack + VSync is quite old, I think I used it all the time in old id tech games, because that 1sec stutter pissed me off. Cutscenes sound is out of sync because of the hack, but everything else seems to be mostly OK. Much better than with the stutter. With today PCs, the slowdowns are second to none, as the game is not that demanding. I really like to know they logic back then, why they have to use the internal tick at 62.5Hz? Why such stupid value? It is present even in their prerendered movies in game resources and looks pathetic. Nevertheless, it is possible to create custom resolution with 125Hz refresh rate, at least on nVidia cards in their control panel. I think every 144+Hz panel should be able to display that.
why do you think it's 62.5, the constant (USERCMD_HZ
) is 60
?
EDIT: oh, is it because 1000/60 == 16
(in integers) and 1000/62.5 == 16
as well, even without any type-dependent rounding?
You might be onto something. I don't know the egine inside out, but it seems that the physics and sound are synchronized to 62.5Hz. That is the value I see in RivaTuner overlay with com_fixedTic 0 and disabled VSync. So not exactly the 60FPS, but this dreaded 62.5. The renderer also seems to repeat a frame every second even when used with 60Hz VSync to synchronize everything to that value.
You'll also notice that the vanilla game is capped at 62.5 (the OSD reads 62/63).
const int USERCMD_HZ = 60 // 60 frames per second const int USERCMD_MSEC = 1000 / USERCMD_HZ; So why they are using integer dividing here? For performance reasons? The second constant should be float and everything that depends on it it should be also calculated in floats. Strange.
it's a constant so there is no difference in performance in the divide itself; I don't know why they're using int and not float there. Note that this is another problem for 120hz (or even more): while 16ms as an int constant seems to work well enough, the higher the Hz (and thus the lower the USERCMD_MSEC frametime), the more the inaccuracy of ints in milliseconds will hurt us. Using either a float or microseconds there should work better; but TBH I'm not sure I dare to make such a deep change - I imagine that this would require switching to float/microsecond in lots of places, possibly including the network protocol. And it might require lots of changes in the gamecode as well, which again would affect mods (=> make them harder to port and break the mod DLL interface; though just chaning USERCMD_HZ to another value or making it configurable at runtime would also break the DLL interface) :-/
https://github.com/RobertBeckebans/RBDOOM-3-BFG/commit/72f986077b4abb523b6b3ac6232bbaf62a0bbc8f
not sure if anything useful can be gleaned from this.
RobertBeckebans/RBDOOM-3-BFG@72f9860
not sure if anything useful can be gleaned from this.
Not really, at least not from that commit itself - as you see USERCMD_HZ is apparently unused in the BFG code, so the change didn't matter. One could try to figure out what changes they did to the gamecode to make it work without it and see if our gamecode could be adjusted in the same way - but again, that might make porting mods harder :-/
The Quake4 tweaker mentioned earlier works flawlessly in my experience - unfortunately I can't find any sources for it.
https://methanhydrat.wordpress.com/2018/02/13/quake-4-tweaker/
I sent the Quake 4 Tweaker author a message on the blog you linked, hopefully they'll tell me how it was done in Q4, maybe the same works for Doom3 (unless Q4 already eliminated USERCMD_HZ and it was just a cvar or sth.. we'll see).
Hi there, I am the author of the Quake 4 Tweaker mod.
I am afraid the solution I used for Quake 4 is not applicable to Doom 3. You are all on the right track and already discovered the USERCMD_HZ
and USERCMD_MSEC
constants. As far as I know, this would be the way to go to adjust the frame rate limit.
The version of id Tech 4 that Quake 4 uses is more advanced than what was released for Doom 3; which makes sense considering it came out a few years later. In that game, the above constants were merged into two additional functions in idCommonLocal
, which I called GetUserCmdHz
and GetUserCmdMsec
, because they basically return computed values for the aforementioned constants.
These functions are called every frame from the engine and seem to be used throughout the code to calculate the corresponding timings. This makes it possible to adjust everything on the fly. The mod hooks these functions and adjusts their returns according to the FPS limit that was configured by the user.
Unfortunately, neither the Doom 3 nor the Doom 3 BFG code features this implementation. The latter uses a different mechanism than the original, but it is still not the same as what can be seen in Quake 4. This also makes sense, because, as far as I know, the BFG edition was developed from the original source code, with some backported featured from id Tech 5.
Now, I think your best bet is to adjust the constants and by hand just try to fix every additional problem that occurs. It might also be helpful to take a deeper look at how the problem was tackled in the BFG edition and maybe get some inspiration for how to do it.
I think it is unfortunate that some of these awesome shooters are hard or impossible to fix for high frame rates, since these types of games benefit immensely from it. What pains me most in this regard, is the original Prey, which is a game that I love, but which uses an even older version of id Tech 4. Contrary to Doom 3, where we have the source code and thus a fair chance to change it, that one most likely will never be fixed.
Hey @Methanhydrat, thanks a lot for the insight! :)
A pity this won't work for Doom3; I kinda feared this (because patching it in Doom3 would probably have been next to impossible, as that constant will be used as a constant by the compiler, not some kind of variable that could be modified by a hack), but was hoping there's a trick to it..
I guess we should indeed look at D3BFG then. I wonder if it would be sufficient to just simulate the game (incl. animations) every 2. (for 120/144hz) or 4. (for 240Hz) frame and only update the viewport (based on the players input) in the others so input (hopefully) still feels smooth - but TBH I never looked closely at how Doom3 does all this, as so far it has just worked the way it is..
Regarding Prey: The game code (SDK) is available, so maybe it would be possible to combine some binary-hacks in the executable with an adapted game DLL? Alternatively one could try to port the Prey SDK to dhewm3, though that wouldn't really conform to the licenses (GPL and SDK license are incompatible, that's why I only support Doom3 mods that have (re-)released their source under GPL) - but OTOH if prey game DLLs turned up that just by dumb luck turned out to work with dhewm3 (possibly modified to implement missing engine features) there's nothing anyone could do about it? ;) Then again, 3DRealms still exists in some form, maybe they could even release the source properly? No idea if they have all the needed rights, but might be worth asking them?