代碼結(jié)構(gòu)
SubShader 會(huì)一次執(zhí)行,上面的執(zhí)行不了就執(zhí)行下面,這個(gè)可以用來(lái)實(shí)現(xiàn)對(duì)應(yīng)不同硬件性能的代碼。
Shader Name
Shader “Custom/Myshader” //“Custom/Myshader”是在unity中找到該shader的路徑
{
}
Shader Properties
//決定哪些參數(shù)在shader Inspector中顯示
//_Name("Display Name",type)=defualtValue[{options}]
Shader "Custom/MyShader"
{
Properties
{
_Int("myInt",Int) = 5
_Float("myFloat",Float) = 2.5
_Range("myRange",Range(1.5,5.5)) = 2.0
_Color("myColor",Color") = (1,1,1,1)
_Vector("myVector,"Vecor) = ( 3,5,8,2)
_2D("myTexture",2D) = "White" {}
_Cube(myCube",Cube) = "" {}
_3D("my3DTexture",3D) = "" {}
}
...
}
Shader SubShader Tags
Reference:https://docs.unity3d.com/Manual/SL-SubShaderTags.html
Tags中Queue的細(xì)分
Queue的順序可以使用加減值來(lái)指定特定的值
Shader SubShader LOD
可以用程序設(shè)置單個(gè)shader的最大LOD和全局最大LOD,若設(shè)定的值大于最大LOD,則該shader不會(huì)被執(zhí)行
Reference:https://docs.unity3d.com/Manual/SL-ShaderLOD.html
RenderSetup
Cull:背對(duì)攝影機(jī)剔除之類的。預(yù)設(shè)是Back
ZTest:深度測(cè)試,預(yù)設(shè)值是LEqual
Zwrite:深度比較
Bledn:輸出顏色和畫面顏色混合
Path
UsePass:重用其他shader中的pass
GrapPass:抓取目前畫面的渲染結(jié)果,存到texture
每個(gè)Path相當(dāng)于做一次渲染
完整Shader代碼例子
使用shader在模型外畫出邊框
基本思路是使用兩個(gè)path,一個(gè)path照常渲染模型,一個(gè)path把模型渲染成固定顏色,并適當(dāng)擴(kuò)大,然后RenderSetup設(shè)置為Cull Front
Shader "Custom/BasicShaer-outline"
{
Properties
{
_Texture("Texture",2D) = "White"{}
_OutlineColor("OutLineColor",Color) = (0,0,1,1)
_Scale("Scale",Range(0,0.05)) = 0.02
}
SubShader
{
Tags{ "Queue" = "Geometry" "RenderType" = "Opaque" }
LOD 100
Pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _OutlineColor;
fixed _Scale;
struct appdata {
fixed4 vertex : POSITION;
fixed4 normal : NORMAL;
};
struct v2f {
fixed4 vertex : SV_POSITION;
};
v2f vert(appdata v)
{
v2f o;
v.vertex.xyz += v.normal*_Scale;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
/////
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _Texture;
struct appdata {
fixed4 vertex : POSITION;
fixed2 uv : TEXCOORD0;
};
struct v2f {
fixed4 vertex : SV_POSITION;
fixed2 uv : TEXCOORD0;
};
v2f vert(appdata i)
{
v2f o;
o.uv = i.uv;
o.vertex = UnityObjectToClipPos(i.vertex);
return o;
}
fixed4 frag(v2f v) : SV_Target
{
return tex2D(_Texture,v.uv);
}
ENDCG
}
}
}
Path內(nèi)部結(jié)構(gòu)解析
#pragma vertex vert
#pragma fragment frag
這兩句用來(lái)指定定點(diǎn)著色器和片段著色器的執(zhí)行函數(shù)名稱,這里我們命名為vert和frag
fixed4 _OutlineColor;
fixed _Scale;
這兩句指明用戶定義的變量,Properties中已經(jīng)從editor拿到了用戶定義的變量,現(xiàn)在需要把它轉(zhuǎn)換成Shader能識(shí)別的類型,所以需要重新聲明一次。
除了用戶自定義的變量之外,還有一些Unity內(nèi)置的Global變量,你可以不聲明他們直接使用,例如_WorldSpaceCameraPos代表相機(jī)世界坐標(biāo),unity_ObjectToWorld代表當(dāng)先的Model矩陣,_WorldSpaceLightPos0當(dāng)xyzw中的w為0時(shí)代表平行光方向,為1時(shí)代表點(diǎn)光源位置等等。
更多的內(nèi)置變量可以參考這里
CGPROGEAM
ENDCG
這一對(duì)宏用來(lái)告訴Unity現(xiàn)在開始使用CG語(yǔ)法,而不是shaderlab
struct appdata {
fixed4 vertex : POSITION;
fixed4 normal : NORMAL;
};
struct v2f {
fixed4 vertex : SV_POSITION;
};
定義頂點(diǎn)著色器函數(shù)的輸入?yún)?shù),以及片段著色器函數(shù)的輸入?yún)?shù)(即定點(diǎn)著色器函數(shù)的輸出)注意:POSITION,:NORMAL以及:SV_POSITION被稱為語(yǔ)義(semantics)他們代表一些固定的值,例如POSITION代表頂點(diǎn)的物體坐標(biāo)系坐標(biāo),NORMAL代表頂點(diǎn)法向量,SV_POSITION代表頂點(diǎn)的像素坐標(biāo)
更多的語(yǔ)義可以參考這里
o.vertex = UnityObjectToClipPos(v.vertex);
使用MVP矩陣把定點(diǎn)從物體坐標(biāo)系轉(zhuǎn)換到Clip Space(視錐體空間)
使用shader縮放部分模型并改變顏色
Shader "Custom/BasicShader_Normal"
{
Properties
{
_Texture("Texture",2D) = "White"{}
_Color("Color",Color) = (1,1,1,1)
_Pos("Pos",Range(-1,1)) = -0.3
_Range("Range",Range(0,2)) = 0.2
_Scale("Scale",Range(0,0.5)) = 0.2
}
SubShader
{
Tags{ "Queue" = "Geometry" "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _Texture;
fixed4 _Color;
fixed _Pos;
fixed _Range;
fixed _Scale;
struct appdata {
fixed4 vertex : POSITION;
fixed2 uv : TEXCOORD0;
fixed4 normal : NORMAL;
};
struct v2f {
fixed4 vertex : SV_POSITION;
fixed2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
v2f vert(appdata i)
{
v2f o;
o.uv = i.uv;
if (i.vertex.y <= _Pos && i.vertex.y >= _Pos - _Range)
{
o.color = _Color;
i.vertex.xyz += i.normal*_Scale;
}
else
{
o.color = fixed4(1, 1, 1, 1);
}
o.vertex = UnityObjectToClipPos(i.vertex);
return o;
}
fixed4 frag(v2f v) : SV_Target
{
return tex2D(_Texture,v.uv) * v.color;
}
ENDCG
}
}
}