2016-01-13 95 views
3

我使用Paul Irish的腳本 https://gist.github.com/paulirish/1579671 在html網站內部創建動畫循環。如何使用requestAnimationFrame鎖定FPS?

雖然它在全屏模式下比在瀏覽器窗口中更快,但它起作用。 此外,我觀察到不同的速度取決於畫布大小,並取決於我使用的瀏覽器。

問題:如何使用腳本確保穩定的幀頻?

代碼,請點擊這裏(WebGL的開始,第1章由Brian Danchilla): https://github.com/bdanchilla/beginningwebgl/blob/master/01/2D_movement.html

回答

1

像這樣的東西應該工作。如果兩幀之間的時間差異小於您的FPS限制,則更新函數返回並等待下一幀。但這隻會限制更新發生得太快;就像emackey說的那樣,更新循環總是有可能運行得更慢。

var updateId, 
    previousDelta = 0, 
    fpsLimit = 30; 

function update(currentDelta) { 
    updateId = requestAnimationFrame(update); 

    var delta = currentDelta - previousDelta; 

    if (fpsLimit && delta < 1000/fpsLimit) { 
     return; 
    } 

    /* your code here */ 

    previousDelta = currentDelta; 
} 
0

您不能直接強制執行穩定的幀速率。您的網頁不是在用戶平臺上運行的唯一應用,平臺功能差異很大。​​儘可能快地運行,不超過目標設備上的顯示更新間隔,但可能會慢得多,具體取決於可用的CPU,GPU,內存和其他限制。

此處的標準做法是測量自上一個動畫幀(通常爲Date.now())以來已經過去的時間量,並且每幀將動畫提前一段時間。對於人眼而言,即使幀速率高度變化,這也會使得動畫以一致的速度運行。

例如,網站,如ShadertoyGLSL Sandbox全屏運行GLSL着色器和通過在稱爲time(或iGlobalTime)均勻,這是代表由於着色器開始經過的秒數一個float。這個時間值以不規則的間隔增加,這取決於每個動畫幀需要渲染多長時間,但結果是浮點數似乎以每秒穩定1.0的速度向上計數。這樣,基於此時間值的着色器回放可以看起來一致。

2

美化什麼@emackey說,

簡短的回答是你不能。你可以讓計算機在每一幀中完成無限量的工作。我不能保證在有限的時間內完成這項工作。

最重要的是,每臺電腦有不同的電量。廉價的集成GPU比高端顯卡功耗低得多。英特爾i3比i7慢得多。

您還提到更改畫布大小。繪製300x150的畫布只有45000像素的工作量。繪製一個1920x1080的畫布將是2,073,600像素的工作或46x更多的工作

您可以做的最好的工作是儘可能減少工作量,或者自動或通過用戶選擇在慢速硬件上刪除功能。大多數遊戲都這樣做。他們的圖形設置選項,用戶可以選擇分辨率,紋理水平,抗混疊水平和其他各種各樣的東西。這就是說,你可以嘗試做你的計算,使你的應用程序中的事物以相對於時間的一致速度移動。在較慢的機器上或較大的畫布上,幀率可能較慢,但每秒移動的距離仍保持不變。

您可以通過使用經過的時間值做到這一點爲​​

function render(time) { 
    // time is time in milliseconds since the page was loaded 

    ...do work... 

    requestAnimationFrame(render); 
} 
requestAnimationFrame(render); 

例如這裏是幀率獨立動畫

function render(time) { 

    xPosition = xPosition + velocity; 

    ... 

    requestAnimationFrame(render); 
} 
requestAnimationFrame(render); 

和這裏的幀速率獨立動畫

var then = 0; 
function render(time) { 
    var timeInSeconds = time * 0.001; 
    var deltaTimeInSeconds = timeInSeconds - then; 
    then = timeInSeconds; 

    xPosition = xPosition + velocityInUnitsPerSecond * deltaTimeInSeconds; 

    ... 

    requestAnimationFrame(render); 
} 
requestAnimationFrame(render); 

注意:傳入requestAnimationFrame的時間比Date.now()

Here's an article on it with animations

更高的分辨率