学习漫反射之前需要学习的知识:
知识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;
上图就是Unity中环境光的设置.