1.概念
light color = emissive + ambient + diffuse + specluar
emissive:自发光
ambient:环境光
diffuse :漫反射光
specluar:镜面光
Phong模型 镜面光公式为
为求得的高光颜色值
为灯光颜色
为材质的高光反射颜色
是经验模型,需要两个变量能影响到最终值,用加、减法容易触发溢出,于是使用乘法(个人观点)
为指向视觉的方向向量
为光的反射方向与强度向量
表示将投影到,获得在方向上的分量的标量(大小),即能被摄像机看到的值。
max主要是将反面的光照剔除掉
是材质的光泽度
作为一个指数函数,由于两个向量的分量xyz[0,1],并且夹角大于0,所以得出来的数小于1,当增大时,所得的值变小,即光泽越大,高光范围越小。
2.Phong中的向量计算
图中r为反射向量,v为指向视觉的向量,n为法向量,I为指向光源的向量。一般v,n,I已知,通过已知参数可以求得r。
从单纯的向量计算的角度来说
设为入射光方向,为反射光方向向量,为 或 - 在法向量上的分量
(1)=-
(2)=2=2()
(3)=||·cosθ·= =
如果为方向向量则 =
则=+
=2+
=2()+
=2()+
=2()
即反射光
2.实现
效果:
Shader "Custom/Light/PhongSpecularLight"
{
Properties
{
_Specular ("Specular", Color)=(1,1,1,1)
_Gloss ("Gloss", Range(8.0,256))=20
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos:SV_Position;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
fixed4 _Specular;
float _Gloss;
v2f vert (appdata v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal =mul(v.normal,(float3x3)unity_WorldToObject);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldLightDir=_WorldSpaceLightPos0.xyz;
fixed3 reflectDir=normalize(reflect(-worldLightDir,i.worldNormal));
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(dot(reflectDir,viewDir),_Gloss);
return fixed4(specular,1.0);
}
ENDCG
}
}
}