mipmap的優點具體是什麼?

我知道的是加了mipmap那麼shader工作使用的紋理就是那張小圖,可以大大減少帶寬。

不確定的是,假如一個小區域用大貼圖且沒有mipmap,紋理採樣的性能損失具體有多少?比如一個屏幕像素點的位置下有16個紋理里的像素,它是把他們全部採樣還是選了它們最靠近中間的那個?

另外mipmap是否會根據需要只上傳小圖進入顯存?

Mipmap需要的情況下絕對不能關我知道,但我想明確其理由。畢竟現在太多只在乎那30%額外體積的人了。

順便問個事,紋理採樣都是在單獨的單元內進行的,是否意味著只要沒達到瓶頸,便可以無代價地使用消耗更大的各項異性過濾?


  1. 不用mipmap的話,性能損失主要在於texture cache會很難命中,因為相鄰pixel採樣的texel都是空間不連續的。SSAO演算法也會遇到這個問題。因為SSAO一般會使用雜訊來降低單個像素的採樣次數,所以相鄰pixel採樣的texel會距離很遠,對cache非常不友好。而nvidia的HBAO+就使用了Interleaved Rendering來解決這個問題。具體優化方法就不詳述了,現在HBAO+是開源的,有興趣的話可以去Github看下源碼。
  2. 不管一個pixel覆蓋多少個texel,point採樣1個,bi-linear採樣4個,tri-linear採樣8個,anisotropic則可能會採樣更多。mipmap就是為了解決1個像素覆蓋很多個texel的情況,相當於離線計算好1個pixel覆蓋多個texel的結果,存在mipmap中。mipmap1是1個覆蓋4個,mipmap2是1個覆蓋16個······
  3. 我平時接觸的是dx11。據我所知,只有當顯存不夠了,才會將部分texture移出去,不然就始終是在顯存的。
  4. mipmap可以說是必須的,不然的話遠景頻率太高,畫面會閃爍個不停。就算只是用一個負的lodbias,畫面都會很閃,更別說完全不用mipmap了。
  5. sampler unit和shader unit是完全並行的,sampler返回結果之前,shader unit不會等待,而是去處理其他數據,所以理論上是正確的。

推薦一篇很不錯的文章(A trip through the Graphics Pipeline 2011),你可以從中了解很多底層相關的東西。


第一句說法是錯誤的

不叫使用那個小圖

也不會減少需要訪問紋素的次數(需要訪問的紋素的次數只和最終圖元光柵化後的像素數量和紋理的採樣方式有關)

mipmap只是會增加緩存命中率

因為採樣一次 實際上是把紋理這個採樣位置周圍的紋素數據都載入到緩存

如果沒有mipmap 紋理很大 採樣頻率卻很小的情況下

相鄰的兩個屏幕像素採樣的紋素差的很遠

此時會大大降低緩存命中率

不過mipmap主要的作用也不是為了提高性能

主要目的還是為了提高質量

因為數據頻率遠高於採樣頻率 會導致嚴重的失真

每次採樣需要訪問多少次紋素

是根據採樣方式決定的

和紋理是否是mipmap的無關

一般實現上來說

臨近採樣就只是訪問最近的一個紋素

線性就是訪問周圍4個

三次就是訪問8個

mipmap採樣 根據是否mipmap間是NEAREST或者LINEAR在1個或者2個mipmap層級間採樣 根據上面所說的採樣方式進行採樣 訪問紋素次數是一樣的或者是2倍

各項異性需要在紋理坐標變化速度快的方向進行多次採樣 最終把多次採樣結果進行混合的

根據各向異性採樣次數 需要訪問的紋素次數也是n倍

你恐怕還對帶寬有誤解

帶寬指的不是數據從系統內存傳輸到顯存需要的傳輸量

顯存足夠的情況下 紋理數據是一直存在於顯存的

帶寬指的是渲染時數據在顯存(實際上也不一定是顯存 現在GPU基本都支持DMA)和處理單元之間傳輸所需要的傳輸量

用不用mipmap和用不用各向異性採樣

是要看情況的

如果紋理大小和實際上最終圖元在屏幕上的大小始終差不多的情況下

就不需要mipmap

如果最終光柵化圖元像素的採樣坐標的ddx ddy幾乎是一樣的

就不需要各向異性

比如2D Sprite 就不需要各向異性

如果Sprite在屏幕上的最終大小几乎始終和紋理差不多大

就不需要mipmap


Mipmap的實質,是預先計算了一系列低通濾波的貼圖,以防止屏幕空間的低頻採樣造成貼圖空間的高頻卷回。


問題1、不確定的是,假如一個小區域用大貼圖且沒有mipmap,紋理採樣的性能損失具體有多少?比如一個屏幕像素點的位置下有16個紋理里的像素,它是把他們全部採樣還是選了它們最靠近中間的那個?

答案:採樣是根據演算法的,與是否mipmap關係不大,使用相同的採樣演算法,就沒有任何性能區別。opengl es是通過api glTexParameter設置採樣演算法,也就是設置紋理的filter,當filter為nearest的時候,就採樣一個點,linear的時候採樣周圍的四個點。如果開了mipmap,會多幾種mipmap特有的採樣演算法,GL_NEAREST_MIPMAP_NEAREST之類的,這樣採樣的點就要多一點了,簡單的說就是這樣的。複雜的說還是上鏈接吧。。。說起來比較複雜。。。http://geekfaner.com/shineengine/blog10_OpenGLESv2_9.html#glTexParameter

問題2、另外mipmap是否會根據需要只上傳小圖進入顯存?

答案:是的,這是自動的。所以用mipmap可以節省io,在手機中節省io就能減少發熱(不要認為io沒用哦,說不定fps都有可能bound在io上,我還真遇到過。。)

問題3、順便問個事,紋理採樣都是在單獨的單元內進行的,是否意味著只要沒達到瓶頸,便可以無代價地使用消耗更大的各項異性過濾?

答案:優化是木桶原則。紋理採樣佔用的是GPU時間,如果是CPU bound,那麼GPU怎麼造都隨便,不會影響FPS,但是也不是說沒有代價,因為內存和因為計算量變大造成的發熱,也是性能優化的關注點~


mipmap注意是要預先算好圖片縮小後的圖片,當顯示得Mesh因為種種原因被縮小(transform變化,相機變化)如果直接使用原圖就會過度採樣從而出現顏色信息會丟失,出現走樣的現象。而且如果開啟了抗鋸齒功能,就要耗費時間去反走樣。

而mipmap的消耗也很明顯,圖片不管是硬碟佔用內存佔用還是顯存都會提升相應的倍數,可以說這是一種用空間換時間的方式。(我用工具抓過顯卡裡面的圖片,不是小圖是大圖,當然送到cache的是小圖是可以防止cache Miss的)

不過類似使用正交相機,並且不會對一種原圖進行過度縮放可以考慮關閉mipmap……一種情況要注意:自適應UI的時候,如果屏幕解析度很小而製作規格很大就要作死了,所以一般UI還是選擇在低解析度下製作,為了顯示更加清晰而選擇在1080P下作死,最好開啟mipmap

透視相機沒的說,必須開啟mipmap……


mipmap主要是用來減輕透視紋理採樣出現的混疊現象。這是跟採樣理論相關的。 就好比透視投影校正。

像你說的什麼小區域使用大的紋理,這裡就不談什麼性能問題,因為在特定的透視投影下,得到的視覺效果都是過不了關的。

可以參考《real time rendering》3rd、《Fundamentals of Computer Graphics》4th.


近了給你看大圖,遠了給你看小圖。你生活中不也是這樣嘛。那如果是正交ui就不用mip。生活中也是這樣嘛。

有個好玩兒的地方就是給texture的mip每一級傳入不同的圖紙,做出來的效果會很有意思。


推薦閱讀:

Unity程序員如何轉變為技術美術?現已熟悉UnityShaderlab.?
Unity工作一年能力應該到達什麼水平?
linq 在 Xcode 上編譯錯誤?
用遊戲引擎「實時」做影視特效會衝擊原本屬於「後期」的合成行業嗎?
想要進遊戲公司進行開發,到底需要什麼能力呢,該不該培訓呢。。。?

TAG:遊戲開發 | 編程 | Unity遊戲引擎 |