2010-02-14 33 views
2

我想跟踪我的游戏每秒帧数。我不希望fps显示为平均值。我想看看当我按下按键和添加模型等时帧频如何受到影响。所以我使用一个变量来存储当前时间和以前的时间,当它们相差1秒时,我更新fps。我不明白为什么这个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

这个问题的答案取决于你如何生成你的框架以及代码在你的渲染循环中的位置 – ChrisF 2010-02-14 16:44:33

回答

1

这是因为您获得更多的鼠标消息的消息处理循环而不是阻塞偷看或轮询,作为FPS增加的迹象。您应该考虑使用PeekMessage而不是GetMessage

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

您可以任选两种PM_NOREMOVE或 PM_REMOVE结合的价值 PM_NOYIELD。该标志防止 系统释放任何线程, 正在等待呼叫者空闲 (请参阅WaitForInputIdle)。

+0

我想发布我的消息处理循环但是我不能让代码格式化这些评论框我必须格式化它,而不是在问题框中吗? – rmetzger 2010-02-14 18:54:32

+0

@rmetzger,只需将它添加到原始问题文章 – MSN 2010-02-14 20:23:44

0

更多一个侧面说明不是回答你的问题,但你说你不想平均帧率,但是你有效地通过计算它这样平均起来超过一秒钟。如果你想拥有帧率更新每一帧,你可能想尝试这样的:

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

虽然timeGetTime将开始在这一点上是有点不准确,因为这些数字很可能是小的。 QueryPerformanceCounter可能是一个更好的使用计时器。

+0

1秒平均而言,它在屏幕上的更新速度比我能读的更快。我只是不想从节目开始以来的平均fps,或者乘以一些因素来衡量它。例如,我看到这个在另一个线程: “你需要平滑平均值,最简单的方法是采取目前的答案,并与以前的答案结合起来(绘制最后一帧的时间) 时间=时间* 0.9 + last_frame * 0.1“ 除非我误解了这一点,这是不是结合了最后的fps和所有fps的平均值? – rmetzger 2010-02-14 18:43:02

+0

对不起,上面的格式。我不知道为什么它不会让我做一个块引用或代码格式。 – rmetzger 2010-02-14 18:45:38

+0

您所描述的平均值有一个加权平均值,它将密切跟踪最新的时间点,但在此过程中也会始终受到峰值的影响。我不会担心你的时间码,因为你的目的很好。也许可以将更新速率提高到每秒两次,或者将其绘制为条形图以更轻松地查看效果。 – Kylotan 2010-02-16 10:15:43

0

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

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

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

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

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

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

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

+0

那么我现在使用if-else语句。我很积极,我只是每帧更新一次fps计数器。 我之前使用箭头键移动我的相机。我评论了关键的处理代码,fps没有改变。我无法在任何地方获得或处理我的程序中的鼠标输入。我的fps计数器显示在31-34 fps之间。但是当我移动鼠标时,它仍然跳到48-50。 我不确定这是否相关,但是当我绘制模型时,我的fps介于40-48之间,并且非常不一致。当我移动鼠标时,fps再次达到48-50。 – rmetzger 2010-02-17 02:41:12

0

关于消息循环 - 我建议偷看消息,直到你没有得到任何和然后呈现一个框架。

Pseudo:

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

如果(renderFrame)使您的框架

否则退出消息循环功能(并再次输入,或用而解决这个问题,取决于你如何组织你的主循环的休息了一下

相关问题