修复了使用VSync打开时间步长的问题

Ed *_*rbu 6 c++ opengl game-engine visual-c++ c++11

在我实现的2D OpenGL引擎中,我有一个固定的时间步长,如着名的修复你的时间步骤文章,以及混合.

我有一个垂直移动的测试对象(y轴).运动中有口吃(预编程运动,而非用户输入).这意味着对象不能在屏幕上平滑移动.

请参阅我正在链接的未压缩视频:LINK

游戏帧率保持在60fps(Vsync从Nvidia驱动程序打开)

游戏逻辑以每秒固定的20次更新/滴答更新,由我设置.这个是正常的.对象每次更新移动50个像素.

然而,屏幕上的移动是严重的口吃.

编辑:我注意到通过逐帧踩踏录制的视频,口吃是由一个帧显示两次引起的.

EDIT2:在任务管理器中将应用程序优先级设置为Realtime,完全消除了口吃!然而,这显然不是解决方案.

下面是不同时间的对象y移动增量,VSync关闭第一列是自上一帧以来经过的时间,以微秒为单位(ex 4403)第二列是自上一帧以来对象y轴上的移动.实际上,对象每秒移动1000个像素,下面的日志确认了它.

time since last frame: 4403    ypos delta since last frame: 4.403015
time since last frame: 3807    ypos delta since last frame: 3.806976
time since last frame: 3716    ypos delta since last frame: 3.716003
time since last frame: 3859    ypos delta since last frame: 3.859009
time since last frame: 4398    ypos delta since last frame: 4.398010
time since last frame: 8961    ypos delta since last frame: 8.960999
time since last frame: 7871    ypos delta since last frame: 7.871002
time since last frame: 3985    ypos delta since last frame: 3.984985
time since last frame: 3684    ypos delta since last frame: 3.684021
Run Code Online (Sandbox Code Playgroud)

现在打开VSync

time since last frame: 17629     ypos delta since last frame: 17.628906
time since last frame: 15688     ypos delta since last frame: 15.687988
time since last frame: 16641     ypos delta since last frame: 16.641113
time since last frame: 16657     ypos delta since last frame: 16.656738
time since last frame: 16715     ypos delta since last frame: 16.715332
time since last frame: 16663     ypos delta since last frame: 16.663086
time since last frame: 16666     ypos delta since last frame: 16.665771
time since last frame: 16704     ypos delta since last frame: 16.704102
time since last frame: 16626     ypos delta since last frame: 16.625732
Run Code Online (Sandbox Code Playgroud)

我会说他们看起来不错.

这让我疯狂了好几天,我错过了什么?

下面是我的Frame函数,它在循环中调用:

void Frame()
{
static sf::Time t;
static const double ticksPerSecond = 20;
static uint64_t stepSizeMicro = 1000000 / ticksPerSecond; // microseconds
static sf::Time accumulator = sf::seconds(0);

gElapsedTotal = gClock.getElapsedTime();

sf::Time elapsedSinceLastFrame = gElapsedTotal - gLastFrameTime;
gLastFrameTime = gElapsedTotal;


if (elapsedSinceLastFrame.asMicroseconds() > 250000 )
    elapsedSinceLastFrame = sf::microseconds(250000);

accumulator += elapsedSinceLastFrame;

while (accumulator.asMicroseconds() >= stepSizeMicro)
{
    Update(stepSizeMicro / 1000000.f);
    gGameTime += sf::microseconds(stepSizeMicro);
    accumulator -= sf::microseconds(stepSizeMicro);
}
uint64_t blendMicro = accumulator.asMicroseconds() / stepSizeMicro;
float blend = accumulator.asMicroseconds() / (float) stepSizeMicro;
if (rand() % 200 == 0) Trace("blend: %f", blend);
CWorld::GetInstance()->Draw(blend);
}
Run Code Online (Sandbox Code Playgroud)

评论中要求的更多信息:

  • 在全屏1920x1080和窗口模式1600x900中都会发生口吃

  • 设置是一个简单的SFML项目.在渲染纹理矩形时,我不知道它是否在内部使用VBO/VAO

  • 在我的电脑上没有做任何其他事情.请记住,这个问题也发生在其他计算机上,它不仅仅是我的装备

  • 我在主显示器上运行.显示器并没有真正有所作为.在全屏和窗口模式下都会出现此问题.

Gav*_*son -1

这是一个棘手的问题,但从上面看来,在我看来,这不是“帧速率”问题,而是“动画”代码中的某个问题。另一个观察结果是“Update(stepSizeMicro / 1000000.f);”行。除以 1000000.f 可能意味着由于浮点数位分辨率的限制,您会失去分辨率,因此舍入可能是您的杀手锏?