我不明白为什么这个 fps 计数器不准确

发布于 2024-08-21 00:47:55 字数 1106 浏览 6 评论 0原文

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

我的问题是它显示大约 33fps,但是当我快速移动鼠标时,fps 跳到 49fps。其他时候,如果我在其他地方更改与帧计数器无关的简单代码行,或者关闭项目并稍后打开它,则 fps 将在 60 左右。垂直同步已打开,因此我无法判断鼠标是否仍在起作用每秒帧数。

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

献世佛 2024-08-28 00:47:55

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

示例代码位于另一个答案中。

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

Sample code is in this other answer.

Hello爱情风 2024-08-28 00:47:55

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

编辑:此外,如果您想占用 CPU,还可以添加 PM_NOYIELD,这样系统就不会允许其他线程在 PeekMessage 期间执行。 来自 PeekMessage 的文档< /a>:

您可以选择组合该值
PM_NOYIELD 与 PM_NOREMOVE 或
PM_删除。该标志可防止
系统释放任何线程
正在等待呼叫者空闲
(请参阅 WaitForInputIdle)。

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).

愁以何悠 2024-08-28 00:47:55

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

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

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

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.

我不在是我 2024-08-28 00:47:55

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

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

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

关于 FPS 读数,没有什么可继续的,任何因素都可能影响它。
fps 计数器代码看起来应该能够执行其目的(但精度有所损失)。

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

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

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

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?

蹲在坟头点根烟 2024-08-28 00:47:55

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

伪:

bool renderFrame = true;
if (PeekMessage(...))
{
// 处理它。
渲染帧=假;
if

(renderFrame) 渲染你的框架

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文