光照模型就是一个公式,使用这个公式来计算在某个点的光照效果。
标准光照模型(在标准光照模型里,我们把进入摄像机的光分为下面四个部分):
自发光
高光反射(类似镜子的反射)
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" }