Decouple render framerate from logic/physics framerate [2/2] #1400
Replies: 9 comments
-
I think this is already implemented... you can disable "UseFrameRate" and "Vsync" and disable render completly by using bge.logic.setRender(False)... then just set it to true every other nth frame or when ever you need it... you can even render without refreshing, and refresh the screen in a separate moment after render has finished... (for instance waiting for some sync pulse or other condition)... |
Beta Was this translation helpful? Give feedback.
-
An automagical way to do this would be very very good. In the meantime, @nestanqueiro I would love a more detailed explanation/tutorial on this. Say I wanted 90 FPS as the target render framerate, how to lock the logic rate to 60 and handle slow downs? |
Beta Was this translation helpful? Give feedback.
-
In my machine, this gives me roughly 90 frames per second....
|
Beta Was this translation helpful? Give feedback.
-
for running expensive logic and not slowing the frame rate you may want to
checkout the python exexutor, coroutine and futures modules.
you can task jobs and have them yield when finished, and run over multiple
frames, (great for recomputing pathfinding grid or other expensive tasks
that are not needed every frame)
Let me know if you want a simple .blend demonstrating coroutines that was
provided to me by WKK at the blender discord.
On Jan 15, 2018 9:27 AM, "nestanqueiro" <notifications@github.com> wrote:
In my machine, this gives me roughly 90 frames per second....
from bge import logic
from datetime import datetime, timedelta
obj=logic.getCurrentController().owner
logic.setRender(False)
if 'time' not in obj:
logic.old=datetime.now()
print(logic.old)
obj['time'] = int(float(str(logic.old).split(':')[-1])*10000)
obj['milisegundos']=0
else:
temp=logic.old
current=datetime.now()
delta=timedelta
#print(delta)
obj['time'] = int(float(str(current).split(':')[-1])*10000)
obj['milisegundos']+=1
logic.old=current
if (obj['milisegundos'])==600:
#print(obj['frames'])
logic.setRender(True)
obj['milisegundos']=0
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#666 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AG25WTb1SboUC907rV3juA4VTGHYnzzxks5tK4qXgaJpZM4RU3vH>
.
|
Beta Was this translation helpful? Give feedback.
-
if you please, I would really like to see how to span processing over multiple frames, and I never used none of the modules you mention, so I would really appreciate to see your demo... Thank you very much! |
Beta Was this translation helpful? Give feedback.
-
If the rendering is proceeded separately each render frame should still be preceded by a logic step or a physics step anyway else the render frame will be identical, right ? |
Beta Was this translation helpful? Give feedback.
-
The idea is opposite, @panzergame . In most cases it's the GPU that lags behind and doesn't let CPU get 100% utilization. Being able to do multiple CPU cycles while waiting for GPU would be great (imagine game running at 60 FPS, but input handling and physics calculations running at higher framerate, producing smoother gameplay and more stable and accurate physics). I am wondering if it's possible to move physics and script handling to separate threads. They should run calculations independently, but provide rendering thread (and each other) with necessary information. Would that be doable? |
Beta Was this translation helpful? Give feedback.
-
Physics could be run totally independently of rendering (but not from logic) but it's more complicated with logic which could affect materials, meshes etc… (spatial is fine). Also logic can call directly opengl through bgl. |
Beta Was this translation helpful? Give feedback.
-
I pass this issue to discussions to join it to another thread there |
Beta Was this translation helpful? Give feedback.
-
Right now BGE python's processing is tightly tied to rendering. The script is ran once, then data is passed to GPU. This works well for most people, but sometimes there is some need for increasing the processing frequency (e.g. physics simulation where too high delta times could cause divergence or explosions in integration). Now there are a few workarounds to increase the frequency of the script executed to stabilize delta time, but each of them has major flaws:
Setting game's refresh rate to higher. This does exactly what is needed to solve the delta time issue. However, it has a big limitation - it requires rendering the image more, too. This results in unnecessary GPU usage, reducing performance. And, as GPU starts to lag behind, it also pulls down the CPU. So you're tied to either GPU or CPU - whichever is slower.
You can also run script multiple times (e.g. include loops). This could kinda work, but it has some clear limitations, for example, if your CPU is not fast enough, having this heavy script will slow down the game since GPU will be waiting for CPU to finish it's task. Also, this method doesn't work with several built-in components of the game engine, like Bullet, rendertexture, etc.
A good solution would be to seperate the processing of scripts, physics & logic from the processing of graphics. This would allow the user to set any video refresh rate limit (e.g. VSync) without having to slow down the compution of logic. This would also prevent CPU tasks slowing down GPU or GPU tasks slowing down CPU. In a simulation, a mid-end CPU could easily process a simulation code at around 500 Hz(as example) even if the GPU is very low-end and is barely able to run the game at 30 FPS.
Oh, and maybe this could even solve some VSync input lag issues?
Beta Was this translation helpful? Give feedback.
All reactions