一个简单的顶点片元着色器
Shader "cc/shader1"
{
Properties{
}
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};
v2f vert(a2v v){
v2f o;
//o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.pos = UnityObjectToClipPos(v,vertex); //与上面等价
o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}
fixed4 frag(v2f i):SV_Target{
return fixed4(i.color, 1.0)
}
ENDCG
}
}
}
顶点/片元着色器的结构
语义块
从上面的代码可以看出,顶点片元着色器的构成包含了Shader、Properties、SubShader、Pass、Fallback 等语义
Shader: 定义了这个Shader的名称,并且包含了整个Shader所有的语义
Properties: 属性语义块,用于外部调整材质的一些参数,值得注意的是,属性在Properties中声明,在Pass语义块中使用需要定义相同的属性相匹配
SubShader: 一个Shader包含多个SubShader,但是Unity每次只会选择一个最优的SubShader执行渲染,SubShader可以定义Tag进行渲染设置,如:RenderType(渲染类型)、Rendering Order(渲染顺序),一个SubShader包含多个Pass,执行SubShader会把定义的Pass全部渲染一遍
Pass: 一次物体的几何学渲染,包含了顶点/片元着色器函数和一些渲染标签设置
Fallback: 如果所有的SubShader都不能执行,则执行FallBack指定的shader
顶点/片元着色器的通信
1. 指定顶点/片元着色器函数
顶点/片元着色器函数被包含在Pass中,Pass中CGPROGRAM…ENDCG表示包围的是一段CG代码,以下两行编译指令:
#pragma vertex vert
#pragma fragment frag
分别指定了顶点着色器函数vert和片元着色器函数frag,不一定是vert和frag,也可以指定其他名称
2. 语义
Unity定义了一些语义用来输入或者输出的一些数据,程序可以自己定义自己需要的数据结构体,Unity会根据这些语义去填充对应的数据。
a2v: 表示应用阶段(application) 到 顶点着色器(vert)
v2f: 表示顶点着色器 到 片云着色器
常见的语义如下:
I.从应用阶段到顶点着色器的常用语义
语 义 | 描 述 |
---|---|
POSITION | 模型空间中的顶点坐标,通常是float4类型 |
NORMAL | 顶点法线,通常是float3类型 |
TANGENT | 顶点切线,通常是float4类型 |
TEXCOORD0 | 该顶点的纹理坐标 |
COLOR | 顶点颜色,通常是fixed4或float4类型 |
II.从顶点着色器到片元着色器的常用语义
语 义 | 描 述 |
---|---|
SV_POSITION | 剪裁空间中的顶点坐标 |
COLOR0 | 用于顶点到片元的输出的顶点颜色 |
TEXCOORD0 | 该顶点输出的纹理坐标 |
III.从片元着色器到Unity使用的常用语义
语 义 | 描 述 |
---|---|
SV_Target | 片元着色器的输出值,将会存储到渲染目标中 |
Unity内置文件UnityCg.cginc中包含了一些常用的结构体:
名 称 | 描 述 | 包含的变量 |
---|---|---|
appdata_base | 可用于顶点着色器的输入 | 顶点位置、顶点法线、第一组纹理坐标 |
appdata_tan | 可用于顶点着色器的输入 | 顶点位置、顶点切线、顶点法线、第一组纹理坐标 |
appdata_full | 可用于顶点着色器的输入 | 顶点位置、顶点切线、顶点法线、四组(或更多)纹理坐标 |
appdata_img | 可用于顶点着色器的输入 | 顶点位置、第一组纹理坐标 |
v2f_img | 可用于顶点着色器的输出 | 裁剪空间中的位置、纹理坐标 |
3. 将顶点坐标从模型空间转化到剪裁空间
UNITY_MATRIX_MVP: Unity内置的模型观察矩阵(包含在内置文件UnityCg.cginc中)
使用mul(UNITY_MATRIX_MVP, v.vertex) 函数进行矩阵相乘得到剪裁空间坐标
Unity5.6之后使用UnityObjectToClipPos(v.vertex) 函数代替这个矩阵相乘的运算