【发布时间】:2014-10-06 14:46:35
【问题描述】:
在我实现的 2D OpenGL 引擎中,我有一个固定的时间步长,如著名的 fix your timestep 文章中所述,以及混合。
我有一个垂直移动的测试对象(y 轴)。运动中有口吃(预编程运动,不是来自用户输入)。这意味着对象不会在屏幕上平滑移动。
请看我链接的未压缩视频:LINK
游戏帧率保持在 60fps(从 Nvidia 驱动程序打开 Vsync)
游戏逻辑以固定的每秒 20 次更新/滴答声更新,由我设置。这很正常。对象每次更新移动 50 个像素。
但是屏幕上的动作严重卡顿。
编辑:我注意到通过逐帧进入上面录制的视频,卡顿是由一帧显示两次引起的。
EDIT2:在任务管理器中将应用程序优先级设置为实时完全消除了卡顿!然而,这显然不是一个解决方案。
下面是对象在不同时间的 y 移动增量,垂直同步关闭
第一列是自上一帧以来经过的时间,以微秒为单位(例如 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
现在开启垂直同步
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
我会说它们看起来不错。
这几天一直让我发疯,我错过了什么?
下面是我在循环中调用的 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);
}
在 cmets 中要求的更多信息:
在全屏 1920x1080 和窗口模式 1600x900 下都会出现卡顿
设置是一个简单的 SFML 项目。我不知道它在渲染纹理矩形时是否在内部使用 VBO/VAO
没有在我的计算机上执行任何其他操作。请记住,此问题也发生在其他计算机上,不仅仅是我的设备
正在主显示器上运行。显示器并没有真正的区别。在全屏和窗口模式下都会出现此问题。
【问题讨论】:
-
你没有分析性能问题的根源是什么,这可能是很多事情——后台任务、资源加载、过于复杂的代码……
-
没有性能问题。游戏运行 200+ fps。口吃是问题。口吃意味着对象在屏幕上没有平滑移动。您可以在我发布的日志中的屏幕上看到不同时间的位置。位置是正确的,并且与时间成线性关系。如果问题不够清楚,请告诉我。我不知道为什么人们不赞成它!
-
开启垂直同步后,它保持在 60fps。口吃仍然存在。
-
我看不出在 60fps 的情况下你怎么会看到卡顿,因为你的数据显示你的增量完全相同。如果你忽略时间步长逻辑,只是简单地将 16.6 添加到每帧的 ypos 上,你还会看到卡顿吗?
-
我愿意,是的。这就是奇怪的部分。
标签: c++ opengl visual-c++ c++11 game-engine