🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Understanding how a fixed time step game loop works, but having trouble grasping interpolation in the render function

Started by
2 comments, last by Hashbrown 5 years, 3 months ago

I believe I got most of the theory covered, I'm just having trouble understanding how interpolation in the rendering loop works. Everything seems to work even when my timestep is at 1 fps, the character movement is interpolated smoothly regardless of the 1fps, but I want to really understand what's going on.

Below I'll explain as brief as possible what I understand so far:

Game Loop


while (true) {
    // Time Calculation
    double now = glfwGetTime();
    float delta = (now - previous);
    previous = now;

    if (delta >= 0.25f) delta = 0.025f;
    accumulator += delta;

    // Physics Update
    while (accumulator >= step) {

        UpdatePlayer(step);

        accumulator -= step;
    }
  	// Render
    float alpha = (accumulator / step)
    RenderPlayer(alpha);
}

The physics update makes sure my simulation's physics is corrected in the case that the loop is having trouble catching up. For example, let's say I want to move my character 1 unit per frame. Let's also say:

- PC1 is able to move the character 2 units in 2 seconds (2 frames).
- But PC2 lags behind and it takes 2 seconds to complete 1 frame.

dt.jpg

 

Based on what I understand, the slow computer will stay in the physics update one more update in order to catch up within that frame, essentially leaving the character in the same position like the quicker computer within the same time-frame.

In other words: PC1 only needed 1 physics update per frame, but PC2 needed 2 updates within 1 frame. Am I right about that?

 

Update Player


void UpdatePlayer (const float step) {
    
    previousState = currentState;

    currentState.velocity.x += (currentState.force / currentState.mass) * step;
    currentState.velocity.y += (currentState.force / currentState.mass) * step;
    currentState.velocity.z += (currentState.force / currentState.mass) * step;

    currentState.position.x += (previousState.velocity.x + currentState.velocity.x) * 0.5f * step;
    currentState.position.y += (previousState.velocity.y + currentState.velocity.y) * 0.5f * step;
    currentState.position.z += (previousState.velocity.z + currentState.velocity.z) * 0.5f * step;
}

I'm not getting into numerical integration but I did want to share it just in case. I'm actually using Velocity Verlet integration I found in this interesting article. The following part is where I'm having trouble:

 

Render and State Interpolation (having trouble understanding this)


void RenderPlayer (const float alpha = 1.0f) {
    vec3 interpolated = Interpolate(previousState.position, currentState.position, alpha);
    
    // Matrix Calculations
    player.transform.UpdateModel(interpolated);
    mat4 mvp = camera.projection * camera.transform.view * player.transfomr.model;

    // Upload to GPU and Render
    shader->UploadMVP(mvp);
    mesh->Render();
}

I believe I understand why we're interpolating, but still confused. Let's say my physics loop is running at 1 frame per second, I can interpolate between positions and render at a smooth rate. So 1fps won't be visually noticeable, which is awesome and very useful! I also understand that the alpha value is a percentage of how far we are from the next frame.

But when I print out some numbers, I notice that after interpolation, the currentState.position is at the right position, but when I check the interpolated position we're rendering to, it's always behind the current state. Is that normal?


Current State position: 2.000000 | velocity 1.000000
interpolated at render: x: 1.499536

I understand we're calculating a percentage of how far we are to the next frame, but shouldn't the interpolated positions match the currentState.position at some point? I'm afraid of rendering my player at an incorrect position. I'm having trouble wrapping my head around this concept still.

Hopefully this all makes sense, and if you read this far, thanks for reading!

 

Advertisement
59 minutes ago, Hashbrown said:

In other words: PC1 only needed 1 physics update per frame, but PC2 needed 2 updates within 1 frame. Am I right about that?

Yes.

59 minutes ago, Hashbrown said:

But when I print out some numbers, I notice that after interpolation, the currentState.position is at the right position, but when I check the interpolated position we're rendering to, it's always behind the current state. Is that normal?

Yes. You would typically render by interpolating between the previous and current states, so the render would in 99.9% of cases be behind the current state (unless you hit the tick bang on). In certain games you *could* also consider extrapolating beyond the current state, but beware, here there be dragons.

12 hours ago, lawnjelly said:

Yes.

Yes. You would typically render by interpolating between the previous and current states, so the render would in 99.9% of cases be behind the current state (unless you hit the tick bang on). In certain games you *could* also consider extrapolating beyond the current state, but beware, here there be dragons.

Thanks for taking the time to answer my question Lawn, I really appreciate it. I feel like I passed a huge test at school :) I can move on to other topics now. Thanks again!

This topic is closed to new replies.

Advertisement