1、Normal相关
注意:从模型空间转世界空间
v.normal = mul(unity_ObjectToWorld,v.normal);
如果当前模型等比缩放,当前公式适用,如果当前模型非等比缩放的时候,当前法线会进行一定的偏移,需要进行法线转换
转换规则:1、unity_ObjectToWorld 取逆矩阵 得到 unity_WorldToObject
2、再对矩阵进行转置,转置可通过修改参数顺序得到
将模型空间法线转换为世界空间正确公式如下:
v.normal = mul(v.normal,unity_WorldToObject);
内建函数
UnityObjectToWorldNormal(v.normal)
2、漫反射
N(世界空间)为法线,L为光向量,都是从 v.vertex 出发的向量,L 与 N夹角越小表示光照强度越强,因此漫反射光线公式
float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
diffuse = _LightColor0.rgb(光照颜色,可以替换)*saturate(dot(worldNormal,worldLight));
3、Phong
理想情况下,光源射出的光线,通过镜面反射,正好在反射光方向观察,观察者可以接受到的反射光最多,那么观察者与反射方向之间的夹角就决定了能够观察到高光的多少。夹角越大,高光越小,夹角越小,高光越大。而另一个影响高光大小的因素是表面的光滑程度,表面越光滑,高光越强,表面月粗糙,高光越弱。L代表光源方向,N代表顶点法线方向,V代表观察者方向,R代表反射光方向。首先需要计算反射光的方向R,反射光方向R可以通过入射光方向和法向量求出,R + L = 2dot(N,L)N,进而推出R = 2dot(N,L)N - L
注:L表示光源方向、I表示光源到顶点的方向,N表示法线,V表示视角方向,R表示反射方向
公式:
内建公式:reflect(I,N)
float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
float3 reflectDir = normalize(reflect(-worldLight,worldNormal ));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
//*内建方法:viewDir = WorldSpaceViewDir(v.vertex);*
计算高光值,高光值与反射光方向与观察方向的夹角有关,夹角为dot(R,V),最后根据反射系数计算的反射值为pow(dot(R,V),Gloss)
fixed3 specular = _LightColor0.rgb(光照颜色,可以替换)*pow(saturate(dot(viewDir,reflectDir)),_Gloss(衰减系数));
reflect(I,N) 推导
L+R = 2*cos(L,N)N
= 2dot(L,N)N
R = 2dot(L,N)*N-L;
可将上面reflect(I,N) 替换为当前公式
4、BlinnPhong
Blinn-Phong光照引入了一个概念,半角向量,用H表示。半角向量计算简单,通过将光源方向L和视线方向V相加后归一化即可得到半角向量。Phong光照是比较反射方向R和视线方向V之间的夹角,而Blinn-Phong改为比较半角向量H和法线方向N之间的夹角。半角向量的计算复杂程度要比计算反射光线简单得多,所以Blinn-Phong的性能要高得多,效果比Phong光照相差不多,所以OpenGL中固定管线的光照模型就是Blinn-Phong光照模型
float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
fixed3 viewDir = WorldSpaceViewDir(v.vertex);
//计算半角向量(光线方向 + 视线方向,结果归一化)
fixed3 halfDir = normalize(worldLight + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(halfDir, worldNormal)), _Gloss)
参考网站:https://blog.csdn.net/puppet_master/article/details/53428885