我无法弄清楚为什么这个fps计数器不准确

时间:2010-02-14 16:39:45

标签: frame counter frame-rate

我正试图在游戏中追踪每秒帧数。我不希望fps显示为平均值。我想看看当我按下按键并添加模型等时帧速率是如何受到影响的。所以我使用变量来存储当前时间和上一次,当它们相差1秒时,我更新了fps。

我的问题是它显示大约33fps但是当我快速移动鼠标时,fps跳升到49fps。其他时候,如果我更改了一个与帧计数器无关的简单代码行,或者关闭项目并稍后打开它,则fps将在60左右.Vsync打开,所以我无法判断鼠标是否仍在影响fps。

这是我的代码,它位于每帧发生的更新函数中:

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;
}

以下是变量声明:

int FrameCount;
double fps, currentTime, prevTime, TimeDelta, TimeElapsed;

请告诉我这里有什么问题以及如何解决,或者你有更好的方法来计算fps。感谢!!!!!!

我正在使用DirectX 9顺便说一句,但我怀疑这是否相关,我正在使用PeekMessage。我应该使用if else语句吗?这是我的消息处理循环:

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 ();
}

5 个答案:

答案 0 :(得分:2)

timeGetTime()不准确。请改用high performance counter

Sample code在另一个答案中。

答案 1 :(得分:1)

这表示您的邮件处理循环阻塞而不是偷看或轮询,因为fps会在您收到更多鼠标邮件时增加。您应该考虑使用PeekMessage而不是GetMessage

编辑:此外,如果您想占用CPU,还可以添加PM_NOYIELD,以便系统在PeekMessage期间不允许其他线程执行。 From PeekMessage's documentation

  

您可以选择组合该值   PM_NOYIELD与PM_NOREMOVE或   PM_REMOVE。这个标志阻止了   系统发布任何线程   正在等待呼叫者闲置   (参见WaitForInputIdle)。

答案 2 :(得分:0)

更多的旁注而不是问题的答案,但是你说你不想平均帧速率,但是你通过计算它就可以有效地平均它一秒钟。如果您希望每帧更新帧速率,您可能需要尝试类似:

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

虽然timeGetTime此时开始有点不准确,因为数字可能很小。 QueryPerformanceCounter可能是一个更好的计时器。

答案 3 :(得分:0)

关于你的消息处理循环,是的,你应该像这样使用if-else语句。

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

否则每帧只会处理一条消息,如果帧需要很长时间才能渲染,会导致严重的输入延迟。

关于你的FPS读数,继续下去并不多,任何数量的事情都可能影响它。 fps计数器代码看起来应该执行它的目的(但有一些精度损失)..

鼠标是否控制相机?如果是这样,你确定它是鼠标输入导致fps增加而不是你面对的方向吗?

你绝对确定你的fps代码每帧只运行一次吗?

你在某处处理输入吗?如果是这样,如果禁用该代码并快速移动鼠标会发生什么?还是一样吗?

答案 4 :(得分:0)

关于消息循环 - 我建议先查看消息,直到你没有得到任何消息然后然后呈现一个帧。

伪:

bool renderFrame = true; if(PeekMessage(...)) { // 处理它。 renderFrame = false; }

if(renderFrame)渲染你的框架

否则退出消息循环功能(并再次输入,或者暂时解决它,取决于你如何构建主循环的其余部分