创建自定义漫反射光照模型

作者:追风剑情 发布于:2015-6-27 12:59 分类:Shader

漫反射: 投射在粗糙表面上的光向各个方向反射的现象。

镜面反射: 物体的反射面是光滑的,光线平行反射,如镜子,平静的水面等。

//一个漫反射Shader
Shader "Custom/BasicDiffuse2" {
	Properties {
		_EmissiveColor ("Emissive Color", Color) = (1, 1, 1, 1)
		_AmbientColor ("Ambient Color", Color) = (1, 1, 1, 1)
		_MySliderValue ("this is a Slider", Range(0, 10)) = 2.5
		
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		//#pragma surface 表面着色函数 漫反射函数
		#pragma surface surf BasicDiffuse
		
		//在这里创建与属性同名的变量,Unity会自动将二者关联起来,它们拥有同样的数据。
		//当你在SubShader里创建好变量后,就可以在surf()函数里使用它们了。
		float4 _EmissiveColor;
		float4 _AmbientColor;
		float _MySliderValue;//镜面反射强度

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			float4 c;
			//pow()函数参阅官方在线文档
			//http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
			c = pow((_EmissiveColor + _AmbientColor), _MySliderValue);//镜面反射
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		
		//自定义漫反射函数
		//函数名的格式必须为Lighting<任何名字>
		//可以使用三种格式的光照模型函数:
		//1.该函数用于需要使用延迟着色的项目
		//half4 LightingName(SurfaceOutput s, half4 light){}
		//2.该函数用于不需要视角方向的前向着色
		//half4 LightingName(SurfaceOutput s, half3 lightDir, half atten){}
		//3.该函数用于需要视角方向的前向着色
		//half4 LightingName(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten){}
		//s : surf函数的输出
		//lightDir : 点到光源的单位向量
		//viewDir : 点到摄像机的单位向量
		//atten: 衰减系数
		//原理: 为了完成漫反射计算,需要将Unity和SurfaceOutput结构体提供给我们的数据做乘法运算。
		//为此我们需要乘上s.Albedo(来自于sur函数)和_LightColor0.rgb(来自Unity)然后再将结果与
		//(difLight*atten)相乘,最后,返回这个值作为颜色值。
		inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)
		{
			float difLight = max(0, dot(s.Normal, lightDir));//漫反射强度
			float4 col;
			col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
			col.a = s.Alpha;
			return col;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}
dot函数(dot product function)是Cg语言的另一个内置数学函数,我们可以用它来比较两个向量在空间里的方向。点积函数会检查两个向量是互相平行还是互相垂直。任意两个向量都可以通过点积函数获得-1~1的夹角范围,-1表示平行向量并背离你的方向,1也表示平等向量,不过是朝向你的方向,0表示和你垂直的方向向量。矢量点积(或内积)的归一化向量N和L是测量两个向量之间夹角的方法。两个向量之间的夹角越小,点积越大,表面可以接受的入射光也越多。

max函数:可以限制点积函数的计算结果。max函数采用两个参数max(arg1, arg2),我们在着色器里使用max函数来确保漫反射的计算结果永远介于0和尚点积最大值之间。这样你就永远不会得到小于0的值,更不会是-1,否则可能会在你的着色器区间生成极度黑色的区域,并且在之后的着色器运算过程中容易出问题。在Cg标准函数库里还有一个类似的saturate函数,可以帮助我们将浮点值限制在0~1。saturate(和max)两者唯一的区别是saturate可以直接将浮点值转换成饱和度。max函数包含两个参数并返回二者之间最大的值。

zdygzmx.png

标签: Shader

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号