Shader漫反射与环境光

学习漫反射之前需要学习的知识:

知识1:
名称
标积 / 内积 / 数量积 / 点积
矢积 / 外积 / 向量积 / 叉积
运算式( a b c 粗体字,表示向量)
a·b=|a||b|·cosθ
a × b = c ,其中| c |=| a || b |·sinθ, c 的方向遵守右手定则
几何意义
向量 a 在向量 b 方向上的投影与向量 b 的模的乘积
c 是垂直a、b所在平面,且以| b |·sinθ为高、| a |为底的平行四边形的面积
运算结果的区别
标量(常用于物理)/数量(常用于数学)
矢量(常用于物理)/向量(常用于数学)
从上面的点积只是可以知道:
如果想得到2个向量的Cosθ,那么方法就是用这个2个像单位向量相乘.
单位向量的长度是1 所以 a · b =| a || b |·cosθ ==>  a · b = 1*1* cosθ
所以这个时候 a · b = cosθ

知识2:

漫反射光 Diffuse = 直射光颜色 * max( 0 , Cosθ )  (这里的Cosθ是光和法线的夹角)

max( a , b )这个函数表示取a , b 中的最大值.
因为Cosθ的取值范围是 -1~+1 如果小于0 那么这个颜色就没意义了.取到0,黑色就好了.


知识3:
dot( a , b )  表示a,b的点积  也就是上面的 a · b =| a || b |·cosθ


知识4:
mul(v.normal,unity_WorldToObject)
可以让v.normal的坐标从世界坐标转化成模型坐标.


代码如下:
Shader"Allen/04-Diffuse"{
       SubShader{
              Pass{
              Tags{"LightMode"="ForwardBase"}//设置光照模式
                     CGPROGRAM
#include   "Lighting.cginc" //这个相当于C#中的Using Unity;引入命名空间.
//可以用他来取得第一个直射光的颜色. _LightColor0
//还能取得第一个直射光的位置 _worldSpaceLightPos0
#pragma  vertex vert
#pragma  fragment frag                    
 
                      struct  a2v {
                           float4  vertex : POSITION;
                            float3  normal : NORMAL;
                     };
                      struct  a2f{
                            float4  position:SV_POSITION;
                            float3  temp:COLOR;
                     };
                     a2f  vert  (a2v v){
                           a2f f;
                           f.position=UnityObjectToClipPos(v.vertex);
                           
                           //1 得到法线的单位向量
                           fixed3 normalDir=normalize(mul(v.normal,(float3x3)unity_WorldToObject));
                           //normalize()可以得到单位长度
                           //mul()可以让他从世界坐标转到模型坐标.
                           //这里的float3x3 可以让他强制转化为三维乘以三维
                           //2 得到直射光的向量
                           fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
                           //对于每一个顶点来说光的位置就是光的方向.因为光源是平行光
                           //这个_WorldSpaceLightPos0是通过上面的标记的Tags和引入的include从系统中得到的.
                           //3 获取漫反射的颜色
                           fixed3 diffuse =_LightColor0.rgb*max(dot(normalDir,lightDir),0);
                           //_LightColor0是从上面的标记的Tags和引入的include从系统中得到的.
                           //_LightColor0.rgb 里面的rgb分别代表颜色的rgba ,a表示alpha透明的,这里不需要,所以省略
                           //dot,夹角,点乘 另外注释.
                           //4 通过参数把顶点函数的颜色返回给片元函数,让GPU进行渲染.
                           f.temp=diffuse;
                           return f;
                           
                     }
                      fixed4  frag (a2f f) : SV_Target{
                           return  fixed4 (f.temp,1);
                     }
                     ENDCG
              }
       }
       FallBack"VertexLit"
}      
如果想在漫反射上面加一个颜色.
那么久要用这个颜色和漫反射的颜色相乘.
这个时候的颜色就是有颜色并且可以漫反射.

需要下面几部:
1设置一个颜色的属性.放在Properties里面.
        Properties {
               _Diffuse ( "_Diffuse Color" ,Color)=(1,1,1,1) //定义一个颜色.
       }
2 在Pass块中在重新命名一边他.
fixed4  _Diffuse; //上面虽然定义了这个属性,但是这里用的时候还是要声明
3 让我们的返回值在返回之前和他相乘.我们只要相乘rgb就好alpha不需要.
fixed3  diffuse =_LightColor0.rgb* max ( dot (normalDir,lightDir),0)*_Diffuse.rgb;

环境光
增加环境光需要2步骤.
1 得到Unity里面的宏 UNITY_LIGHTMODE_AMBIENT 这个久能得到环境光.
在对应的顶点函数中
fixed3   ambient=UNITY_LIGHTMODEL_AMBIENT; //得到环境光
2 将返回值在返回之前于环境光相加.
f.temp=diffuse+ambient.rgb;
Shader漫反射与环境光_第1张图片
上图就是Unity中环境光的设置.


你可能感兴趣的:(Shader漫反射与环境光)