我正试图在游戏中追踪每秒帧数。我不希望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 ();
}
答案 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)渲染你的框架
否则退出消息循环功能(并再次输入,或者暂时解决它,取决于你如何构建主循环的其余部分