下为一个逐顶点漫反射光照shader
Shader "study/Chapter6/vertexShader"{
Properties{
_Diffuse("Diffuse",Color)=(1, 1, 1, 1)//材质的漫反射属性
//声明一个Color类型的属性 } SubShader{ Pass{ Tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag
//unity的内置文件,为了可以使用unity的一些内置变量,如后面的——LightColor0 #include "Lighting.cginc"
//匹配属性的变量,关于属性和变量的匹配,下面有 fixed4 _Diffuse; //顶点着色器输入结构体,结构体下面有 struct a2v{ float4 vertex:POSITION;//存储模型顶点 float3 normal:NORMAL; //存储模型顶点法线 }; //顶点着色器输出结构体,同时也是片元着色器输入结构体 struct v2f{ float4 pos:SV_POSITION; fixed3 color:COLOR;//将顶点着色器计算的光照颜色传递给片元着色器 }; //顶点着色器 v2f vert(a2v v){ v2f o; //将顶点从模型空间转化到裁剪空间 o.pos=UnityObjectToClipPos(v.vertex); //获取外部项,通过unity内置函数UNITY_LIGHTMODEL_AMBIENT获取环境光部分 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz; //将法线从模型空间转化到世界空间 fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject)); //光源方向,_WorldSpaceLightPos0假设场景中只有一个平行光源才能得到正确方向 fixed3 worldLight=normalize(_WorldSpaceLightPos0.xyz); //_LightColor0为unity内置变量访问该Pass处理的光源的颜色和强度信息
//下面给出漫反射计算公式 fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLight)); o.color=ambient+diffuse; return o; }
//片元着色器 fixed4 frag(v2f i):SV_TARGET{ return fixed4(i.color,1.0); } ENDCG } } //把这个unity shader的回调设置为内置的Diffuse FallBack "Diffuse" }
首先下边是Unity支持的语义
现在来看看顶点输入结构体
struct a2v{ float4 vertex:POSITION;//存储模型顶点 float3 normal:NORMAL; //存储模型顶点法线 };
这个叫a2v的结构体包含了顶点着色器需要的模型数据,a2v表示application to vertex shader,把数据从应用阶段传递到顶点着色器中
一个结构体的格式如下
struct structname{
Type(数据类型) Name(变量名):Semantic(语义);
Type(数据类型) Name(变量名):Semantic(语义);
Type(数据类型) Name(变量名):Semantic(语义);
......
};
我们一般是从顶点着色器输出一些数据比如模型的法线,坐标纹理等给片元着色器就需要通过上述代码中的v2f结构体来实现两者通信。
顶点着色器是逐顶点调用的,片元着色器是逐片元调用的。片元着色器实际上是吧顶点着色器的输出进行差值后得到的结果。
在顶点着色器中做的就是把顶点着色器输入结构体作为(上为a2v)中顶点的一些信息经过一顿操作转换为v2f(就是个函数),然后将这个v2f丢到片元着色器中再
一顿操作,然后输出一个颜色
下面是属性与变量匹配关系
比如你在properties中声明了一个2D属性,在CG中你就要声明一个sample2D变量来匹配这个2D属性,声明的属性名必须与变量名一致,
比如上面都是_Diffuse。取值范围上fixed<half<float,在移动端平台上需要注意下。
我们看到的光=环境光/自发光+漫反射+高光反射
漫反射计算公式
漫反射=(光源颜色*材质的漫反射颜色)max(0,表面法线*光源的单位矢量)
为了防止法线和光源方向点乘的结果为负值,需要使用去最大值函数
将其截取到0,以防止物体被从后面的光源照亮。
得到的材质球效果如下