光照模型就是一个公式,使用这个公式来计算在某个点的光照效果。
标准光照模型(在标准光照模型里,我们把进入摄像机的光分为下面四个部分):
自发光
高光反射(类似镜子的反射)
specular = 直射光的颜色* pow(max(COS θ(反射光方向和视野方向的夹角), 0), 10);
漫反射(类似石头)
兰伯特光照模型:
Diffuse = 直射光颜色 * max(0,COS θ(光和法线的夹角))
半兰伯特光照模型:
Diffuse = 直射光颜色 * (cosθ *0.5 +0.5) θ为光和法线的夹角
环境光(均匀反射)
一些方法:
normalize() 用来把一个向量,单位化(原来的方向保持不表,长度为1)即向量的方向向量
max()用来取得函数中最大的一个
dot 用来取得两个向量的点积
_WorldSpaceLightPos0取得平行光的位置
_LightColor0取得平行光的颜色
UnityObjectToClipPos(*) 这个矩阵用来把一个坐标从模型空间转换到剪裁空间
_World2Object 这个矩阵用来把一个方向从世界空间转换到模型空间
UNITY_LIGHTMODEL_AMBIENT用来获取环境光
漫反射在顶点函数中:
Shader" Diffuse Vertex" {//漫反射
Properties{
_Diffuse("Diffuse Color",Color) = (1,1,1,1)
}
SubShader{
Pass{
CGPROGRAM
#include "Lighting.cginc"//取得第一个直射光的颜色
#pragma vertex vert
#pragma fragment frag
fixed4 _Diffuse;//每一次使用属性中的值在 CGPROGRAM中在引用一次
struct a2v {
float4 vertex: POSITION;
float3 normal :NORMAL;//模型空间下
};
struct v2f {
float4 position :SV_POSITION;
fixed3 color : COLOR;
};
v2f vert(a2v v) {
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
fixed ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//取得环境光
fixed3 normalDir = mul(v.normal, (float3x3)unity_WorldToObject);//从模型空间转换到世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//第一个直射光的位置,光的位置就是光的方向
fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, -lightDir), 0)*_Diffuse.rgb;//直射光颜色* 法线和光线的点积*自身rgb色
f.color = diffuse + ambient;//两个颜色叠加为加强,亮度增加,两个颜色融合为相乘亮度不变颜色变化
return f;
}
fixed4 frag(v2f f) :SV_Target{
return fixed4(f.color,1);
}
ENDCG
}
}
Fallback"VertexLit"
}
漫反射在片元函数中:
Shader"Diffuse Fragment" {//漫反射
Properties{
_Diffuse("Diffuse Color",Color) = (1,1,1,1)
}
SubShader{
Pass{
CGPROGRAM
#include "Lighting.cginc"//取得第一个直射光的颜色
#pragma vertex vert
#pragma fragment frag
fixed4 _Diffuse;//每一次使用属性中的值在 CGPROGRAM中在引用一次
struct a2v {
float4 vertex: POSITION;
float3 normal :NORMAL;//模型空间下
};
struct v2f {
float4 position :SV_POSITION;
fixed3 worldNormalDir : COLOR0;
};
v2f vert(a2v v) {
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
f.worldNormalDir = mul(v.normal, (float3x3)unity_WorldToObject);
return f;
}
fixed4 frag(v2f f) :SV_Target{
fixed ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//取得环境光
fixed3 normalDir = normalize(f.worldNormalDir);//从模型空间转换到世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//第一个直射光的位置,光的位置就是光的方向
fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, -lightDir), 0)*_Diffuse.rgb;//直射光颜色* 法线和光线的点积*自身rgb色
fixed3 tempColor = diffuse + ambient;
return fixed4(tempColor, 1);
}
ENDCG
}
}
Fallback"VertexLit"
}
高光反射在顶点函数中
Shader"Custom/ 08 specular vertex" {//漫反射
Properties{
_Diffuse("Diffuse Color",Color) = (1,1,1,1)
}
SubShader{
Pass{
CGPROGRAM
#include "Lighting.cginc"//取得第一个直射光的颜色
#pragma vertex vert
#pragma fragment frag
fixed4 _Diffuse;//每一次使用属性中的值在 CGPROGRAM中在引用一次
struct a2v {
float4 vertex: POSITION;
float3 normal :NORMAL;//模型空间下
};
struct v2f {
float4 position :SV_POSITION;
fixed3 color : COLOR;
};
v2f vert(a2v v) {
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
fixed ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//取得环境光
fixed3 normalDir = mul(v.normal, (float3x3)unity_WorldToObject);//从模型空间转换到世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//第一个直射光的位置,光的位置就是光的方向
fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, -lightDir), 0)*_Diffuse.rgb;//直射光颜色* 法线和光线的点积*自身rgb色
fixed3 reflectDir = normalize(reflect(lightDir, normalDir));//取到平行光方向 和法线方向 得到反射光方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(v.vertex, (float3x3)unity_WorldToObject).xyz);//相机坐标 减去 当前物体坐标点的位置 得到视野坐标向量即方向
fixed3 specular = _LightColor0.rgb * pow(max(dot(viewDir, reflectDir), 0), 10);//得到高光
f.color = diffuse + ambient+ specular;//两个颜色叠加为加强,亮度增加,两个颜色融合为相乘亮度不变颜色变化
return f;
}
fixed4 frag(v2f f) :SV_Target{
return fixed4(f.color,1);
}
ENDCG
}
}
Fallback"Diffuse"
}