為什麼要把資源貼圖都放在一張圖上?

如圖,為什麼要把資源貼圖都放在一張圖上?而不是分別做成一個一個的多張圖片


比如在OpenGL里,貼圖單元數量是有限的,假設最壞情況只支持1個貼圖單元,這時候你有一個2D角色的兩個對象實例,分別正處於不同的動作幀,你如果沒有用貼圖合併技術把同一角色所有幀都合到一張貼圖,那麼要繪製這兩個對象就會提交兩次貼圖,如果是合併貼圖就只需要提交一次,然後通過在shader裡面取不同的坐標來獲得對應動作的貼圖。

同理,推廣到一個遊戲場景,有各種特效和角色,儘可能合併貼圖帶來的好處就是執行效率的提升。

比如顯卡支持10個貼圖單元,那麼你可以盡量把當前場景用到的各種貼圖提交上去,然後把對象的頂點信息一次性提交上去,最好情況是只要一次貼圖提交和一次draw call。

更極端點,你的場景對象沒有變化的情況下,之後的所有幀,你都不用重新提交貼圖了,只需要每幀提交對象的頂點信息就可以了。


如果用同一個材質(紋理+shader) 可以做batching,有效降低draw call

特別是UI部分,恩。。。這個對性能是有好處滴


瀉藥,不過沒太看明白你的問題和附圖。

===================================================================

假如是圖標類的資源,比如我現在程序裡頭或者遊戲裡頭要用到如上的25個圖標資源,如果分段載入的話,難於管理、命名和控制。打個比方,比如我現在拿Delphi來寫的話,25個圖標資源對應25個Image控制項吧,然後一個個載入,就顯得很麻煩。

如果把這25個控制項編製成一個控制項數組,然後用統一載入該圖,只不過顯示區域不同而已。這樣寫起來就快了很多,而且方便。要是你要換一個圖標,只要把這幅圖上的圖標扣掉換了就行,代碼完全不用改。

=====================================================================

對於某些2D遊戲而言,人物動畫幀如果分開的話,需要一幅幅載入,耗時且占內存,不方便管理和調用。如果把它們做成一副圖片,幀與幀之間等距離的話,一次只需載入一次,而且播放到第幾幀,就直接把顯示區域往後挪第幾塊,方便快捷。

咳咳,就是苦了美工。

=====================================================================

不過題主的附圖顯得略微雜亂,按理說寧可餘下些空白也要分門別類地把圖片規劃好,我感覺那個不像是一個資源圖片,要是真這樣的話估計需要一個專門的數據文件來記錄顯示區域……

作為未來的手游策劃我只能說這麼多,反正還沒進這個行業,說錯了還請見諒


如果是手游的話,那是由於歷史原因造成的。

在openGL ES 1.0的時代,要求貼圖的尺寸都必須是2的整次冪,所以即使是一個513x513的圖片,也會創建一張1024x1024的貼圖。如果遊戲的圖片比較多的話,這個浪費的內存還是相當可觀的。

於是出現了一種技術,就是把多個不同給的小圖片整合到一張大的2的整次冪的圖片中,這樣有幾個好處,一個是節省了很多內存,一個是免去了很多的文件操作次數。

後來因為這個方法太普遍,於是出現了很多的商業工具專門做這個事情,比如TextarePack之類的。商業工具可以設定各種配置以及輸出格式,甚至旋轉圖片以為了盡量利用整張大圖。

當然,在openGL ES 2.0之後,這條限制被去掉了。這麼做的也少了很多。


這就是個坑。

由於歷史原因,API 能能綁定的貼圖數量是有限的,比如一次只能填 128 個坑。

想切換貼圖必須把原先佔坑的貼圖換出來,換坑是很耗費時間的操作(你得讓之前坑裡的把事情做完吧,等啊等),因此遊戲中希望儘可能減少這類操作。

怎麼辦呢?就是把不同的貼圖合起來……

等於是一個坑裡佔了好幾張圖片(稍微擠擠還是擠得下的),就不需要那麼頻繁得換貼圖了。

這就是歷史原因。

現在的話,新的 API 都開始支持無坑模式(bindless texture),也就是可以隨便綁定貼圖,這種技術也就不那麼重要了!


站在遊戲開發者的角度說一下

簡單說我不想維護那麼多的文件。

資源貼圖的數量跟著遊戲規模幾何上升,如果一張圖一個文件的話,海量的文件會讓你欲仙欲死。

且不說讀取大量小圖片文件的速度遠遠比不上讀取單個大圖片文件,你看著那麼多玩藝兒都不舒服啊。更不要說編輯起來也很麻煩了.

然後從代碼角度,在D3D11中,維護一張紋理圖片,需要一個ID3D11ShaderResourceView介面。如果用多個文件,那麼每個文件都需要一個介面來維護之。對程序來講也是個不小的負擔。

而且,圖形引擎本身就支持裁切紋理操作。合適的使用紋理坐標,你就可以從一大張圖上裁切下任何一個矩形區域的小圖。這樣做的效率也是很高的。


基本上大家的原因都有..早期做端游的時候.為了符合大眾配置以及假設的最低配置..我們會假設玩家的設備是不支持非2的冪的紋理的...100*100的紋理創建的時候都會默認被創建為128*128..會有存儲上的浪費...解決這種問題就是將圖拼到2的冪尺寸的圖片上...預先生成或者動態合圖

後來基本所有的硬體都支持非2的冪尺寸的圖..不過冪次方的圖片理論上還是比其他尺寸在使用上是更合適的...

後來作為手機設備這種優化方案被保留下來了...但是因為性能原因除了聊天字體曾經使用動態合圖之類似題主這樣的UI基本都是預先合圖..可以將UI按場景分類然後提前合在一張紋理上..這樣場景UI在同一紋理不管層次如何都可以一次提交到顯存..減少Drawcall來優化性能...甚至有些UI設計師風格統一二三級窗口都是九宮格等...一張大紋理基本能擺下所有的UI...免去了多個小圖片的I/O以及解碼...在loading時期就載入完畢...大大解決遊戲中打開窗口時因為圖片載入解碼產生的卡頓重要的是所有UI一個批次就可繪製完成

事實上細碎的圖片儲存上也會比合在一起的整圖大.不管是存儲在硬碟還是顯存中

總的來說優點很多

以上來自個人職業生涯經驗以及看法


載入多個尺寸不定的貼圖時, 顯存會出現碎片空間,為了更好利用有限的資源,這是一個好idea.


webgame的話,據說是一張圖比多張圖下載得塊


節省資源和載入時間。


如果是web應用的話一張圖和多張圖的區別就是:一個是建立一次網路鏈接和多次網路連接的區別。

另外如果圖片下載完畢後,所有使用這張圖片的元素會同時展現給用戶,而不是一塊塊的。


在這裡提一個問題

讀取這些貼圖有規則嗎?圖可以隨意畫,但是程序怎麼知道把圖片哪一部分貼到對應物體?


推薦閱讀:

如何評價國產動畫《幻鏡諾德琳》?
為什麼《請問您今天要來點兔子嗎》這類萌系動畫從今年下半年開始就人氣飆升呢?
柯南從某些方面來看是否是一部失敗的漫畫?
動漫中有哪些黑色波浪發的美麗女性?
原力動畫這間公司目前是怎樣的?

TAG:動畫 | 遊戲設計 | 編程 | OpenGL | 貼圖 |