unityshader中經常見到CGPROGRAM,除此之外還有一個CGINCLUDE關鍵字。 二個關鍵字都是用ENDCG來結束,但是用法完全不一樣。
CGINCLUDE和ENDCG內可以插入一些shader代碼,unity會把插入的這些代碼插入到每一個pass中。這等於我們只在CGINCLUDE和ENDCG中寫一次就可以在多個Pass里復用這些代碼。
如果多個Pass中頂點着色器和片元着色器計算的公式之類的都是一樣的,只有渲染狀態不一樣,比如透明度混合的混合參數不同等,此時我們完全可以把多個Pass里重復的頂點計算和
片元計算寫在CGINCLUDE和ENDCG內,復用這部分代碼。下面放一個示例shader:
Shader "CGINCLUDEExample" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata_shaded {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f_shaded {
float4 vertex : SV_POSITION;
float fresnelValue : TEXCOORD0;
};
v2f_shaded vert_shaded (appdata_shaded v) {
v2f_shaded o;
o.vertex = UnityObjectToClipPos(v.vertex);
float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
o.fresnelValue = lerp(0.39, 0.66, saturate(dot(v.normal, viewDir)));
return o;
}
fixed4 _Color;
fixed4 frag_shaded (v2f_shaded i) : SV_Target {
return _Color * i.fresnelValue;
}
ENDCG
SubShader {
//Pass 1 : Shaded solid
Pass {
Blend One Zero
ZWrite On
ZTest On
CGPROGRAM
#pragma vertex vert_shaded
#pragma fragment frag_shaded
ENDCG
}
//Pass 2 : Shaded transparent
Pass {
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
ZTest On
CGPROGRAM
#pragma vertex vert_shaded
#pragma fragment frag_shaded
ENDCG
}
}
}
在這個shader里,2個Pass都用了透明度混合,不過混合的參數不一樣,但是頂點計算和片元計算都一樣,所以把頂點函數vert_shaded和片元函數frag_shaded復用,寫到CGINCLUDE和ENDCG里面。
這樣就等於在Pass1和Pass2中都聲明了頂點函數vert_shaded和片元函數frag_shaded。代碼看起來簡潔許多,復用代碼也能使得我們減少手誤敲錯代碼的幾率,shader有改動時也只需改動一處即可。