setting max frames per second in openGL

2020-05-27 11:36发布

Is there any way to calculate how much updates should be made to reach desired frame rate, NOT system specific? I found that for windows, but I would like to know if something like this exists in openGL itself. It should be some sort of timer.

Or how else can I prevent FPS to drop or raise dramatically? For this time I'm testing it on drawing big number of vertices in line, and using fraps I can see frame rate to go from 400 to 200 fps with evident slowing down of drawing it.

7条回答
时光不老,我们不散
2楼-- · 2020-05-27 11:53

This code may do the job, roughly.

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);
}
查看更多
成全新的幸福
3楼-- · 2020-05-27 12:01

Rule #1. Do not make update() or loop() kind of functions rely on how often it gets called.

You can't really get your desired FPS. You could try to boost it by skipping some expensive operations or slow it down by calling sleep() kind of functions. However, even with those techniques, FPS will be almost always different from the exact FPS you want.

The common way to deal with this problem is using elapsed time from previous update. For example,

// 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.
}
查看更多
淡お忘
4楼-- · 2020-05-27 12:02

You absolutely do wan't to throttle your frame-rate it all depends on what you got going on in that rendering loop and what your application does. Especially with it's Physics/Network related. Or if your doing any type of graphics processing with an out side toolkit (Cairo, QPainter, Skia, AGG, ...) unless you want out of sync results or 100% cpu usage.

查看更多
Lonely孤独者°
5楼-- · 2020-05-27 12:04

Here is a similar question, with my answer and worked example

I also like deft_code's answer, and will be looking into adding what he suggests to my solution.

The crucial part of my answer is:

If you're thinking about slowing down AND speeding up frames, you have to think carefully about whether you mean rendering or animation frames in each case. In this example, render throttling for simple animations is combined with animation acceleration, for any cases when frames might be dropped in a potentially slow animation.

The example is for animation code that renders at the same speed regardless of whether benchmarking mode, or fixed FPS mode, is active. An animation triggered before the change even keeps a constant speed after the change.

查看更多
仙女界的扛把子
6楼-- · 2020-05-27 12:12

Is there any way to calculate how much updates should be made to reach desired frame rate, NOT system specific?

No.

There is no way to precisely calculate how many updates should be called to reach desired framerate.

However, you can measure how much time has passed since last frame, calculate current framerate according to it, compare it with desired framerate, then introduce a bit of Sleeping to reduce current framerate to the desired value. Not a precise solution, but it will work.

I found that for windows, but I would like to know if something like this exists in openGL itself. It should be some sort of timer.

OpenGL is concerned only about rendering stuff, and has nothing to do with timers. Also, using windows timers isn't a good idea. Use QueryPerformanceCounter, GetTickCount or SDL_GetTicks to measure how much time has passed, and sleep to reach desired framerate.

Or how else can I prevent FPS to drop or raise dramatically?

You prevent FPS from raising by sleeping.

As for preventing FPS from dropping...

It is insanely broad topic. Let's see. It goes something like this: use Vertex buffer objects or display lists, profile application, do not use insanely big textures, do not use too much alpha-blending, avoid "RAW" OpenGL (glVertex3f), do not render invisible objects (even if no polygons are being drawn, processing them takes time), consider learning about BSPs or OCTrees for rendering complex scenes, in parametric surfaces and curves, do not needlessly use too many primitives (if you'll render a circle using one million polygons, nobody will notice the difference), disable vsync. In short - reduce to absolute possible minimum number of rendering calls, number of rendered polygons, number of rendered pixels, number of texels read, read every available performance documentation from NVidia, and you should get a performance boost.

查看更多
不美不萌又怎样
7楼-- · 2020-05-27 12:17

You have two different ways to solve this problem:

  1. Suppose that you have a variable called maximum_fps, which contains for the maximum number of frames you want to display.

    Then You measure the amount of time spent on the last frame (a timer will do)

    Now suppose that you said that you wanted a maximum of 60FPS on your application. Then you want that the time measured be no lower than 1/60. If the time measured s lower, then you call sleep() to reach the amount of time left for a frame.

  2. Or you can have a variable called tick, that contains the current "game time" of the application. With the same timer, you will incremented it at each main loop of your application. Then, on your drawing routines you calculate the positions based on the tick var, since it contains the current time of the application.

    The big advantage of option 2 is that your application will be much easier to debug, since you can play around with the tick variable, go forward and back in time whenever you want. This is a big plus.

查看更多
登录 后发表回答