大家玩遊戲這麼多年,或許都會有那麼幾個雲牽夢繞的疑問:為什麼2D像素化的古董超級馬裡玩起來不卡,但3D遊戲確卡了?為什麼電影每秒24幀不覺卡?但遊戲沒30幀就得卡成汪星人?雖然網上有各種各樣的回答,但很多都不盡科學不夠全面,所以筆者還是來全面科普一下吧。
生理基礎
電影膠捲記錄的逐幀信息
所有的故事都要從人類肉眼的「視覺暫留」和「腦補」現象說起,前者是指人類視網膜在光信號消失後,殘像還會保留一定時間的現象;後者是大腦自行補足畫面中間幀的「腦補」功能。它們的混合作用,讓我們誤以為每秒24幀回放的照片是「連續」的。
而至於為什麼要把數字定在24,這裡面更多是約定俗成和玄學,電影規格本身也經歷了16到24幀的轉變,這個數字以後估計也會繼續增長。而PAL/NTSC/SECAM三種電視信號規格,把幀數定在每秒25幀和30幀的原因,其實只是因為不同地區的供電頻率不同(50Hz和60Hz)……為了方便計算,採用NTSC制式的美國和日本,在遊戲中很自然地了沿用了每秒30幀的習慣(NTSC制式為29.97幀)。
但為什麼看24幀的電影毫無違和感,但30幀,甚至60幀的遊戲中也會出現卡頓?這裡直接說結論,決定遊戲流暢度有4個:動態模糊效果、操作響應、幀率和幀率均勻度,當中以動態模糊最為重要。
動態模糊動態模糊,是指相機快門慢於物體運動而導致的運動軌跡拖影。3D遊戲和電影的重要差別:電影是現實光影的記錄,而3D遊戲是3D模型形狀/位置的實時渲染,前者會有動態模糊,而後者不會。
電影是恆定頻率的拍攝的膠捲/數碼照片,它可以完整記錄一段時間內的光線信息。一般24幀每秒的視頻會選取高一倍的1/50秒的快門,可以完整記錄半秒的光線信息。而這些「多出來」的豐富圖像信息,會像重影一樣疊在一起而造成動態模糊/拖影,其原理和「光繪」一樣,只是快門不是幾秒,而是1/50秒。
高快門速度的樣張
低快門速度的樣張
在人類大腦中,動態模糊是視覺信息量的一個重要表現,即使實際看到的幀數不夠,加入動態模糊的間隔畫面也足夠我們用來進行腦補,從而實現「流暢」。另外,偏題一下,如果同樣的每秒24幀,如果快門速度提高到1/96秒,那膠捲中記錄的光線信息只有1/4秒(24*1/96),丟失的光線信息會讓模糊效果減弱,這樣的電影看起來也是會有卡頓感的。
左側為不同快門速度記錄的光線信息量(快門越慢,記錄的光線越多),右為實際畫面
而遊戲則是把這個「快門速度」提升到極致的產物,遊戲中的30幀,是遊戲引擎生成的30個無限短的瞬間畫面,而且這些瞬間無論多快,物體本身都是清晰無比,絕壁不會有模糊效果。如果這時候還以24幀每秒播放,大腦會抗議,這貨動得這麼快,為什麼我還看得那麼清楚,完全不科學啊,結果「腦補流暢度畫面」過程就無法進行,我們就真的在看播幻燈片了。
要解決這個問題,要不提高取樣率,要不就人為增加模糊效果。前者是下面會說到的高幀率方案,而後者就是增加模糊效果欺騙大腦,讓它以為自己看到是高信息量的畫面(然而模糊效果也很耗資源)。
幀率大小
遊戲中的物體如果每秒移動1個像素點,我們或許還能覺得流暢,但如果物體每秒移動10個像素點,那就有明顯段落感了。這時候需要提高取樣率,把中間缺掉的畫面補出來,如果幀數提高到每秒10幀,我們就可以看到接近剛才1秒1個像素點的流暢度了。
通過把每秒24幀的畫面,提升到每秒48、甚至60幀,雙眼接收到的信息量大到一定程度,就足夠用來「腦補」出流暢效果了。雖然最完美的遊戲應該是要幀數儘可能地多,那樣才是真正模擬現實情況,但對於遊戲來說,渲染幀數越多,需要的性能就越高,這個方案的代價太大了。而現在大家公認的是,做到30幀就能完成腦補過程了。
幀率均勻度
然而實際遊戲中,30幀照樣會時有卡頓,甚至提升到60幀也還是會卡。平時我們擼手機評測的時候,經常兩部不同GPU的手機,就算顯示的FPS(每秒的幀數)相同,照樣也是會有流暢度差異,這是為什麼呢?
兩款顯卡的幀數對比
兩款顯卡幀渲染時間對比
這裡的問題出在了「幀」的精確上。即使之前時間都能30幀以上渲染,但只要有那麼幾個瞬間跌破30幀,那依舊是卡。理想情況下的30幀每秒,是30幀均勻分布,但實際上有可能前半秒渲染29幀,最後的整整半秒只渲染了1幀。
因為運算能力和畫面複雜度的限制(例如從平原中突然有巨大爆炸的畫面),前半秒渲染壓力小,可以滿幀跑。但一到爆炸場景,運算量暴增,來不及渲染,後面幀數就下降了。肉眼雖然對幀數的絕對值不敏感,但明顯的幀數變化還是能輕易地察覺的。
很明顯平時我們看的FPS(每秒幀數)的精度完全不夠用,我們需要把精度,從每秒多少幀,提升到每毫秒多少幀才能精確衡量幀率的穩定性。
響應時間與跟手度
遊戲和電影的最大區別是,遊戲是需要用戶做出動作並對動作進行實時反饋的。除了視覺流暢,我們還需要操作流暢。大家追求60幀高幀率的重要原因,為的就是降低響應時間。我們感知一個動作是否完成,是要機器接受操作信息,並最終反映在下一幀中才算完成。而實際操作中,大多數遊戲引擎在接受操作指令後,要3幀間隔才能體現在畫面上。
幀數刷新速度越高,我們能感知的操作速度就越快。30幀的遊戲,即使忽略操作指令傳輸速度,每個畫面持續33毫秒(1s/30=0.033s),一個操作需要100毫秒(33毫秒*3幀)才能反映在畫面上,而60幀的遊戲,則只需要50毫秒就能響應過來了。這50毫秒,在遊戲中很有可能決定你是爆別人頭,還是被人爆頭了。
另外,如果出現畫面壓力太大,機器來不及渲染,畫面出現掉幀甚至卡頓,我們的操作指令也是會被順延輸入的。效果就是我們幾秒前的做的操作,在幾秒後才逐一顯示在畫面上,這就是傳說中的卡成翔了……