开发者

I can't figure out why this fps counter is inaccurate

I'm trying to track frames per second in my game. I don't want the fps to show as an average. I want to see how the frame rate is affected when I push keys and add models etc. So I am using a variable to store the current time and previous time, and when they differ by 1 second, then I update the fps.

My problem is that it is showing around 33fps but when I move the mouse around really fast, the fps jumps up to 49fps. Other times, if I change a simple line of code elsewhere not related to the frame counter, or close the project and open it later, the fps will be around 60. Vsync is on so I can't tell if the mouse is still effecting the fps.

Here is my code which is in an update function that happens every frame:

FrameCount++;
currentTime = timeGetTime ();
static unsigned long prevTime = currentTime;
TimeDelta = (currentTime - prevTime) / 1000;
if (TimeDelta > 1.0f)
{
 fps = FrameCount / TimeDelta;
 prevTime = currentTime;
 FrameCount = 0;
    TimeDelta = 0;
}

Here are the variable declarations:

int FrameCount;
double fps, currentTime, prevTime, Ti开发者_Go百科meDelta, TimeElapsed;

Please let me know what is wrong here and how to fix it, or if you have a better way to count fps. Thanks!!!!!!

I am using DirectX 9 btw but I doubt that is relevant, and I am using PeekMessage. Should I be using an if else statement instead? Here is my message processing loop:

MSG msg;
ZeroMemory (&msg, sizeof (MSG));

while (msg.message != WM_QUIT)
{
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

    Update ();
    RenderFrame ();
}


timeGetTime() is inaccurate. Use the high performance counter instead.

Sample code is in this other answer.


This is a sign that your message processing loop is blocking instead of peeking or polling, as the fps increases as you receive more mouse messages. You should consider using PeekMessage instead of GetMessage.

EDIT: Also, if you feel like hogging the CPU, you can also add PM_NOYIELD so that the system won't allow other threads to execute during PeekMessage. From PeekMessage's documentation:

You can optionally combine the value PM_NOYIELD with either PM_NOREMOVE or PM_REMOVE. This flag prevents the system from releasing any thread that is waiting for the caller to go idle (see WaitForInputIdle).


More of a side note than an answer to your problem, but you say you don't want to average the framerate, however you're effectively averaging it over a second by calculating it like that. If you want to have the framerate updated every frame, you might want to try something like:

currentTime = timeGetTime();
fps = 1000.0f / (currentTime - prevTime);
prevTime = currentTime;

Though timeGetTime is going to start to be a bit inaccurate at this point, as the numbers are likely to be small. QueryPerformanceCounter might be a better timer to use.


Concerning your message processing loop, yes you should use an if-else statement like so.

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage (&msg);
    DispatchMessage (&msg);
} 
else
{
    Update ();
    RenderFrame ();
}

Otherwise only one message per frame would be processed, which would result in serious input-lag if the frame takes a long time to render.

Concerning your FPS readings it's not much to go on, any number of things could affect it. The fps counter code looks like it should be performing it's purpose (but with some loss of precision)..

Is the mouse controlling the camera? If so, are you sure it's the mouse input that cause the fps increase and not what direction you are facing?

Are you absolutely sure that your fps code is only run once per frame?

Do you handle input somewhere? If so what happens if you disable that code and move the mouse fast then? Still the same?


About the message loop - I advise peeking for messages until you're not getting any and then rendering a frame.

Pseudo:

bool renderFrame = true; if (PeekMessage(...)) { // Handle it. renderFrame = false; }

if (renderFrame) render your frame

otherwise exit the message loop function (and enter it again, or solve it with a while, depends a bit on how you've structured the rest of your mainloop

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜