表面著色器

2021-10-10 09:34:38 字數 4522 閱讀 3490

除了幾乎從頭開始編寫著色器之外,unity還允許我們定義一些引數,並讓unity生成執行複雜光照計算的**。 這些著色器稱為「表面著色器」。

之前的basic shader轉換到表面著色器

使用表面著色器時,我們不必做其他的事情,因為unity會為我們生成它們。為了轉換為你表面著色器,可以完全刪除頂點著色器。可以刪除頂點和片段函式的編譯指示定義。可以刪除輸入以及將片段片段化的頂點。 可以刪除進行紋理縮放的maintex_st變數,也可以刪除unitycg包含檔案的包含。 然後我們刪除pass的起點和終點,unity將為我們生成pass。 最終,我們清空的著色器應如下所示:

shader "unityshader/su***ce shader basics"

} subshader

cgprogram

sampler2d _maintex;

fixed4 _color;

fixed4 frag (v2f i)

: sv_target

endcg

} fallback "standard"

}

我們已經破壞了之前的著色器,現在可以新增一些內容使其用作表面著色器。

首先,我們新增乙個新結構並將其命名為input,它將包含設定表面顏色所需的所有資訊。 對於此簡單的著色器,只是uv座標。 像上乙個著色器一樣,座標的資料型別將是二維浮點數。這裡的命名很重要,將其命名為uv_maintex,這樣,它將已經具有maintex紋理的平鋪和偏移。如果紋理的名稱不同,則必須使用uvtexturename獲取適合該紋理的座標。

struct input 

;

接下來,將片段功能更改為表面功能。為使更改顯而易見,我們將其重新命名為surf。然後,我們將返回型別替換為void,因此該函式不會返回任何內容。然後,我們將其擴充套件為2個引數。首先,我們剛定義的輸入結構的乙個例項,因此我們可以訪問基於每個頂點定義的資訊。其次,稱為su***ceoutputstandard的結構,顧名思義,我們將使用它來將資訊返回到著色器的生成部分。為了使「返回」正常工作,我們必須在其前面編寫inout關鍵字。第二個結構是單位將用於照明計算的所有資料。光照計算是基於物理的(我將在本文後面解釋引數)。接著,我們將從方法中刪除sv_target屬性,因為像其他方法一樣,它是由unity其他地方完成的。為了使su***ce方法起作用,我們最後要做的更改是刪除return語句(這就是我們將return型別更改為void的原因)。相反,我們將輸出結構的反照率部分設定為我們的顏色值。

void

surf

(input i,inout su***ceoutputstandard o)

漫反射:漫反射是材料的底色。它將被照亮它的燈光的光照顏色所著色,並且在陰影中暗淡,這正是我們所期望的。反射光的顏色不會影響鏡面照明,因此您可以使黑色材料仍然具有明顯的光澤。它儲存為3維顏色向量。

法線:這是材質的法線。法線位於「切線空間」中,這意味著在將它們返回之後,它們將被更改為相對於世界的法線。在切線空間中具有法線意味著如果我們將(0,1,0)寫入該變數,則法線實際上不會指向上,而是遠離表面(這是將法線編碼為法線貼圖的方式,因此我們可以直接從法線貼圖複製資訊到此變數)

。法線儲存為3維方向向量。

自發光:可以使您的材料發光。如果僅編寫此內容,則著色器將看起來像我們之前製作的未著色著色器,但消耗更高。自發光顏色不受光的影響,因此可以使斑點始終保持明亮。如果使用hdr顏色進行渲染(可以在相機設定中進行設定),則可以將值大於1的值寫入發射通道(當您使用bloom後期處理效果時,可以使事物看起來真的很明亮,並使事物綻放更多) 。發射顏色也儲存為3d顏色向量。

金屬光澤:當材料不是金屬時,它們看起來是不同的。要使材料看起來像金屬,可以調高該值。它將使物件以不同的方式進行反射,反照率值將對反射進行著色,而不是您使用非金屬獲得的漫反射照明。金屬值儲存為標量(一維)值,其中0表示非金屬材料,1表示完全金屬的材料。

平滑:使用此值,我們可以指定材料的平滑度。平滑度為0的材料看起來粗糙,光將被全方位反射,我們看不到鏡面高光或環境反射。具有1的平滑度的材料看起來超級拋光。 「正確設定環境後,您會看到它反映在您的材料上。它也是如此拋光,以至於您也看不到鏡面高光,因為鏡面高光變得越來越小。將平滑度設定為小於1的值時,您開始看到周圍燈光的鏡面反射高光。隨著降低平滑度,高光會變大,而強度會降低。平滑度也儲存為標量值。

遮罩:遮罩會從您的材料中去除光線。有了它,您可以偽造燈光而不會進入模型的裂縫,但是您幾乎不會使用它,除非您要使用超現實主義風格。遮擋也儲存為標量值,但與直覺相反,1表示畫素具有全亮度,0表示畫素在黑暗中。

透明 : alpha是透明材質。我們當前的材質是「不透明」的,這意味著不能有任何透明畫素,並且alpha值也不會做任何事情。製作透明著色器時,alpha將定義我們可以在該畫素處看到多少材料,其中1完全可見,而0完全透明。 alpha也儲存為標量值。

實現上面的照明屬性

現在可以增加上面提到的屬性到之前的shader中,我將會用到自發光以及金屬質感還有平滑這幾個值。首先我增加兩個標量值smoothness和metalness,確定他們的型別為half,新增到我們的全域性範圍。

half _smoothness;

half _metallic;

然後,我們還將這些值新增到屬性中,以便能夠在編輯器中對其進行更改。 屬性不知道half型別,因此我們告訴他們變數是float型別。 這足以使變數顯示在檢查器中,但我們尚未使用它們。類似於將顏色變數分配給材質的漫反射的方式,現在我們可以將平滑屬性分配給輸出結構的平滑度,將金屬度分配給金屬輸出變數。

void

surf

(input i,inout su***ceoutputstandard o)

這種方法很好用,但是很容易為這些值分配大於1或小於0的值,並得到非常錯誤的結果,而且很難知道該值有多高。 為了解決這個問題,我們可以將值分配為範圍屬性,而不是浮點屬性。 範圍屬性使我們可以定義最小值和最大值,並且在unity將顯示乙個滑塊。

properties 

_smoothness (

"smoothness"

,range(0

,1))

=0_metallic (

"metalness"

,range(0

,1))

=0}

接下來,我們新增自發光。 首先作為hlsl**中的變數,然後作為屬性。 我們使用color屬性型別,就像我們對色調所做的一樣。 我們將half3作為型別儲存,因為它是不帶alpha的rgb顏色,並且其值可以大於1(輸出結構也使用half3)。 然後,我們也像其他操作一樣在shader輸出中分配值。

half3 _emission;

_emission

("emission"

,color)=(

0,0,

0,1)

o.emission = _emission;

使用hdr標籤 可以將亮度設定為更高的值

[hdr]

_emission

("emission"

,color)=(

0,0,

0,1)

改進

最後,我要向您展示兩個小東西,它們使您的著色器看起來更好一些。 首先,您可以在子著色器下新增乙個後備著色器。 這允許統一使用其他著色器的功能,而我們不必自己實現它們。 為此,我們將標準著色器設定為後備,統一將借鑑它的「陰影通道」,使我們的材質在其他物件上投射陰影。 接下來,我們可以擴充套件我們的編譯指示。 我們將fullforwardshadows引數新增到著色器指令中,這樣我們可以獲得更好的陰影。 另外,我們新增了將構建目標設定為3.0的指令,這意味著unity將使用更高的精度值,這會導致更漂亮的照明。

shader "unityshader/su***ce shader basics"

_smoothness

("smoothness"

,range(0

,1))

=0_metallic

("metalness"

,range(0

,1))

=0[hdr]

_emission

("emission"

,color)=(

0,0,

0,1)

} subshader

cgprogram

#pragma su***ce surf standard fullforwardshadows

#pragma target 3.0

sampler2d _maintex;

fixed4 _color;

half _smoothness;

half _metallic;

half3 _emission;

struct input

;void

surf

(input i,inout su***ceoutputstandard o)

endcg

} fallback "standard"

}

表面著色器

設計目的 頂點 幾何 片元著色器處理方式比較適合gpu去理解,但是對人理解而言就顯得比較晦澀。所以unity提供了一種適合人類理解的處理方式,也就是表面著色器 光照模型 光照著色器。它是在頂點 幾何 片元著色器上面進行的一層抽象封裝,最終還是會被unity翻譯成頂點 幾何 片元著色器的處理方式。表面...

表面著色器一

在su ce shader當中不需要編寫pass通道,su ce shader就是對vertex shader和fragment shader的一種包裝。它主要可以用來生成 所以生成的過程不需要進行干預,因此pass通道也能夠幫我們自動生成,不需要去新增pass通道。一 建立的shader的 sha...

表面著色器二

一 surf函式 void surf input in,inout su ceoutputstandard o 二 該函式是無返回值的,第乙個引數input in就是我們定義的乙個結構體 struct input 在這個函式中,只是使用了乙個主紋理的紋理座標,這個紋理座標必須要以uv小寫開頭 三 第...