最简单的Shader:
Shader "Chan/Shader_5_All" {
Properties
{
//面板定义属性
_Color("Color Tint",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
//定义了顶点着色器函数
//pragma vertex name 一般顶点着色器函数名用vert
#pragma vertex vert
//定义了片元着色器函数
//pragma vertex name 一般顶点着色器函数名用frag
#pragma fragment frag
//在CG代码中,定义一个属性名称和类型都匹配的变量
fixed4 _Color;
//1.为了访问模型数据,定义一个数据结构,然后用语义告诉系统,每个值需要用什么数据填充
//2.这个数据结构作为顶点着色器的输入(下边的a2v v)
//3.语义中的数据由使用了该材质的Mesh Render提供 每帧调用Draw Call时候,Mesh Render会把需要渲染的模型数据发送给Shader
struct a2v
{
//语义获取模型空间下的顶点
float4 vertex:POSITION;
//语义获取模型空间下的法线
float3 normal:NORMAL;
//语义获取模型的第一套纹理坐标
float4 texcoord:TEXCOORD0;
};
//定义一个数据结构,用于从顶点着色器传数据给片元着色器
struct v2f
{
//1.通过语义,知道pos是裁剪空间下的顶点坐标数据
//2.必须有SV_POSITION,否则片元着色器得不到顶点坐标,无法渲染
float4 pos:SV_POSITION;
//通过语义,知道color变量用于存储颜色信息
float3 color:COLOR0;
};
//顶点着色器函数名
v2f vert(a2v v)
{
//申明结构(顶点着色器像片元着色器传递数据的数据结构)
v2f o;
//Shader内置函数 将顶点坐标从模型空间变换到裁剪空间下
o.pos = UnityObjectToClipPos(v.vertex);
//随便计算一个颜色值,赋值给color
o.color = v.normal * fixed3(0.5,0.5,0.5);
//返回赋值后数据结构,供片元着色器使用
return o;
}
//片元着色器函数名
//SV_Target告诉渲染器,把用户输出的颜色存储到渲染目标中,这里将输出到默认的帧缓存中
fixed4 frag(v2f i):SV_Target
{
fixed3 c = i.color;
c *= _Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
Unity内置包含文件:
路径 = Unity安装路劲下的CGIncludes文件夹下。
.cginc文件中定义了一些常用变量和帮助函数。使用#include指令可包含文件,方便使用。
常用包含文件:
文件名 | 描述 |
UnityCG.cginc | 包含了最常用的帮助函数,宏和结构体等 |
UnityShaderVariables.cginc |
在编译Unity_Shader时,会被自动包含进来,包含了许多内置的全局变量,如 UNITY_MATIRX_MVP等 |
Lighting.cginc | 包含了各种内置的光照模型,如果编写的是Surface Shader,会自动包含进来 |
HLSLSupport.cginc | 在编译Unity Shader时,会被自动包含进来,声明了很多用于跨平台编译的宏和定义 |
UnityCG.cginc中常用的结构体
名称 | 描述 | 包含的变量 |
appdata_base | 可用于顶点着色器的输入 | 顶点位置,顶点法线,第一组纹理坐标 |
appdata_tan | 可用于顶点着色器的输入 | 顶点位置,顶点切线,顶点法线,第一组纹理坐标 |
appdata_full | 可用于顶点着色器的输入 | 顶点位置,顶点切线,顶点法线,四组(或更多)纹理坐标 |
appdata_img | 可用于顶点着色器的输入 | 顶点位置,第一组纹理坐标 |
v2f_img | 可用于顶点着色器的输出 | 裁剪空间中的位置,纹理坐标 |
UnityCG.cginc中常用的帮助函数
函数名 | 描述 |
float3 WorldSpaceViewDir(float4 v) | 输入模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向 |
float3 ObjectSpaceViewDir(float4 v) | 输入模型空间中的顶点位置,返回模型空间中从该点到摄像机的观察方向 |
float3 WorldSpaceLightDir(float4 v) | 仅可用于前向渲染中,输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向,没有被归一化 |
float3 ObjSpaceLightDir(float4 v) | 仅可用于前向渲染中,输入一个模型空间中的顶点位置,返回模型空间中从该点到光源的光照方向,没有被归一化 |
float3 UnityObjectToWorldNormal(float3 norm) | 把法线方向从模型空间转换到世界空间中 |
float3 UnityObjectToWorldDir(in float3 dir) | 把方向矢量从模型空间变换到世界空间中 |
float3 UnityWorldToObjectDir(float3 dir) | 把方向矢量从世界空间变换到模型空间中 |
CG/HLSL提供的语义:
这些语义告诉Shader该怎么读取数据,并把数据输出到哪。同一个语义在不同的着色器中,含义不尽相同。
例如:在传递给顶点着色器的结构体中TEXCOORD0来描述texcoord,Unity会识别TEXCOORD0语义,以把模型的第一组纹理坐标填充到texcoord中。如果在顶点着色器传递给片元着色器的数据结构体中TEXCOORD0修饰的变量由我们随便赋值。
DirectX10以后,有了SV开头的系统数值语义(system value)。SV开头的语义修饰的变量不能随便赋值,因为渲染流水线需要用它们完成特定的目的。
应用阶段传递模型数据给顶点着色器时,Unity内部赋予某些语义特殊含义:
语义 | 描述 |
POSITION | 模型空间中的顶点位置,通常是float4类型 |
NORMAL | 顶点法线,通常是float3类型 |
TANGENT | 顶点切线,通常是float4类型 |
TEXCOORDn,如TEXCOORD0,TEXCOORD1 | 该顶点的纹理坐标,TEXCOORD0表示第一组纹理坐标,以此类推,通常是float2或float4类型 |
COLOR | 顶点颜色,通常是fixed4 或 float4类型 |
从顶点着色器传递模型数据给片元着色器时,Unity支持的语义
语义 | 描述 |
SV_POSITION | 齐次裁剪空间中的顶点坐标,结构体中必须要包含一个用于该语义修饰的变量,等同于DirectX9中的POSITION,但最好使用SV_POSITION(为了通用性) |
COLOR0 | 通常用于输出第一组顶点颜色,但不是必需的 |
COLOR1 | 通常用于输出第二组顶点颜色,但不是必需的 |
TEXCOORD0~TEXCOORD7 | 通常用于输出纹理坐标,但不是必需的 |
除了SV_POSITION,其他都可以任意赋值,比如需要把自定义数据从顶点着色器传递给片元着色器,一般选用TEXCOORD0.
片元着色器输出时,Unity支持的常用语义
语义 | 描述 |
SV_Target | 输出值将会存储到渲染目标中(render target),等同于DirectX 9中的COLOR语义,但最好使用SV_Target |