Unity-Shader-SubShader CG代码块
系统函数
由系统调用,与Unity生命周期中的Start(),UpDate函数类似
1、简介
顶点函数,将顶点在模型空间的坐标转换为屏幕坐标(模型坐标转剪裁空间)
片元函数:对每一片元(像素)计算其颜色
SubShader{pass{ CGPROGRAM
//函数声明
#program vertex vert
#program fragment frag函数定义xxx vert(xxx){}xxx frag(xxx){}ENDCG}}FallBack "Diffuse"
需要先声明函数,再定义函数
声明函数
#program+函数类型名,自定义的函数名
vertex:顶点函数
fragment:片元函数
#program vertex vert
定义函数
这两个函数均有返回值和传入参数,返回值在函数名前,参数在函数名后的括号内
返回值 vert(参数)
{
}
2、具体介绍
顶点函数
示例为将模型空间转换为剪裁空间的简单操作(MVP变换)
语义说明:传入的参数v通过 : POSITION告知系统将模型坐标传入v,函数通过:SV_POSITION告知系统函数的返回值为裁剪空间下的顶点坐标
float4 vert(float4 v : POSITION) :SV_POSITION
{return mul(UNITY_MATRIX_MVP,v);
}
mul自带方法:矩阵相乘
UNITY_MATRIX_MVP:宏定义的MVP的变换矩阵
为了方便起见,一般会把传入的参数与输出的值做成两个结构体分别储存
//application to vertex
struct a2v{float4 vertex :POSITION;//模型空间下的顶点的位置float3 normal :NORMAL; //模型空间下的法线向量float4 texcoord :TEXCOORD0; // 纹理坐标
}//vertex to fragment
struct v2f{float4 position :SV_POSITION;
}
!注意:如果要把输出的值集合成一个结构体的话,结构体的成员变量必须是带有语义的类型
上述顶点函数就可以改成
v2f vert(a2v v)
{v2f f;f.position = mul(UNITY_MATRIX_MVP,v.normal);return f;
}
片元函数
示例为将模型的每个片元的颜色设置为白色
语义说明:函数通过:SV_Target告知系统函数的返回值为每个片元的颜色值
fixed4 frag() :SV_Target
{return fixed4(1,1,1,1);
}
可以利用fixed4 节约空间,fixed 类型值范围为-2~2.
3、顶点函数与片元函数的通信
如果想把顶点函数中所用到的参数(例如normal),或者是计算出来的值用在frag函数中,我们可以利用之前构建的结构体。在顶点函数中给结构体的成员变量赋值,再将结构体传入片元函数中。
下面是传输法线(normal)的示例:
先在v2f结构体中增加成员变量
struct v2f{float4 position :SV_POSITION;float3 temp : COLOR0;
}
因为v2f作为顶点函数的返回值,其成员变量必须带有语义。这里我们先用COLOR0作为语义
在顶点函数中赋值
v2f vert(a2v v)
{v2f f;f.position = mul(UNITY_MATRIX_MVP,v,normal);f.temp = v.normalreturn f;
}
在片元函数中调用:
fixed4 frag(v2f f) :SV_Target
{return fixed4(f.temp,1);
}
因为顶点数量与片元数量并不一致(一般是片元数大于顶点数),所以片元函数的返回值会是根据顶点自动插值后的结果。
为什么两个不同的v2f可以传递数据:事实上需要传递的数据通过语义存在了系统里,我们只是通过v2f调用存储在系统中的数据。