1、最简单的顶点/片元着色器
1.1 顶点/片元的基本结构
包含Shader、Properties、SubShader、Fallback等语义块
Shader "MyShaderName"{
Properties{
//属性
}
SubShader{
//针对显卡A的SubShader
Pass{
//设置渲染状态和标签
//开始CG代码片段
CGPROGRAM
//该代码片段的编译指令
#pragma vertex vert
#pragma fragment frag
//CG代码写在这里
ENDCG
//其他设置
}
//其他需要的Pass
}
SubShader{
//针对显卡B的SubShader
}
//上述SubShader都失败后用于回调的Unity Shader
Fallback "VertexLit"
}
最重要的是Pass语义块
Shader "Unity Shaders Book/Chapter5/SimpleShader" {
SubShader{
Pass{
CGPROGRAM
//以下两条告诉Unity哪个函数包含顶点着色器代码,哪个函数包含片元着色器代码
//#pragma vertex name
//#pragma fragment name
#pragma vertex vert
#pragma fragment frag
//v包含顶点位置,通过POSITION语义定义,返回值float4,POSITION和SV_POSITION均为
//CG/HLSL语义。如POSTION告诉Unity将模型顶点坐标填充到参数v中,SV_POSITION告诉
//Unity顶点着色器的输出是裁剪空间的顶点坐标
float4 vert(float4 v:POSITION) : SV_POSITION{
return UnityObjectToClipPos (v);
}
//SV_Target是HLSL的语义,告诉渲染器用户的输出颜色存储到一个渲染目标中,这里输出到
//默认的帧缓存中,返回一个表示白色的fixed4类型。
fixed4 frag() : SV_TARGET{
return fixed4(1.0,1.0,1.0,1.0);
}
ENDCG
}
}
}
1.2 模型数据来源
上面例子中POSITION得到了模型顶点位置,当需要模型上每个顶点的纹理坐标和法线方向时。纹理坐标访问纹理,法线用于计算光照。这次新的参数将为一个结构体。
Shader "Unity Shaders Book/Chapter5/SimpleShader" {
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//使用结构体来定义顶点着色器的输入
struct a2v{
//POSITION告诉Unity,用模型空间顶点坐标填充vertex变量
float4 vertex : POSITION;
//NORMAL告诉Unity,用模型空间的法线方向填充normal变量
float3 normal : NORMAL;
//TEXCOORD0语义告诉Unity,用模型的第一套纹理坐标填充texcoord变量
float4 texcoord : TEXCOORD0;
};
float4 vert(a2v v) : SV_POSITION{
//使用v.vertex访问模型空间顶点坐标
return UnityObjectToClipPos (v.vertex);
}
fixed4 frag() : SV_TARGET{
return fixed4(1.0,1.0,1.0,1.0);
}
ENDCG
}
}
}
对于顶点着色器的输出,语义有:POSITION、TANGENT、NORMAL、TEXCOORD0、TEXCOORD1、TEXCOORD2、TEXCOORD3、COLOR,在Unity中由使用该材质的Mesh Render组建提供,在每帧Draw Call调用时发送。
1.3 顶点着色器和片元着色器之间如何通信
Shader "Unity Shaders Book/Chapter5/SimpleShader" {
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
//结构体定义顶点着色器输出
st