有没有办法计算应该达到多少更新以达到所需的帧速率,而不是系统特定的?我发现对于windows,但我想知道openGL本身是否存在这样的东西。它应该是某种计时器。
或者我怎样才能防止FPS大幅下降或上升?这次我正在测试它在线上绘制大量顶点,并且使用fraps我可以看到帧速率从400到200 fps,并且明显减慢了绘制速度。
答案 0 :(得分:11)
您有两种不同的方法可以解决此问题:
假设您有一个名为maximum_fps
的变量,其中包含您要显示的最大帧数。
然后你测量最后一帧花费的时间(计时器会做)
现在假设您说您的应用程序最多需要60FPS。那么你希望测量的时间不低于1/60。如果测量的时间降低,则拨打sleep()
以达到一帧的剩余时间。
或者您可以拥有一个名为tick
的变量,其中包含应用程序的当前“游戏时间”。使用相同的计时器,您将在应用程序的每个主循环中递增它。然后,在绘图例程中,您将根据tick
var计算位置,因为它包含应用程序的当前时间。
选项2
的一大优势是,您的应用程序将更容易调试,因为您可以随时使用tick
变量,随时可以随时返回。这是大加。
答案 1 :(得分:11)
规则#1。不要使update()或loop()类函数依赖于调用它的频率。
你无法真正获得所需的FPS。您可以尝试通过跳过一些昂贵的操作来提升它,或者通过调用sleep()类函数来减慢它的速度。但是,即使使用这些技术,FPS也几乎总是与您想要的精确FPS不同。
解决此问题的常用方法是使用上次更新所用的时间。例如,
// Bad
void enemy::update()
{
position.x += 10; // this enemy moving speed is totally up to FPS and you can't control it.
}
// Good
void enemy::update(elapsedTime)
{
position.x += speedX * elapsedTime; // Now, you can control its speedX and it doesn't matter how often it gets called.
}
答案 2 :(得分:3)
有没有办法计算应该达到多少更新以达到所需的帧速率,而不是系统特定的?
没有。
无法精确计算应调用多少更新以达到所需的帧速率。
但是,您可以测量自上一帧以来经过的时间,根据它计算当前帧速率,将其与所需帧速率进行比较,然后引入一点Sleep来将当前帧速率降低到所需值。不是一个精确的解决方案,但它会起作用。
我发现对于windows,但我想知道openGL本身是否存在这样的东西。它应该是某种计时器。
OpenGL只关注渲染内容,与定时器无关。此外,使用Windows计时器不是一个好主意。使用QueryPerformanceCounter,GetTickCount或SDL_GetTicks来测量已经过了多少时间,并使用sleep来达到所需的帧速率。
或者我怎么能阻止FPS大幅下降或提高?
你可以通过睡觉防止FPS升高。
至于防止FPS下降......
这是一个非常广泛的话题。让我们来看看。它是这样的:使用顶点缓冲对象或显示列表,profile application,不要使用疯狂的大纹理,不要使用太多的alpha混合,避免“RAW”OpenGL(glVertex3f),不要渲染不可见的对象(即使没有绘制多边形,处理它们也需要时间),考虑学习BSP或OCTrees来渲染复杂场景,在参数曲面和曲线中,不要不必要地使用太多基元(如果你使用一百万渲染一个圆圈)多边形,没有人会注意到差异),禁用vsync。简而言之 - 减少到绝对可能的最小渲染调用次数,渲染多边形数量,渲染像素数量,读取的纹素数量,从NVidia读取每个可用的性能文档,您应该获得性能提升。
答案 3 :(得分:1)
你绝对不想扼杀你的帧速率一切都取决于你得到了什么 继续在渲染循环中以及您的应用程序执行的操作。特别是它的 物理/网络相关。或者,如果您使用外侧工具包(Cairo,QPainter,Skia,AGG,...)进行任何类型的图形处理,除非您想要不同步结果或100%cpu使用。
答案 4 :(得分:0)
你问的是错误的问题。您的显示器只能以60 fps(欧洲50 fps,或者如果你是专业游戏玩家,可能是75 fps)显示。
相反,你应该寻求将你的fps锁定在60或30.有一些OpenGL扩展允许你这样做。然而,扩展不是跨平台的(幸运的是它们不是特定于视频卡的,或者它真的很可怕)。
wglSwapIntervalEXT
glXSwapIntervalSGI
这些扩展程序与您的监视器v-sync密切相关。一旦启用调用交换,OpenGL后台缓冲区将阻塞,直到监视器准备就绪。这就像在您的代码中进行睡眠以强制执行60 fps(或30或15或其他一些数字,如果您没有使用以60 Hz显示的显示器)。 “sleep”的区别总是完全定时,而不是基于最后一帧花费多长时间的有根据的猜测。
答案 5 :(得分:0)
Here is a similar question, with my answer and worked example
我也喜欢deft_code的答案,并会考虑将他建议添加到我的解决方案中。
我的答案的关键部分是:
如果您正考虑放慢速度并加快帧速度,那么您必须仔细考虑在每种情况下是否表示渲染或动画帧。在此示例中,简单动画的渲染限制与动画加速相结合,适用于在潜在的慢动画中丢帧的任何情况。
该示例适用于以相同速度呈现的动画代码,无论基准模式或固定FPS模式是否处于活动状态。在更改之前触发的动画甚至在更改后保持恒定速度。
答案 6 :(得分:0)
这段代码可以粗略地完成这项工作。
static int redisplay_interval;
void timer(int) {
glutPostRedisplay();
glutTimerFunc(redisplay_interval, timer, 0);
}
void setFPS(int fps)
{
redisplay_interval = 1000 / fps;
glutTimerFunc(redisplay_interval, timer, 0);
}