短篇圖形學——紋理座標及其應用


3樓貓 發佈時間:2024-03-01 12:32:53 作者:Hakumen Language

前言

雖然是接著“遊戲中還原真實世界”來寫的,但是在做新選題時我逐漸意識到必須要補充一些圖形學的簡單概念才能繼續講大點的課題了,否則說到“雲”、“霧”、“水體”、“陰影”等等這些根本就沒法談。
雖然僅僅介紹圖形學沒有那麼多實際遊戲的例子,會顯得略微枯燥一些,但我覺得知道各種技術方案為什麼被髮明出來也是一件有趣的事情。
這裡面我也基本不會介紹各種計算的過程或原理,主要是拋出各種“是什麼”以及“為什麼”。很多東西雖然實現複雜,但是目標其實挺簡單的。
最後簡單說一下,這個系列主要也是鍛鍊我把複雜東西說得簡單有趣的能力,本身介紹的東西都不新鮮了;很多人即使不理解這些也以學習工具的方式用引擎做了一堆東西了——不過我覺得工具性的理解始終不如成系統的理解。
那麼讓我們從紋理(Texture )開始——有些應用場合也被稱為貼圖,兩者雖然不完全一樣但也不必較真:

1 紋理和紋理座標

(圖中展示了不使用紋理和使用紋理能呈現的模型渲染效果)
遊戲發展的過程中,2D是先於3D的,所以會使用紋理或貼圖的出發點很好理解——在三角面有限的情況下,想讓顏色更豐富一些,在三角面的範圍內呈現出顏色變化。
之所謂常常被人稱為貼圖,也是因為其最常見的存儲方式就是一張圖片。有了這張圖片讀進顯存後,就能以一定的座標系來查詢其中的像素,這種座標系就被稱為紋理座標(Texture Coordinates)
例如一張512*512的圖片,輸入x值100、y值100(或者其歸一化之後的值),這時就能查詢到一個顏色。紋理座標命名上為了避開模型空間的xyz座標,通常就被稱為UV座標——即紋理座標中的x、y值也對應寫作u、v。(紋理座標後續還有2個維度wq,和本文提到的應用無關,這裡不展開了)
(圖中展示了一個簡單的紋理座標應用)
可以認為紋理座標是關於顏色查詢的。當然實際使用中面臨的往往不是“輸入2個數輸出一個顏色”這麼簡單,第一步就是模型上存儲的uv值是如何得到的。這就引入了下面一個話題:

2 紋理映射(Texture Mapping)

(圖中展示了一個紋理映射的動態圖)
在渲染物體的過程中,物體頂點座標經歷了從物體空間參數空間(或裁剪空間)
的矩陣變換(此時還沒到屏幕空間的具體像素)——這裡矩陣變換指運算過程依賴的是矩陣的加或乘,最後可用的結果既可能是座標(向量)也可能是矩陣。
對一個三角面來說,通過3個頂點的UV值,已經可以確定其在紋理座標中包圍起來的範圍。
網格和UV的對應關係不一定是完全對應覆蓋的。對於超出紋理座標範圍的UV值,人們在紋理映射的過程中引入了環繞模式(WrapMode)的概念,用來定義超出時紋理像素範圍的顏色如何顯示處理。
常見的重複模式有:Repeat、Clamps、Mirror幾種情況。
Repeat比較好理解,就是循環重複整個紋理。例如一大片地磚就常常使用這種方案,地面可能只有1個四邊面,覆蓋的紋理範圍卻是循環了很多次的。
Mirror就是鏡像紋理,有些引擎還有MirrorOnce的選項。
Clamps可以理解成邊緣顏色外擴,主要是處理紋理座標中的“空白”(也可以用作透明)區域,這裡就不展開了。
(圖中展示了一些WrapMode及其預覽效果)
如果2個頂點連的一條直線是幾何意義上連續的,那麼很多問題都不用討論了。但是實際上顯然不是,不僅屏幕空間最小單位是像素,紋理座標的最小單位也是像素,這就跨越了2個離散的空間
這之間經歷了幾輪空間變換之後,帶來了或多或少的精度損失;如何減少過程中的精度損失並儘量在最終視覺上顯得更連續或更還原,就成了紋理映射誕生之後不斷在發展改進的一系列技術方向。

3 插值與Mipmap

插值(Interpolation)思想被廣泛運用於圖形學的顏色採樣和動畫採樣等方面,其中的線性插值(Linear Interpolate)可以簡單的理解為取平均值。例如(0,0,0)和(1,1,1),其40%位置的線性插值就是(0.4,0.4,0.4)。
如果是一段動畫,在2個關鍵幀(位置、縮放、旋轉)之間需要插值,動畫概念裡也被稱為補間(但往往不是線性的,而是由其它曲線函數定義的過程)。那麼紋理座標對應的顏色採樣什麼時候需要插值呢?
(圖中演示了圖片放大過程中雙線性插值的過程)
常見的一種情況就是紋理放大,如果顯示尺寸大於紋理尺寸,那麼就需要考慮2個顏色之間顯示什麼顏色的問題。雙線性插值( Bilinear Interpolation 就是在2個軸上一起對顏色值進行線性插值,取得的值相當於紋理座標上4個像素之內的一個中間值
如果不用這種插值方法,採樣也可以使用最近顏色(Nearest)方案,呈現出的效果感覺就是像素顆粒更大的原圖。(這裡有一個Filtering的概念沒展開,我覺得這只是一種命名,其實說的是一回事)
如果是紋理縮小,例如——屏幕上10個像素,對應紋理上1000個顏色漸變的像素。這種極端情況下如果每隔100個像素在紋理座標上採樣,映射到屏幕10個像素會顯得非常不連續,因為每100個像素的顏色值已經完全變了。改進的基本思路則是對這100個像素做插值,由此誕生了Mipmap
(左邊展示了紋理縮小的一種失真情況,右邊使用mipmap緩解了這種視覺上的失真)
Mip之所以很少使用全稱,因為其來源是一個意義不太一樣的拉丁詞 multum in parvo ("much in a small space"),所以說到這個概念基本就是用縮寫,也沒有很好的中文翻譯。硬要說的話,可以理解為多層紋理技術
其基本思想是——針對原始紋理,每次計算其雙軸取一半分辨率,並把顏色線性插值的結果存儲為一個次級紋理;這樣遞歸若干次(基本是7次)得到的結果集合就被稱為mipmap。
(圖中展示了一組層級紋理構成的mipmap)
低分辨率紋理中的顏色已經是逐步插值取色後的結果了,這樣呈現的視覺效果也可以理解為相鄰顏色的一種混合。有了mipmap後,紋理的等比縮小就都可以按最接近的分辨率選擇合適的紋理層級(mip level),顯示出“混合得更好的顏色”了。
經過這樣處理後,得到的紋理在存儲上已經比原來的大了約30%。所以這也是一種利用預計算結果犧牲空間換顯示效果的技術,最主要的應用就是減少紋理縮小時採樣的失真感。
實際應用中,紋理的縮小往往不是雙軸等比的,所以後續人們還引入了各向異性(Anisotropic)的mipmap——各向異性可以簡單理解成每個軸不一樣,這裡就是縮放比例每個軸不一樣。
(各向異性mipmap的例子,顯然這樣又消耗更大的存儲空間了)
結合上mipmap後還誕生了紋理的三線性插值(Trilinear Interpolation)的技術,其基本思路就是在雙線性插值的基礎上,在2層相鄰的mipmap之間再做一次插值。篇幅原因這個點就不展開了,可以去看Games101或者wiki。
順帶一提,mipmap也被用於流式加載,其基本思路是可以先加載低分辨率的紋理,然後多線程加載並漸變成高分辨率的,屬於一套存儲結構2種用途的情況了。

4 抗鋸齒( Anti-Aliasing )

抗鋸齒是玩遊戲時常見的翻譯,其實其英文原詞更接近的翻譯是反走樣(因為與其相應的信號系統中的概念被翻譯成失真或走樣)。
部分抗鋸齒的方案已經和紋理映射沒關係了,但大部分對於像素顏色處理的思路是類似的,無外乎是各種插值與混合。
這裡列舉分析一些常見的抗鋸齒技術:
1)超採樣 —— Super-Sampling Anti-aliasing,簡稱SSAA
簡單來說就是以超過屏幕分辨率的尺寸來渲染,這樣映射到屏幕分辨率的像素時會有更好的效果,但性能消耗是很大的。
2)多重採樣—— MultiSampling Anti-Aliasing,簡稱MSAA
只對深度緩衝(Z-Buffer)和模板緩衝(Stencil Buffer)中的數據進行超級採樣抗鋸齒的處理。可以簡單理解為只對多邊形的邊緣進行抗鋸齒處理,相對前者處理的數據量會小一些,性能有所提高。(深度緩衝上一篇文章解釋過,而模板緩衝這個概念不展開了)
3)Fast Approximate Anti-Aliasing,簡稱FXAA
只基於圖像渲染結果進行若干個步驟的估算,例如對比度、亮度、方向等,這裡不展開了。
4)Temporal Anti-Aliasing ,簡稱TAA
通過綜合歷史幀
的方式來進行,對動態物體需要結合Motion Vector來計算,這裡不展開了。(*這裡FXAA和TAA沒有合適的翻譯,建議結合描述來理解)
(圖中展示了TAA的效果)
FXAA和TAA是目前遊戲引擎中比較主流的兩種方案。

5 UV動畫

紋理映射時通過引入一個偏移量來動態改變紋理座標,就可以實現很多簡單又豐富的UV動畫效果。
例如在一個循環的屏幕上播放循環的卷軸效果,或者是通過純紋理實現的水流或岩漿效果等。一般來說這種紋理是需要能四方連續的。
(圖中展示了UV動畫的一種應用。有些地方也提出了Flow map的概念,特指專用於UV動畫表現流動的紋理)
結合這裡還沒談到的透明顏色混合模式(Blend Mode),用多個紋理的UV動畫結合,並開發對應的著色器代碼,就能實現非常豐富的特效了。

結語

圖形學的第一課就是如何在屏幕上畫一根直線,這種把“連續”想辦法變為最接近的“離散”的思想也貫穿了紋理相關的技術以及很多其它的圖形學技術。
而Mipmap則結合了“預計算”與“存儲空間換效果”的思想,這種思路也廣泛運用在了很多其它的圖形學技術中。引擎中所謂的要烘焙的數據或紋理貼圖幾乎都屬於此類。
製作植物樹葉或者人物頭髮等等常使用有透明像素的紋理,篇幅所限本文也沒有討論透明紋理與其要面對的其它問題——畢竟透明與半透明討論起來又是另一個深坑了。
(圖中是植物紋理的一種應用)
相關資料,還是老樣子優先用Wiki:
紋理映射
Mipmap
各向異性過濾(Anisotropic Filtering)
三線性插值(對於紋理把頂點想象成顏色值)

© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com