漫反射: 投射在粗糙表面上的光向各个方向反射的现象。
镜面反射: 物体的反射面是光滑的,光线平行反射,如镜子,平静的水面等。
//一个漫反射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函数包含两个参数并返回二者之间最大的值。