一、問題
在相機隨主角移動的過程中,發現地圖的細節部分不停的閃爍。我們用草地做背景,濾波模式設定為point,然後讓攝像頭沿著x軸緩慢移動,可以看到在移動過程中,的某些部分抖動得很厲害,這種程度的抖動對於一般遊戲來說都是不可以接受的,因此網上也有些解決方案,但大部分人對抖動的成因理解不夠,這篇文章將先分析抖動的成因,然後簡單介紹下抖動的解決方案。
二、成因
1. 螢幕實際上是乙個取樣器,它對影象取樣
2. 而根據奈奎施特取樣定理,取樣頻率必須至少是影象頻率的兩倍,取樣後的影象才能完整的代表原影象。
從這裡我們可以知道,螢幕解析度越低、高頻訊號越高,越容易產生抖動現象,比如把上圖的影象代替成乙個單色影象,顯然是不會發生抖動的。
ok,下面開始具體的分析了,我們把影象經過螢幕顯示的過程數學建模,影象經過螢幕顯示呈現到人們面前,實際上是分成了兩個步驟:
1. 取樣:影象處理器從影象中選取乙個或多個點平均,得到乙個rgba值,取樣在shader中用tex2d函式實現,opengl有幾種取樣方式gl_nearest, gl_linear和gl_linear_mipmap_linear,分別對應unity的point, bilinear和trilinear三種取樣模式。
2. 濾波:取樣後的rgba值通過畫素發光,這是乙個低通濾波器,把乙個沒有大小的rgba值顯示為乙個畫素大小的光點,可能大家對這步體驗不夠清楚,然而這確實有乙個低通濾波的過程,不然人們只能在螢幕上看到乙個個dirac函式陣列。
為了敘述方便,我們把討論侷限於一維空間。我們將討論乙個長度為1、高度(rgba值)為1的線段的在一維螢幕上的顯示過程,以及線段移動時,頻域的變化。下圖展示了小方塊經過取樣和低通濾波後在螢幕成像的空域和頻域流程圖:
圖(1)
圖中,寬度為1,坐落在座標中心的小方塊經過寬度為0.1(取樣頻率為10hz)的取樣函式取樣後,再經過乙個低通濾波函式,最終呈現在螢幕上。從上圖中可以看到,在空域,小方塊最後的樣子和最初的樣子寬度變化了些,在頻域,小方塊的高頻分量被削弱了。
從上圖,我們也很容易理解奈奎施特取樣定理,被取樣後的小方塊在頻域是多個波峰疊加,波峰之間的距離就是乙個取樣頻率,如果要求兩個波峰之間的頻譜不疊加,那麼其最高頻率的2倍必須不大於取樣頻率。
下面我們讓小方塊沿著x軸移動
經過取樣頻率為10hz的取樣函式取樣:
顯然,如果要讓小方塊在移動前和移動後,頻域大小保持不變,那麼可以令
頻域大小為:
也就是說,只要小方塊以整數倍取樣週期運動,那麼小方塊取樣頻域將保持不變,這也就是我們本文一開始的結論,扯了這麼多,無非是想說這個結論是有數學根據的。
三、在unity中的應用
1.在影象資源的製作過程中使用各種濾波函式來模糊影象;
2.在匯入資源時設定濾波模式為bilinear或者trilinear。
然而這兩種方式有時並不能完全解決抖動現象,尤其是在影象縮小時,這時頻域將擴大,而無視濾波。
我們還得想其他辦法,根據第二節的結論,只要小方塊以整數倍取樣週期運動,其頻域大小就不變,那麼只要影象以整數倍畫素大小移動,就不會發生抖動。目前的一般做法有兩種:
1. unity的sprites/default 這個shader帶有乙個pixel snap選項,選上該選項,sprite在渲染時,其頂點位置將snap到整數倍畫素位置,從而保證整個sprite能以整數倍畫素大小移動。
圖(2)
2. 在指令碼中把位移snap到整數倍畫素大小。這種方式在攝像頭移動時很方便,只要給攝像頭加乙個指令碼,就可以圓滿的解決這個問題。附件裡有這個指令碼,也很簡單。
四、總結
其實對於些螢幕解析度比較高,又不需要影象縮小,用bilinear濾波模式也就差不多了,這大概也是這個問題沒有多少人提及的原因吧。
抖動問題不限於螢幕取樣,在遊戲物件通過一系列變換過程中,如果其運算的截斷誤差(乙個取樣過程)經過放大,能夠在螢幕上顯示出來,就會產生問題。
VLANawareVM引發的問題和解決方法
vm能夠傳送和接收帶有vlan tag的報文,這種情況叫vlan aware vm。乙個可以vlan aware 的vm,意味著它可以接入多個network vlan 如下圖所示。在neutron模型中並沒有vm的概念,而是以port指代。我們先這樣簡單的理解port,port是vm的虛擬網口。在沒...
WordPress安裝遇到的問題和解決方案
在php.ini檔案中 新增 upload tmp dir tmp開啟配置檔案 vi etc httpd conf httpd.conf在httpd.conf中新增 virtual hosts include conf extra httpd vhosts.conf建立 配置extra httpd ...
Qt 編譯過程,出現的問題和解決方
在學習c gui qt4的過程中編寫hello程式 建立hello目錄 進入hello目錄,編寫hello.cpp程式檔案 進行編譯 生成乙個與平台無關的檔案 qmake project 輸入如下命令,從這個目錄檔案生成乙個與平台相關的makefile檔案 qmake hello.pro 鍵入mak...