####漫反射(diffuse)
当光线从光源照射到模型表面,该表面回向每一个方向散射多少辐射量
漫反射符合兰伯特定律:反射光线的强度与表面法线与光源方向之间的夹角的余弦值成正比.
漫反射的计算:
n表面法线和l指向光源的向量的单位向量点乘来表示余弦值,用max防止点乘结果为负数,防止物体被从后面来的光源照亮.
由公式可知,计算漫反射的结果须要四个参数:
1.入射光线颜色和强度
2.材质的漫反射系数
3.表面法线
4.光源方向
在cg中咱们使用saturate函数来事先max的操做web
逐顶点光照:也被称为高落德着色,在每一个顶点计算光照,在渲染图元内部进行插值.光照模型中出现非线性的计算时,会出现问题.
逐像素光照:Phong着色,在片面之间对顶点法线进行插值.svg
###漫反射的逐顶点光照的实现:函数
Properties{ _Diffuse("Diffuse",Color) = (1,1,1,1) }
在Properties中声明一个color用来获得材质的漫反射材质3d
SubShader{ Pass{ Tags{"LightMode" = "ForwardBase"}
LightMode是一种Pass标签,用来定义该Pass在Unity流水线中的角色code
CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc"
导入Unity的内置文件Lighting.cginc,使用Unity内置变量须要
为了在Shader中使用Properties的属性,须要定义一个和该属性类型相匹配的变量orm
fixed4 _Diffuse;
两个结构体xml
struct a2v { float4 vertex : POSITION; float4 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; fixed3 color : COLOR; };
在顶点着色器中计算漫反射部分blog
v2f vert(a2v v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP,v.vertex); fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject)); float3 worldLight = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0 * _Diffuse.rgb * saturate(dot(worldLight,worldNormal)); o.color = diffuse + ambient; return o; }
1.基本任务将模型顶点从模型空间转换到裁剪空间.
2.经过Unity内置变量获取环境光部分
3.法线变换,将法线与变换矩阵的逆转置的矩阵进行矩阵乘法,获得正确的变换后的法线(在世界坐标下),这里法线是一个三维矢量,变换矩阵只需截取3x3便可
4.直接使用_WorldSpaceLightPos()获得平行光
5.经过上面的公式计算获得diffuse
6.将获得的颜色信息在frag中进行输出get
###逐像素光照
对Shader进行一些修改来实现逐像素的漫反射效果,代码改变部分it
struct v2f { float4 pos : SV_POSITION; fixed3 worldNormal : TEXCOORD0; }; v2f vert(a2v v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP,v.vertex); o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject); return o; } fixed4 frag(v2f i) : SV_Target{ fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldNormal = normalize(i.worldNormal); float3 worldLight = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0 * _Diffuse.rgb * saturate(dot(worldLight, worldNormal)); fixed3 color = diffuse + ambient; return fixed4(color, 1.0); }
咱们将每次的计算放在fragment中进行,获得的结果更加平滑.可是即便咱们加入了环境光,仍然没法解决背光面明暗同样的状况,为了改善这种状况,咱们使用下面的光照模型
###半兰伯特模型
咱们对点乘结果进行α倍数的缩放在加上β的偏移,大多数状况下两个值为0.5
这样咱们将[-1,1]映射到[0,1],在此模型下背光面也有明暗变化,此模型没有物理依据,仅做为视觉加强的效果.
背面效果图: