2010-02-14 114 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)使您的框架

否則退出消息循環功能(並再次輸入,或用而解決這個問題,取決於你如何組織你的主循環的休息了一下

相關問題