Hi all
I want to ask you about a very basic thing, yet I think many people do not realize it. I am talking about creating a smooth animation, an optimal main loop. I decided to look into this matter after reading this article: http://frankforce.com/?p=2636
OK, so how do we get smooth animation? Just turn on Vsync and use the DT, then you have smooth animation, you may say. But recently I discovered that this whole approach only appears to work fine, but it's logic is false. The thing is, the DT that is passed to the update loop represents the time difference between the last screen flip and the second to last. So it is the DT that has been, not the DT that will be. OK, you may say, but the vsync fixes the DT, so it's always the same. Well, that's not true. Vsync does not assure perfectly even DT's.
So, we're not looking for the DT that has been, we're predicting the time of the next screen flip in order to draw an accurate frame. Honestly, I did not understand all of the stuff in the linked article, that's why I would like to hear your opinion.
I also attached an example with comparison where I use the Actual DT versus the Average DT. When you look at the moving blocks, you can see (at least on my screen) that the red block is "shaking" from time to time, and the green one is more stable.
How to achieve smooth animation - DT prediction
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
How to achieve smooth animation - DT prediction
- Attachments
-
dt_test.love
- DT Test
- (776 Bytes) Downloaded 147 times
- bartbes
- Sex machine
- Posts: 4946
- Joined: Fri Aug 29, 2008 10:35 am
- Location: The Netherlands
- Contact:
Re: How to achieve smooth animation - DT prediction
I don't agree with your logic of "we're predicting the next frame". No, we're taking the state at the last frame, then applying our transformation for time passed since then to present the current frame. Yes, dt is the time to the last frame, but that is also the time you've yet to simulate.
EDIT: Also keep in mind your average is also measured over the past, this hides sudden movement (hence the smoothness), but I could easily induce larger dt values and it would show that the average dt method rubber bands back into a consistent state. This is arguably a nicer effect, but it also means your simulation is inconsistent for your averaging period after a sudden discontinuity. (Note that I assume the dt method is always consistent, which it isn't, but it's a fair baseline for this.)
EDIT: Also keep in mind your average is also measured over the past, this hides sudden movement (hence the smoothness), but I could easily induce larger dt values and it would show that the average dt method rubber bands back into a consistent state. This is arguably a nicer effect, but it also means your simulation is inconsistent for your averaging period after a sudden discontinuity. (Note that I assume the dt method is always consistent, which it isn't, but it's a fair baseline for this.)
Re: How to achieve smooth animation - DT prediction
I disagree, toobartbes wrote:I don't agree with your logic of "we're predicting the next frame". No, we're taking the state at the last frame, then applying our transformation for time passed since then to present the current frame. Yes, dt is the time to the last frame, but that is also the time you've yet to simulate.
![I'M SO HAPPY I COULD SHIT A RAINBOW RIGHT NOW :awesome:](./images/smilies/ms-awesome.png)
In my opinion a better approach is this: I want to predict when the next frame is displayed to the user and keep my simulation up to date with that. Using average DT is just one way of predicting, in the linked article the guy is using some more sophisticated way.
- bartbes
- Sex machine
- Posts: 4946
- Joined: Fri Aug 29, 2008 10:35 am
- Location: The Netherlands
- Contact:
Re: How to achieve smooth animation - DT prediction
No, the next draw happens directly after you are done, conceptually at least. Dt also includes time spent waiting, for whatever reason. I really do believe that you are always talking about now, and then drawing that. And not thinking about whenever this timestep ends (which is always after the draw occurs, by the way), and drawing that. Your claim that I assume anything about the next draw is plain wrong, I make no assumptions whatsoever on the future.
Regardless, like I mentioned, while your average dt method is smoother (which may very well be your goal) it is by definition lagging because you're basing your predictions not only on the last frame, but on the last second or so, which means you just smear a lagspike out instead of dealing with it.
Regardless, like I mentioned, while your average dt method is smoother (which may very well be your goal) it is by definition lagging because you're basing your predictions not only on the last frame, but on the last second or so, which means you just smear a lagspike out instead of dealing with it.
Re: How to achieve smooth animation - DT prediction
i think you might have the logic behind dt a little bit wrong. dt is a means of accurately changing a variable, each update, based on time. if we want our object to move exactly 10 units per second, dt works perfectly. if our frame takes 0.5 of a second, our object will move 5 units. if our frame takes 1 second, our object will move 10 units. it doesn't matter than dt is based on the last frame, because 10 units will always take 1 second to travel.
by averaging the dt, our object is no longer guaranteed to have moved 10 units after 1 second. this is because a frame taking 1 second will not move the object 10 units, only a fraction more than our non-laggy frame.
your example is a cool concept with its own uses, but i think it would be a little too unreliable for any kind of accurate calculations
by averaging the dt, our object is no longer guaranteed to have moved 10 units after 1 second. this is because a frame taking 1 second will not move the object 10 units, only a fraction more than our non-laggy frame.
your example is a cool concept with its own uses, but i think it would be a little too unreliable for any kind of accurate calculations
Re: How to achieve smooth animation - DT prediction
OK I implemented the logic described in the article, the loop looks like this:
1. We assume Vsync is on, with interval of 60 Hz.
2. We calculate how many full frames we should simulate.
3. We ensure that the simulation progresses by at least 1 frame.
4. We calculate the difference between the simulated time and actual time and store it in the delta buffer.
Now, please test the attached LOVE file and see how the red block shakes left and right once every couple of seconds. Then, grab the window to generate a lag spike and see how both blocks stay in the same relative position.
Code: Select all
function love.update(dt)
local old_delta = dt + delta_buffer
local frames = math.floor(old_delta * 60)
if frames < 1 then frames = 1 end
local new_delta = frames / 60
delta_buffer = old_delta - new_delta
end
2. We calculate how many full frames we should simulate.
3. We ensure that the simulation progresses by at least 1 frame.
4. We calculate the difference between the simulated time and actual time and store it in the delta buffer.
Now, please test the attached LOVE file and see how the red block shakes left and right once every couple of seconds. Then, grab the window to generate a lag spike and see how both blocks stay in the same relative position.
- Attachments
-
dt_test2.love
- DT Test 2
- (703 Bytes) Downloaded 130 times
Re: How to achieve smooth animation - DT prediction
It works for me. On my monitor it looks as if the blue box is moving steadily while the red one moves in jumps from time to time.
I was skeptical at first, but now that I see the method in action, I think it is a clever method, as long as vsync is switched on.
It took me a while to understand what the method does, so here is a summary:
In the update, we obtain a dt, which is the time passed, since the update was called last. But what we are really interested in, is the time between two drawing calls. dt is a good approximation to this, but additionally we know that the time between two drawing calls must be a multiple of the vsync-frequency. Thus, the method you show, rounds dt downward to the next multiple of the vsync-frequency. The part that was cut of is added on top of the next dt, so that no time gets lost.
The method can still not predict, the accurate time, the current update takes. So if for some reason the update takes more time, then still the frame drawn afterwards is "at the wrong time". And I think there is no way around this. This is a chicken-egg-situation. We need dt to make an update, but the time the update takes is not know beforehand.
I was skeptical at first, but now that I see the method in action, I think it is a clever method, as long as vsync is switched on.
It took me a while to understand what the method does, so here is a summary:
In the update, we obtain a dt, which is the time passed, since the update was called last. But what we are really interested in, is the time between two drawing calls. dt is a good approximation to this, but additionally we know that the time between two drawing calls must be a multiple of the vsync-frequency. Thus, the method you show, rounds dt downward to the next multiple of the vsync-frequency. The part that was cut of is added on top of the next dt, so that no time gets lost.
The method can still not predict, the accurate time, the current update takes. So if for some reason the update takes more time, then still the frame drawn afterwards is "at the wrong time". And I think there is no way around this. This is a chicken-egg-situation. We need dt to make an update, but the time the update takes is not know beforehand.
Check out my blog on gamedev
Re: How to achieve smooth animation - DT prediction
Cheers! That's exactly how I understood it. Rather than relying on the DT, we rely on the fact than the interval between two physical screen refreshes is constant. I'm glad that you see how the red box jumps. For me it's not comfortable to see this kind of glitch.micha wrote:It works for me. On my monitor it looks as if the blue box is moving steadily while the red one moves in jumps from time to time.
I was skeptical at first, but now that I see the method in action, I think it is a clever method, as long as vsync is switched on.
It took me a while to understand what the method does, so here is a summary:
In the update, we obtain a dt, which is the time passed, since the update was called last. But what we are really interested in, is the time between two drawing calls. dt is a good approximation to this, but additionally we know that the time between two drawing calls must be a multiple of the vsync-frequency. Thus, the method you show, rounds dt downward to the next multiple of the vsync-frequency. The part that was cut of is added on top of the next dt, so that no time gets lost.
For me there are two issues:micha wrote:The method can still not predict, the accurate time, the current update takes. So if for some reason the update takes more time, then still the frame drawn afterwards is "at the wrong time". And I think there is no way around this. This is a chicken-egg-situation. We need dt to make an update, but the time the update takes is not know beforehand.
1. How to make this work for any refresh rate, not just 60 Hz? (LOVE does not support getScreenRefreshRate property, right?)
2. How do I achieve "smooth" graphics with a constant timestep with vsync turned off?
Who is online
Users browsing this forum: No registered users and 4 guests