2

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

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

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

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

5 回答 5

2

timeGetTime() 不准确。请改用高性能计数器

示例代码在另一个答案中。

于 2010-02-16T16:46:02.300 回答
1

这表明您的消息处理循环正在阻塞而不是偷看或轮询,因为随着您收到更多鼠标消息,fps 会增加。您应该考虑使用PeekMessage而不是GetMessage.

编辑:另外,如果你想占用 CPU,你也可以添加PM_NOYIELD,这样系统就不会允许其他线程在PeekMessage. 来自PeekMessage的文档

您可以选择将值 PM_NOYIELD 与 PM_NOREMOVE 或 PM_REMOVE 组合。此标志防止系统释放任何等待调用者空闲的线程(请参阅 WaitForInputIdle)。

于 2010-02-14T17:12:16.627 回答
0

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

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

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

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

是鼠标控制摄像头吗?如果是这样,您确定是鼠标输入导致 fps 增加而不是您面对的方向吗?

您确定您的 fps 代码每帧只运行一次吗?

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

于 2010-02-16T01:44:15.730 回答
0

关于消息循环 - 我建议您先查看消息,直到您没有收到任何消息,然后再渲染一个帧。

伪:

布尔渲染帧=真;if (PeekMessage(...)) { // 处理它。渲染帧=假;}

if (renderFrame) 渲染你的框架

否则退出消息循环函数(然后再次输入它,或者用一段时间解决它,这在一定程度上取决于您如何构建主循环的其余部分

于 2010-05-23T00:52:58.090 回答
0

更多的是附注而不是您的问题的答案,但是您说您不想平均帧速率,但是通过这样计算,您可以在一秒钟内有效地平均它。如果您希望每帧更新帧率,您可能需要尝试以下操作:

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

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

于 2010-02-14T17:23:22.877 回答