開始學習unity也有一個多月了,之前就想把學習的東西總結一下,記錄下來方便自己以後查閱,可是工作太忙總是忘記了這個事情,最近 終於有時間了,打算把每天學的東西記錄下來。寫這個文章的原因有兩點:1.很多想法都是在學的時候可能會想到,但是過一段時間又忘記了。2.以前都是翻看別人的博文,然後突然找不到別人的部落格了,然後有些內容重新找起來感覺很麻煩,那就乾脆把自己的想法記錄下來,方便自己以後查閱。
shader是unity裡面比較重要的一個東西,將shader和紋理(texture)一起輸出打包會得到一個材質(material),將材質賦予給某個對象,某個對象上就能看到我們想要的效果。
建立一個shader檔案,選擇standard surface shader,
雙擊開啟檔案,可以看到裡面的內容:
Shader "Custom/NewSurfaceShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
檔案中代碼的最外層架構是
Shader“”{}
其實“”引號內可以輸入任何內容,輸入的內容就是你自訂的shader名字,該名稱和檔案名稱沒有任何關係,名稱可以用/分割,如果使用了/分割,那麼/前面的內容就是檔案的上級目錄,這個可以用來分類管理。
花括弧裡面的內容:分為Properties ,SubShader和FallBack三大塊
Properties{}
這個模組裡面定義的shader的屬性,所有用到的都是聲明在這個模組裡面,並且聲明的變數可以在Inspector面板裡面看到。Shader的屬性類型以及屬性的定義方式一共有如下幾種:
屬性定義結構
屬性名稱 (屬性面板上顯示的名稱,屬性類型) 預設值
屬性類型
Color 顏色
_Color ("Color", Color) = (1,1,1,1)
Vector 向量(預設四維向量)
_Vector ("Vector", Vector) = (1,1,1,1)
Int 整數類型
_Int("Int",Int) = 2
Float 小數類型
_Float("Float",Float) = 4.5 Range 範圍類型 小括弧內為最大值和最小值,如果輸入超過最大值的數值時,會自動調節至括弧內的最大數值
_Range("Range",Range(1,11)) = 6
2D 圖片類型 ""裡面可以給顏色的值 當2D沒有制定圖片的時候 會顯示""裡面制定的顏色 {}裡面進行制定具體的紋理
_2D("Texture",2D) = ""{}
Cube 立方體紋理 類似於skybox天空盒紋理
_Cube("Cube",Cube) = ""{}
3D 紋理 使用較少
_3D("3DTexture",3D) = ""{}
語義塊SubShader
這個是shader裡面最重要的內容,因為裡面的文法控制就是電腦的gpu如何對物體進行渲染,決定了我們會看到的物體效果。一個shader裡面是有多個SubShader的,shader載入的時候會從上到下進行載入SubShader裡面的內容,先載入第一個SubShader裡面的內容,如果第一個SubShader裡面的效果都可以實現,那麼就使用第一個SubShader ,如果顯卡發現這個SubShader裡面某個效果它實現不了,他會自動去運行下一個SubShader。SubShader裡面定義了一系列的Pass(可以認為是進階語言中的方法函數,一個SubShader至少要包含一個Pass ps:有一點奇怪的是為啥樣本中的SubShader裡面沒有Pass,但是shader卻沒問題) ,在Pass裡面編寫具體的渲染細節。
Pass{
//在這裡編寫Shader代碼 也可以用HLSLPROGRAM
CGPROGRAM
ENDCG
}
Pass中可以對Pass進行命名
例如 Name "FirstPass"
進行命名了的Pass可以在別的Shader中使用Use Pass直接引用
例如 UsePass "MyShader/FIRSTPASS"
除了自訂的Pass之外,Unity 還自訂了一些特殊的Pass,方便代碼的複用,例如:
UsePass 前面提到的,用來引用別的shader中的pass
GrabPass 該Pass是負責抓取螢幕結果並儲存為一張紋理,用於後續的Pass處理
[RenderSetup] 狀態設定
通過設定RenderSetup的屬性值我們可以設定顯卡的各種狀態,設定顯卡的渲染狀態,常見的渲染狀態設定選項有:
狀態名 設定指令
Cull Back|Font|Off 設定剔除模式:剔除背面/正面/關閉
ZTest Less Greater|LEqual|GEqual|Equal|NotEqual|Always 設定深度值測試時使用的函數
ZWrite On|Off 開啟/關閉深度寫入
Blend Blend SrcFactor DstFactor 開啟並設定混合模式
使用的時候直接設定就好 例如 ZWrite On 來開啟深度寫入
[Tags] 標籤
標籤是用來告訴系統我希望如何以及什麼時候來渲染這個對象的,Tags即可以在SubShader裡面使用也可以在Pass中使用,不過兩者的類型並不一樣
SubShader的Tags類型
Queue 用來控制該物體屬於哪個渲染隊列,渲染隊列可以自訂,該標籤一般用來控制所有透明物體在不透明物體之後渲染 Tags{"Queue"= "Trans"}
RenderType 用於對著色器進行分類,例如將著色器分類為透明著色器和不透明著色器。 Tags{"RenderType"="Opaque"}
DisableBatching 用於設定是否對該SubShader使用批處理操作 Tags{"DisableBatching"= "True"}
ForceNoShadowCasting 用於控制該物體是否是否產生投影效果 Tags{"TagForceNoShadowCasting="True"}
IgnoreProjector 用於控制物體是否收到Projector的影響,通常是用於半透明物體 Tags{"IgnoreProjector"="True"}
CanUseSpriteAtlas 當該標籤是用於sprites時,需要將該標籤設定為FALSE Tags{"CanUseSpriteAtlas"="False"}
PreviewType 用於指定材質的預覽形狀,系統預設是圓形,可以更改為"skybox"之類的類型 Tags{"PreviewType"="Plane"}
Pass的Tags類型
LightMode 指定該Pass在Unity的渲染流水線中的角色 Tags{"LightMode"="ForwardBase"}
RequireOptions 指定一些值,當系統滿足指定的條件時才會渲染該Pass,它的值是一個由空格分隔的字串,目前unity支援的選項有SoftVegetation Tags{"RequireOptions"="SoftVegetation"}
Tags和RenderSetUp如果在SubShader裡面設定,那麼所有的Pass都會受到影響,如果在Pass裡面設定,那麼只會對當前的Pass產生影響
需要注意的是這兩句CGPROGRAM和ENDCG不能忘記,這兩句語句的意思是裡面的代碼都是使用的CG文法來編寫Shader,編寫Shader的文法一共有三種,一種是OPENGL的開發,使用的GLSL 文法來編寫shader,不過這類更適合手機端的開發,第二種就是DirectX的開發,使用的是HSSL文法來編寫shader,這類的文法只適用於pc端的開發,兩種文法都不能在另一平台上使用。第三種就是英偉達公司 的CG文法進行shader的開發,具有良好的跨平台性。
在SubShader裡面是不能直接使用上面定義好的屬性,在SubShader裡面,我們需要對使用的屬性進行重新定義,將屬性轉換成另一種變數,具體的轉換如下:
使用屬性的時候需要進行重新定義
Color ==> float4
Vector ==> float4
Int ==> float
Float ==> float
Range ==> float
2D ==> sampler2D
Cube ==> samplerCube
3D ==> sampler3D
需要注意的是任何使用float類型的屬性都可以用half和fixed替代,如
float ==> half ==> fixed
float4 ==> half4 ==> fixed4
區別:
float 使用32位來儲存
half 使用16位來儲存
fixed 使用11位來儲存
為了節省記憶體 選擇適當的資料類型
例如:顏色一般會使用fixed來進行儲存
fixed4 _Color;
FallBack 後備方案
fallback在shader檔案裡面是緊跟在SubShader後面的,這個語義塊的作用是當前面的SubShader沒有一個是可用的,那麼就執行這個語義塊,這個語義塊裡面一般定義是定義為:
FallBack "Diffuse" or FallBack Off
FallBack 後面的額字串裡面的內容一般是一個系統定義好的shader,這樣當前面的SubShader都不能使用的時候,就會調用系統的SubShader屬性,但是如果你使用的是FallBack Off ,那麼系統 可以理解為如果上面所有的SubShader都不能使用,那麼就不管他了,不去渲染這個物體了。
有一點需要注意的是,如果FallBack指定了系統shader,如果系統的shader定義了和我們在Properties裡面相同的屬性名稱的屬性,並使用了該屬性,就算是我們能在Inspector面板看到該屬性並調節它,但是並不會對物體的顏色產生影響。
本人是學習unity的新手一枚,如果上述文章中有任何錯誤和不正確的地方,歡迎指出。寫的不好,如果噴,請輕噴。,。