計算機圖形學:紋理映射(Texture Mapping)及Mipmap技術

2021-03-06 Unity3D遊戲開發精華教程乾貨

紋理映射及Mipmap技術

在本篇文章中,我們會具體的討論如何利用紋理映射讓場景擁有豐富的顏色信息,以及紋理貼圖精度大小所帶來的問題,怎麼去解決,最後將會介紹Bump Mapping和Displacement Mapping

1 紋理映射(Texture Mapping)

首先讓我們一起來觀察這樣一張圖:

無論是球上的圖案,以及地板的木頭紋理都呈現出了不同的顏色信息,那麼回想在講解Blinn-Phong反射模型的時候曾提到,一個點的顏色是由其漫反射係數決定的,反射什麼顏色的光,人眼就能看見什麼顏色。那麼針對上面這幅圖,難道要去針對每一個點自己去設定一個顏色嗎?還是說有什麼更方便的方法呢?那便是紋理映射了!

我們可以將三維物體上的任意一個點都映射到一個2維平面之上,舉一個簡單例子,地球儀:

倘若擁有從3維World space到2維Texture space的一個映射關係,那麼只需要將每個點的顏色信息即漫反射係數存儲在2維的Texture之上,每次利用光照模型進行計算的時候根據映射關係就能查到這個點的漫反射係數是多少,所有點計算完之後,結果就像最左邊的screen space之中,整個Texture被貼在了模型之上。

有了Texture,有了映射關係,對渲染結果會有一個非常大提升,因為很多fancy的效果都可以通過texture的設計得到(當然這屬於美術的活兒了,咱們用就行了)。可以看這樣一個有點醜的例子。

可以看到在利用texture渲染之後,這個獨眼怪物醜的更有特點了。

好了,相信到這大家都對紋理映射了有了一個大概的了解,那麼有了一張Texture之後,這種映射關係究竟是如何表示的呢?這就要從紋理坐標(UV)說起了。在紋理空間之內任意一個二維坐標都在[0,1]之內。如下圖是一個可視化紋理坐標的結果:

橫軸和縱軸的最大值都為1,為什麼整幅texture圖可視化之後是紅色和綠色呢?可以將(u,v)坐標的兩點想像成red和green就能明白了。一幅Texture上的任意一點都可以用一個(u,v)坐標來表示(0<=u<=1,0<=v<=1),因此只需要在三維world space中每個頂點的信息之中存儲下該頂點在texture space的(u,v)坐標信息,自然而然的就直接的得到了這種映射關係。至於一個頂點所對應在紋理空間的坐標是怎麼得到的,這就並不是程式設計師們關心的了,美術大大們會幫我們最好的(當然讀者有興趣也可以自行搜集資料)。

有一種特殊的紋理稱為tile,這種紋理的特徵是重複拼接之後上下左右都是連續的,因此這種紋理可以複製很多張貼在牆面或地板上。

一個具體的重複利用這種貼圖的例子如下:

最後給出一個紋理坐標使用的偽代碼供參考:

簡而言之就是對每個光柵化的屏幕坐標算出它的uv坐標(利用三角形頂點重心坐標插值),再利用這個uv坐標去查詢texture上的顏色,把這個顏色信息當作漫反射係數Kd。

好了在理解了紋理映射的基礎之後,考慮如果紋理精度特別小(reslution低)或者紋理精度特別大(reslution大)會分別引起什麼問題呢?

2 紋理過小和紋理過大的問題及解決方案2.1 紋理過小引發的問題

紋理過小的問題相對容易理解,想想我們把一張100x100的紋理貼圖應用在一500x500的屏幕之上必然會導致走樣失真,因為屏幕空間的幾個像素點對應在紋理貼圖的坐標上都是集中在一個像素大小之內。那麼如果僅僅是使用對應(u,v)坐標在texture貼圖下最近的那個像素點,往往會造成嚴重的走樣。

如圖中紅色點是屏幕空間下一像素所對應在texture空間中的點,會去選擇離他最近的那個橙色框起來的點。

這種方法是不可取的,接下來會介紹利用雙線性插值的方法緩解這種走樣現象。

2.2 雙線性插值(Bilinear Interpolation)

我們依然取上圖的點作為例子,解釋雙線性插值。第一步,取出離紅色點最近的4個黑色頂點,分別算出,該紅色點在水平及豎直方向偏移的比率s,t,圖示如下:

接著先利用s,可以線性插值出如下圖所示的u0,u1點的顏色值

那麼下一步相信讀者也能猜到了,利用比例t,顏色值u0,u1插值出紅色點的顏色值

如此這樣利用兩次線性插值,考慮到了所有4個點的顏色值,能夠很好的緩解走樣失真現象,並且計算速度較高。

(tips:還有一種插值方法叫做雙三次插值(Bicubic),是利用三次方程來進行兩次插值,效果可能更好,但是計算速度很低不在這裡具體討論了)

最後以一張閆老師課上的例子看看這3種方法效果的對比

可能會看不太清。理解個意思就好

2.3 紋理過大引發的問題

可能對於我們的第一直覺來說,紋理小確實會引發問題,但是紋理大那不是更好嗎,為什麼會引發問題呢?但事實是紋理過大所引發的走樣甚至會更加嚴重。想像一張很大的地板,在上面鋪滿了重複的方格貼圖,我們所期望看到的結果應該是這樣的:

嗯,非常符合透視關係,不錯,當然這只是一個參考。再來看看利用在第一章所提到的計算紋理顏色的偽代碼來計算的結果呢:

近處鋸齒!遠處摩爾紋!非常嚴重的走樣現象,為什麼會導致這樣的一個現象呢?這裡作者嘗試給出自己的兩種解釋:

1 如開頭所說,地板上鋪滿了重複的方格貼圖,根據近大遠小,遠處的一張完整的貼圖可能在屏幕空間中僅僅是幾個像素的大小,那麼必然屏幕空間的一個像素對應了紋理貼圖上的一片範圍的點,這其實就是紋理過大所導致的,直觀來說想用一個點採樣的結果代替紋理空間一片範圍的顏色信息,必然會導致嚴重失真!(從信號的角度來說就是,採樣頻率過低無法還原信號原貌)

2 換一種想法,考慮離相機很遠的一個三角形面,假設該三角形面真正在紋理貼圖上對應的一片區域有10個像素點。但是由於透視的關係,距離很遠的三角形面投影到近平面時可能只有1個或2個像素點的大小(遠遠小於10個像素的原來大小),那麼這1個或2個像素採樣texture的結果就要代表原來這個三角形面10個像素點的顏色信息,自然會導致失真!

(tips:可能有讀者一開始會疑惑(包括我也是)為什麼1個屏幕空間像素點覆蓋多個紋理空間像素就是紋理過大呢,想像一下紋理貼圖大小500x500,屏幕空間100x100,將屏幕空間的像素點均勻分布在紋理空間之中,那麼1個屏幕空間像素點所佔的平均大小就是5x5=25個紋理空間像素,因此這就是紋理過大所導致的結果)

這種現象被形象的成為屏幕像素在texture空間的footprint。如上圖所示一個屏幕空間的藍色像素點離相機越遠,對應在texture空間的範圍也就越大。其實也就是越來越欠採樣,那麼一種直觀的解決方法就是Supersampling,如果一個像素點不足以代表一個區域的顏色信息,那麼便把一個像素細分為更多個小的採樣點不就可以解決這個問題了嗎?對,確實是這樣,可以看看如下圖512x超採樣的結果

效果雖稱不上完美但也極大緩解了走樣現象,但問題是什麼?計算量太大了,一個像素點被分為了512x512個採樣點,計算量幾乎多出了25萬倍!這顯然不是所希望看到的,並且隨著屏幕空間的點離相機距離更遠,更多的texels(紋理空間的像素)會在屏幕像素的一個footprint裡面,會要更高的超採樣頻率。

那麼另外一種想法,如果不去超採樣,僅僅是求出每個屏幕像素所對應的footprint裡所有texels的顏色均值呢?這也就是接下來所要介紹的著名的Mipmap技術了!

2.3 Mipmap

回顧一下屏幕像素在Texture空間裡的footprint的這張圖:

正如上文所提,一個採樣點的顏色信息不足以代表 「footprint」裡一個區域的顏色信息,如果可以求出這樣一個區域裡面所有顏色的均值,是不是就是一種可行的方法呢?沒錯我們的目標就是從點查詢Point Query邁向區域查詢Range Query。但依然存在一個問題,從上圖不難看出,不同的屏幕像素所對應的footprint size是不一樣大小的,看下圖這樣一個例子:

遠處圓圈裡的footprint必然比近處的要大,因此必須要準備不同level的區域查詢才可以,而這正是Mipmap。

level 0代表的是原始texture,也是精度最高的紋理,隨著level的提升,每提升一級將4個相鄰像素點求均值合為一個像素點,因此越高的level也就代表了更大的footprint的區域查詢。接下來要做的就是根據屏幕像素的footprint大小選定不同level的texture,再進行點查詢即可,而這其實就相當於在原始texture上進行了區域查詢!

那麼如何去確定使用哪個level的texture呢?利用屏幕像素的相鄰像素點估算footprint大小再確定level D!如下圖:

在屏幕空間中取當前像素點的右方和上方的兩個相鄰像素點(4個全取也可以),分別查詢得到這3個點對應在Texture space的坐標,計算出當前像素點與右方像素點和上方像素點在Texture space的距離,二者取最大值,計算公式如圖中所示,那麼level D就是這個距離的log2值 (D = log2L) ! 這不難理解,讀者可以具體取幾個例子比如L = 1,L = 2,L = 4,看看是否符合這樣的計算即可。

但是這裡D值算出來是一個連續值,並不是一個整數,有兩種對應的方法:

1 四捨五入取得最近的那個level D

2 利用D值在 向下和向上取整的兩個不同level進行3線性插值

第一個方法很容易理解,具體講述一下第二個方法,如圖:

所謂3線性插值,就是在向下取整的D level上進行一次雙線性插值(前文提過),再在D+1 level之上進行一次雙線性插值,這二者數據再根據實際的連續D值在向下和向上取整的兩個不同level之間的比例,再來一次線性插值,而這整體就是一個三線性插值了。

好了!根據上述的方法算出屏幕上每一個像素點所對應的Mipmap level,再進行三線性插值得到顏色值,是否就能很好的解決走樣問題了呢?很遺憾,在本文的那個地板的例子之中,費了這麼大力氣依然不能完美解決,如下圖結果:

雖然和一開始的point sample有了很大的進步,但是有一個嚴重的問題是,遠處的地板產生一種過曝的現象,完全糊在了一起。該如何解決這個最後的問題呢——各向異性過濾。

2.4 各向異性過濾Mipmap

好,接著上文的遠處產生過曝的問題繼續來談,產生這種現象的原因是因為,所採用的不同level的Mipmap默認的都是正方形區域的Range Query,然而真實情況並不是如此,見下圖:

可以看出不同screen space的像素點所對應的footprint是不同的,有長方形,甚至是不規則圖形,那麼針對這種情況,有的所需要的是僅僅是水平方向的高level,有的需要的僅僅是豎直方向上的高level,因此這也就啟發了各向異性的過濾:

(個人感覺,應該是要算出水平方向的level D0,再算一個豎直方向的level D1,然後算根據這兩個level去各項異性過濾的texture裡面找一張最合適的)

利用這樣不同的貼圖,更加精細的選擇後結果就會明顯好很多:

可以看出,遠處過曝的現象已經大大減少了。

(Note:其實各向異性過濾並不能解決 diagonal的footprint,因為各向異性只能解決水平或豎直的不同大小的矩形footprint,所以針對diagonal的footprint,一般是去sample更多的點,或者提前算好diagonal 過濾的texture)

總結

紋理映射的一些基礎概念和做法個人感覺還是比較容易理解的,難的是後序的紋理過大過小引發的問題,可能相對而言有些抽象,需要自己仔細思考思考,包括解決問題的一些方法Mipmaps,各向異性過濾什麼的,希望能對大家的理解產生一點幫助吧!

最後對大家理解有幫助的話求點讚求收藏求一個大大的關注 :) ,後序會持續更新,感謝閱讀!

Reference

[1] GAMES101-現代計算機圖形學入門-閆令琪

聲明:發布此文是出於傳遞更多知識以供交流學習之目的。若有來源標註錯誤或侵犯了您的合法權益,請作者持權屬證明與我們聯繫,我們將及時更正、刪除,謝謝。

作者:孫小磊

來源:https://zhuanlan.zhihu.com/p/144332091

More:【微信公眾號】 u3dnotes

相關焦點

  • 【GAMES101-現代計算機圖形學課程筆記】Lecture 09 Shading 3 (紋理映射)
    這樣一來,比如A紋理原來的大小是100x100,B紋理原來的大小是20x20,很顯然映射後A所對應的紋理平面的紋理會更密集,而B則會相對稀疏。Texture Coordinates本節內容概要:重心坐標(barycentric coordinates)1.
  • 音視頻開發之旅(12) OpenGL ES之紋理
    圖片坐標系的(0,0)在圖片左上角,紋理坐標的(0,0)在紋理左下角紋理映射為了能夠把紋理映射(Map)到三角形上,我們需要指定三角形的每個頂點各自對應紋理的哪個部分。這樣每個頂點就會關聯著一個紋理坐標(Texture Coordinate),用來標明該從紋理圖像的哪個部分採樣。
  • 走過半個多世紀,計算機圖形學的發展告訴你5毛錢電影特效有多難
    2019 ACM 圖靈獎大獎出爐,最終花落計算機圖形學專家 Patrick M. Hanrahan 和 Edwin E. Catmull,以表彰他們在概念創新和軟硬體方面的貢獻,以及對計算機圖形學所產生的根本性的影響。
  • 走過半個多世紀,計算機圖形學的發展歷程告訴你5毛錢的電影特效...
    2019 ACM 圖靈獎大獎出爐,最終花落計算機圖形學專家 Patrick M. Hanrahan 和 Edwin E. Catmull,以表彰他們在概念創新和軟硬體方面的貢獻,以及對計算機圖形學所產生的根本性的影響。
  • ...圖形學先驅Hanrahan和Catmull獲獎,二人見證了好萊塢3D動畫電影史
    原題目《圖靈獎公布,計算機圖形學先驅Hanrahan和Catmull獲獎,祝賀兩位好萊塢3D動畫大片技術元老》ACM(國際計算機協會)今天宣布,授予 Patrick M. Hanrahan 和 Edwin E. Catmull 2019 年 ACM A.M.
  • 分析 AGI 紋理數據並提升 GPU 性能
    後續渲染步驟 (Post Processing steps) 對紋理帶寬需求較高是可以理解的,也許您可以在渲染的後序階段把部分帶寬使用於一些特殊的效果處理上面,比如實現光暈和色調映射。但是如果您的遊戲存在很高的紋理讀取帶寬峰值,那麼就需要注意潛在的性能問題了。
  • 計算機圖形學領域的人才需要是什麼?
    這個新技術的背後 ,其實就是計算機圖形學的應用。那麼,計算機圖形學是什麼?計算機圖形學是計算機學科的一大分支,是一種使用數學算法將二維或三維圖形轉化為計算機顯示器的柵格形式的科學。簡單地說,計算機圖形學的主要研究內容就是研究如何在計算機中表示圖形、以及利用計算機進行圖形的計算、處理和顯示的相關原理與算法。
  • OpenGL 學習系列 --- 紋理
    接下來探索紋理了。紋理,簡單的理解就是一副圖像。而把一副圖像映射到圖形上的過程,叫做紋理映射。比如有如下圖形和三角形,想要把圖形中的一部分映射到三角形上。基本原理要注意到,OpenGL 繪製的物體是 3D 的,而紋理是 2D 的,那麼紋理映射就是將 2D 的紋理映射到 3D 的物體上,可以想像成用一張紙裹著一個物體一樣,不過要按照一定規律來。
  • 計算機中的Map接口
    在計算機中想到集合和容器,我們應該想到List,Set,Queue隊列,Map這幾個集合容器。而我們在其中這幾個當中選取適合裝我們所需的數據。舉個生活的小李子,提水,你想到的是什麼?你第一反應想到的應該是桶這一類的東西,我覺得你不會想到用缸這一龐然大物。以現實生活中的例子反應到計算機中,就通俗易懂了!
  • 計算機圖形學的應用領域
    今年大家都說就業難,不好找工作,但是學計算機類的專業一直都是就業崗位多,薪資待遇待遇好的專業,從雲計算到大數據,都是社會各界非常關注的。那今天我們來講講計算機學中的一個重要分支——計算機圖形學的應用領域圖形圖像一直都比單純數據有更多的表現力,首先圖形可以將科學成果通過可視化的方式展示給人們;其次在遊戲和電影特效中,
  • UE4精品課程 | OpenGL學習筆記(五)紋理
    >為了能夠把紋理映射(Map)到三角形上,我們需要指定三角形的每個頂點各自對應紋理的哪個部分;這樣每個頂點就會關聯著一個紋理坐標,用來標明該從紋理圖像的哪個部分採樣,之後在圖形的其它片段上進行片段插值(Fragment Interpolation);紋理坐標在x和y軸上,範圍為0到1之間(2D紋理圖像);使用紋理坐標獲取紋理顏色叫做採樣(Sampling
  • 賈伯斯好友獲圖靈獎,曾打造《玩具總動員》,為計算機圖形學先驅
    國際計算機協會ACM說,圖靈獎頒給卡特姆和漢拉汗,以表彰他們對3D計算機圖形學的貢獻,以及對電影製作和計算機生成圖像等應用的革命性影響。這也是圖靈獎新歷史紀錄:圖形領域學者第一次以圖形學貢獻獲頒圖靈獎。
  • Unite 2018 | 使用自定義渲染紋理實現炫酷特效
    而更進一步,畫面渲染的質量再很大程度上取決於像素著色器Pixel Shader(它一般也叫做片元著色器Fragment Shader)的紋理貼圖功能(Texture Mapping)。無論是像素著色器還是紋理貼圖技術都需要將面映射到平面區域,同時儘量減小映射帶來的幾何畸變。微分幾何中曲面映射理論為這些技術提供了堅實的基礎,指明了算法的發展方向。
  • 談談遊戲中常見的後處理技術
    通常gamma encode和decode都是由GPU來進行的,包括採樣貼圖、寫入color buffer、alpha 混合以及mipmap間的雙線性插值。Scene-Referred和Display-ReferredTone Mappingtone mapping就是將HDR映射回LDR的過程,如果沒有進行tone mapping,直接顯示到普通顯示器會出現過曝的情況。
  • 計算機學院博士生獲中國圖像圖形學學會(CSIG)優秀博士學位論文獎
    西工大新聞網12月9日電(張薇)近日,中國圖像圖形學學會(CSIG)公布了2019年CSIG優秀博士學位論文獎,西北工業大學計算機學院博士畢業生張磊(導師:張豔寧教授)的博士學位論文《基於結構化稀疏表示的高光譜圖像壓縮感知技術研究》獲此殊榮。
  • OpenGL核心技術之混合技術
    我們要忽略(丟棄)紋理透明部分的像素,不必將這些片段儲存到顏色 緩衝中。接下來要做的事情就是加載帶有Alpha通道的紋理圖片,在這裡我們使用了SOIL庫, SOIL 是一個用於向OpenGL中 加載紋理的小型C語言庫。