- A+
 
所属分类:UnityShader 原创文章
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53  | 
						Shader "chicai/diffuse" { 	Properties{ 		_Diffuse("Diffuse",Color) = (1,1,1,1) 	} 	SubShader{//子着色器 		Pass{//通道 			Tags{ "LightMode"="ForwardBase" } 			CGPROGRAM 			#include "Lighting.cginc" //包含了一些光照的宏 			fixed4 _Diffuse;//假装是物体的自身颜色 			struct a2v{ 				float4 v:POSITION; 				float3 nor:NORMAL; 			}; 			struct v2f{ 				float4 position:SV_POSITION; 				float3 col:COLOR0; 			}; 			#pragma vertex vert 			#pragma fragment frag 			v2f vert(a2v v){ 				v2f f; 				f.position = UnityObjectToClipPos(v.v); 				//计算光颜色 				fixed3 norDir = normalize((fixed3) mul(unity_ObjectToWorld,float4(v.nor,0))); 				fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz ); 					fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//环境光 				float rate = dot(norDir,lightDir) * 0.5 + 0.5;  //半兰伯特计算公式 				f.col = _LightColor0.rgb  * rate * _Diffuse + ambient; 				return f; 			} 			fixed4 frag(v2f f):SV_Target{ 				return fixed4(f.col,1); 			} 			ENDCG 		} 	} }  | 
					
一、来解析一下这一堆代码吧!首先,看前面一段,属性的声明,_Diffuse-属性("显示的名称",Color(类型)) = (1,1,1,1)
| 
					 1 2 3  | 
						Properties{ 	_Diffuse("Diffuse",Color) = (1,1,1,1) }  | 
					
二、两个结构体
| 
					 1 2 3 4 5 6 7 8 9  | 
						struct a2v{ 	float4 v:POSITION; 	float3 nor:NORMAL; }; struct v2f{ 	float4 position:SV_POSITION; 	float3 col:COLOR0; };  | 
					
a2v表示 application to vertex,表示是应用传进来给顶点函数的,v2f表示vertex to fragment,表示的是顶点函数传递给片元函数,里面属性加:后面的是语义,POSITION表示顶点,NORMAL表示法线,都是模型空间的,SV_POSITION表示传入给片元函数的顶点数据,COLOR0就是颜色的意思
三、声明顶点处理函数和片元处理函数
| 
					 1 2  | 
						#pragma vertex vert #pragma fragment frag  | 
					
四、顶点函数
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | 
						v2f vert(a2v v){ 	v2f f; 	f.position = UnityObjectToClipPos(v.v); 	//计算光颜色 	fixed3 norDir = normalize((fixed3) mul(unity_ObjectToWorld,float4(v.nor,0))); 	fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz ); 	fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//环境光 	float rate = dot(norDir,lightDir) * 0.5 + 0.5;  //半兰伯特计算公式 	f.col = _LightColor0.rgb  * rate * _Diffuse + ambient; 	return f; }  | 
					
传入a2v结构数据,在里面构造出v2f数据,UnityObjectToClipPos(模型顶点) 转化模型空间的点到剪裁空间,unity_ObjectToWorld 模型空间到世界空间的转换矩阵,_WorldSpaceLightPos0 世界空间下的光线方向,半兰伯特计算公式,dot() 点乘范围=cos()[-1,1],*0.5后[-0.5,0.5],再+0.5=[0,1],刚好是0-1之间,受光照的强度,颜色相乘表示融合,颜色相加表示加强
五、片元函数
| 
					 1 2 3  | 
						fixed4 frag(v2f f):SV_Target{ 	return fixed4(f.col,1); }  | 
					
SV_Target语义表示 返回的颜色
六、兰伯特的计算公式
| 
					 1 2  | 
						float rate = max(dot(norDir,lightDir),0); f.col = _LightColor0.rgb  * rate * _Diffuse + ambient;  | 
					
缺点就是,小于0的,就是[-1-0]区间的都是0,这样就会黑乎乎一片
兰伯特和半兰伯特效果对比
左边是兰伯特(黑乎乎的),右边半兰伯特
