包含Vertex&Fragment 的Shader叫做顶点&像素着色器,在Vertex的功能函数中,我们侧重于几何计算,如纹理坐标,顶点坐标等;在Fragment 的功能函数中,我们侧重于计算最终的颜色值,如光照后的效果等,注意这里会对像素进行平滑插值。
Shader "JQM/Test01" { Properties { ... } SubShader {
... } SubShader {
... } ... }
在第一行:Shader "JQM/Test01",声明了着色器的名字和路径;然后在它的大括号内包含一个属性和多个SubShader;
在Shader的计算中,每个Shader会根据计算机硬件系统自己的条件选择一个合适SubShader运行。每一个SubShader可以包含多个Pass通道,每一个Pass依次计算,多个Pass之间我们会采用混合技术来合理使用,这样可以制作更多的特效,在Pass中,就是具体的计算方法了,Vertex&Frag就在Pass中。
SubShader
{
Pass
{
...
}
Pass
{
...
}
...
}
在Properties作用域中,包含着一些属性,如纹理、颜色浮点值等,以下是属性类型。但是要使用这些属性值,需要在CG块中声明一次。Unity 圣典属性
Properties { _MyTexture ("Texture", 2D) = "white" {} //纹理 _MyColor ("Some Color", Color) = (1,1,1,1) //颜色 _MyVector ("Some Vector", Vector) = (0,0,0,0) //4维坐标 _MyFloat ("My float", Float) = 0.5 //浮点 _MyRange ("My Range", Range(0,1)) = 0.5 //浮点 _MyCubemap ("Cubemap", CUBE) = "" {} //立方体纹理 }
Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct VertexOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; sampler2D _MainTex; float4 _MainTex_ST; VertexOutput vert (appdata_full v) { VertexOutput o; ... return o; } fixed4 frag (VertexOutput i) : COLOR { fixed4 col = tex2D(_MainTex, i.uv); ... return col; } ENDCG }
在Pass中,CGPROGRAM...ENDCG里面,所有的功能代码,都在该区域内。在CGPROGRAM...ENDCG中,先声明顶点着色器vert和像素着色器frag,具体的计算在函数里面。然后是包含Unity的Cg头文件,一些内置变量在纹理里面。还定义了自己的结构体用于顶点着色器向像素着色器传递信息。如果要使用属性值,需要在该区域里面声明。
如下图:先通过顶点着色器,计算模型的坐标和纹理,再传入像素着色器计算颜色值。
*注意
_MainTex_ST 和 TransForm_Tex 是对应关系,计算纹理坐标的偏移和平铺。
裁剪空间的范围是[-1,1],也就是在经过MVP矩阵后,o.pos.x/ o.pos.w 以及o.pos.y/ o.pos.w 的范围都是[-1,1] 故可以将裁剪空间坐标转换为 相对屏幕位置的uv坐标,如下o.uv = float2(( o.pos.x/o.pos.w+1)*0.5,(o.pos.y/o.pos.w+1)*0.5);
源代码:
1 Shader "JQM/VertexAndFrag" //文件名和路径 2 { 3 Properties //属性 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 10 Pass 11 { 12 CGPROGRAM //Vertex&Frag 类型的shader 采用Cg语言 13 #pragma vertex vert 14 #pragma fragment frag 15 16 #include "UnityCG.cginc" 17 18 sampler2D _MainTex; //属性声明 19 float4 _MainTex_ST; 20 21 struct appdata 22 { 23 float4 vertex : POSITION; 24 float2 uv : TEXCOORD0; 25 }; 26 27 struct v2f 28 { 29 float4 pos:SV_POSITION; 30 float2 uv : TEXCOORD0; 31 }; 32 33 34 v2f vert (appdata v) //顶点程序 35 { 36 v2f o; 37 o.pos = mul(UNITY_MATRIX_MVP, v.vertex); //模型视图投影矩阵,将模型坐标转到摄像机坐标,在投影到屏幕的坐标 38 o.uv = TRANSFORM_TEX(v.uv, _MainTex); //计算UV和贴图之间的值 39 return o; 40 } 41 42 fixed4 frag (v2f i) : COLOR //片段程序,强制返回Color类型的颜色值 43 { 44 // sample the texture 45 fixed4 col = tex2D(_MainTex, i.uv); //纹理采样 46 return col; 47 } 48 ENDCG 49 } 50 } 51 }