漫反射的原理:漫反射是投射在粗糙表面上的光向各个方向反射的现象,根据入射光线与此点的法线来决定此点的反射强度,用ShaderLab书上的公式表达就是:
Lum = C * max(0,cos<L,N>)
C : 到达此点光线的强度和颜色
N : 法线
L : 单位长度(标准化)的入射光向量。
再顶点函数实现漫反射代码:
Shader "Custom/Diffuse" {
Properties
{
_Color("Color",Color) = (1,1,1,1) //控制漫反射的颜色
}
SubShader
{
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引入需要使用灯光的内置变量
#include "Lighting.cginc"
fixed4 _Color;
struct a2v
{
float4 vertex :POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
fixed3 color : COLOR;
};
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));
//将灯光归一化
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
//漫反射公式:光照颜色 * 漫反射颜色 * max(0,法向量*光照方向)
//saturate():将范围控制在0-1之间
fixed3 diffuse = _LightColor0.rgb * _Color.rgb * saturate(dot(worldNormal,worldLight));
//添加本行代码为半兰伯特模型
//diffuse = diffuse * 0.5 + 0.5;
//返回的颜色为环境光加漫反射的光
o.color = ambient + diffuse;
return o;
}
fixed4 frag(v2f i) :SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
}
Fallback "Diffuse"
}
再片元函数实现漫反射代码:
Shader "Custom/Diffuse2" {
Properties
{
_Color("_Color",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 position:SV_POSITION;
float3 color:COLOR;
};
v2f vert(a2v v)
{
v2f f;
f.position = mul(UNITY_MATRIX_MVP,v.position);
f.color = v.normal;
return f;
}
float4 frag(v2f f) :SV_Target
{
//得到世界空间下的法线
float3 normalDir = normalize(mul(f.color,(float3x3)_World2Object));
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//获得漫反射
float3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0)*_Color;
//半兰伯特模型
diffuse = diffuse * 0.5 + 0.5;
//获取环境光
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
return float4(diffuse + ambient,1);
}
ENDCG
}
}
Fallback "Diffuse"
}
效果图:
适合用在地形,岩石,墙壁等粗糙的物体上。