天天看點

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

在模拟現實效果方面,紋理可以讓着色器迅速生動起來。為了高效使用紋理,我們需要了解二維圖像是如何映射成三維模型的。這個映射過程稱為紋理映射。為了進行紋理映射,我們需要在着色器和想要應用紋理的三維模型上下點工夫。模型事實上是由三角形組成的,三角形的每一個頂點可以存儲着色器可以通路的資料。uv資料是頂點中存儲的諸多重要資訊之一。uv資料由兩個坐标組成,也就是u和v,取值範圍為0到1,它們表示了二維圖像中像素映射到頂點時的xy坐标。uv資料隻是給頂點用的,三角形内部其他位置上的值則是gpu根據內插補點算法按照一定的間隔比例去紋理上取的值。下圖展示了二維紋理是如何映射到一個三維模型的基礎三角形上去的。

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

uv資料儲存在三維模型中,并需要用專門的模組化軟體才可編輯。某些模型沒有uv元件,也就不能支援紋理映射了。比如之前舉例的那個斯坦福兔子最開始就沒有uv元件。

在這一節中,需要一個有uv資料的三維模型及其紋理。在開始之前需要将這二者導入unity中。你可以直接将其拖曳到unity編輯器中。标準着色器預設支援紋理映射,是以我們會用這個标準着色器來解釋紋理映射是怎麼工作的。

使用标準着色器給模型添加紋理非常簡單,步驟是:

建立一個新的名為texturedshader的标準着色器。

建立一個新的名為texturedmaterial的材質。

通過拖曳将着色器指定給材質。

選中材質後,将紋理拖曳到名為albedo(rgb)的空長方形中。如果你按照這個步驟進行的話,材質的inspector标簽頁應該看起來像這樣:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

标準着色器知道如何通過uv資料将二維圖像映射到三維模型上。

當标準着色器在材質的審查器(inspector)中被使用時,紋理映射背後的過程對于開發人員是完全透明的。如果我們想了解它是如何工作的,需要深入看一看texturedshader。從properties部分來看,可以發現albedo(rgb)紋理實際引用的代碼是_maintex:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

在cgprogram部分,該紋理被定義為sampler2d—二維紋理的标準類型:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

下一行代碼是一個名為input的結構體。這是表面函數的輸入參數,這個輸入參數包含一個名為uv_maintex的包裝數組:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

每次surf()函數被調用時,input結構會包含三維模型需要渲染的某一個特殊點的_maintex的uv值。标準着色器會識别出uv_maintex引用的是_maintex的值,并且會自動對其進行初始化。如果你對于uv值是如何從三維模型映射到二維紋理上的比較感興趣,可以看看第3章的内容。

最後,表面函數的第一行中, uv資料被用來對紋理進行采樣:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

這個過程是通過cg的tex2d()函數來實作的。該函數接受一個紋理和uv,并傳回像素在該位置的顔色值。

 uv坐标都是從0到1,其中(0,0)和(1,1)表示的是兩個對頂角。不同的實作方式會把uv和不同的角聯系起來。如果你的紋理看起來有點翻轉了,試着颠倒一下v的值。

當你向unity導入一個紋理的時候,其實是在給sampler2d準備一些它需要用到的屬性。最重要的是filter(過濾)模式,過濾模式會決定紋理采樣時顔色是如何插值的。一般而言,uv資料不會準确指向像素的中心,而其他一些時候你可能需要在最接近的像素間進行插值來讓顔色看起來勻稱。下圖是一個樣例紋理的inspector标簽頁截圖:

《Unity着色器和螢幕特效開發秘笈(原書第2版)》一2.4 給着色器添加紋理

對于大部分應用程式,bilinear(雙線性)過濾是一種廉價而又有效的平滑紋理的方式。但是如果你建立的是二維遊戲,那麼雙線性可能産生一些模糊的地方,這時你可以使用point(點)過濾來移除紋理采樣過程的插值。

當我們從一個大傾角觀察紋理時,紋理采樣通常會産生一些不友好的瑕疵。你可以通過增加aniso level的值來減少這些瑕疵,這個改動對于地闆和天花闆這種類型的紋理非常有效,因為這些紋理中的一些毛刺會破壞視覺的連續性。

如果你想深入了解紋理映射的更多内容,可以查閱下面的網址:

也可以在下面這個網址找到所有導入二維紋理時的可用選項:

繼續閱讀